Konvertieren von Primärschlüsseln in gruppierte Primärschlüssel für eine große Anzahl von Tabellen unter Beibehaltung der referenziellen Identität

7

Nachdem ich festgestellt habe, dass ich die Primärschlüssel besser von nicht geclustert in geclustert ändere. Bei dieser Frage zu Clustered-Indizes für Identitätsspalten besteht der nächste Schritt darin, dies auf praktische Weise zu tun.

Ich war überrascht, dass ich diese Frage auf SO nicht gefunden habe.

Referenzreferenzen zwischen meinen Tabellen zu haben, kann ich nicht einfach tun

if object_id('MyChild') > 0 drop table MyChild
if object_id('Mytable') > 0 drop table Mytable
create table Mytable(
    id int Not NULL
)
go
create table MyChild(
    id int Not NULL,
    masterid int NULL
)
go
alter table Mytable add constraint PK_Mytable primary key  (id)
alter table MyChild add constraint FK_MyChild_MyTable foreign key (masterid) references Mytable(id)
go
-- Now I want to change the primary key into a clustered primary key
-- this throws an error
ALTER TABLE Mytable DROP CONSTRAINT PK_Mytable
GO
ALTER TABLE Mytable ADD CONSTRAINT PK_Mytable  PRIMARY KEY CLUSTERED (id)
GO

Hier bekomme ich folgenden Fehler

Msg 3725, Level 16, State 0, Line 1
Auf die 'PK_Mytable'-Einschränkung wird von der 'MyChild'-Tabelle, FOREIGN KEY-Einschränkung 'FK_MyChild_MyTable' verwiesen.
Msg 3727, Level 16, State 0, Line 1
Die Einschränkung konnte nicht gelöscht werden. Siehe vorherige Fehler.

OK Ich weiß, dass es funktioniert, wenn ich die Fremdschlüsseleinschränkung vor der Änderung lösche und sie danach wieder einrichte.

alter table MyChild drop constraint FK_MyChild_MyTable
go
ALTER TABLE Mytable DROP CONSTRAINT PK_Mytable
GO
ALTER TABLE Mytable ADD CONSTRAINT PK_Mytable  PRIMARY KEY CLUSTERED (id)
GO
alter table MyChild add constraint FK_MyChild_MyTable foreign key (masterid) references Mytable(id)
go

Das klingt so, als müsste ich alle Fremdschlüsselbeziehungen aus der Datenbank skripten, löschen, meine Primärschlüsseländerungen vornehmen und die Fremdschlüssel aus dem generierten Skript wiederherstellen.

Gibt es bessere Möglichkeiten für diese Aufgabe?

Übrigens. Schließlich möchten wir dies in Produktionsdatenbanken tun. (Ausfallzeiten sind zulässig). Alle Datenbanken sind SQL Server 2005 oder SQL Server 2008.

Bearbeiten:

Ein Mitarbeiter schlug vor, alle Indizes vor diesem Vorgang zu löschen und anschließend neu zu erstellen. Klingt für mich vernünftig.

2. Bearbeiten:

Wenn ich mir diese Frage zu dba.stackexchange anschaue , frage ich mich, ob es ausreichen würde, nur Clustered-Indizes zu den Primärschlüsselspalten der Tabellen hinzuzufügen.

bernd_k
quelle

Antworten:

6

Ihr Ansatz ist korrekt und so ziemlich der einzige Weg, aber ich würde in Betracht ziehen, ein Tool wie Red Gate zu verwenden, um mir zu helfen.

  • fallen alle FKs ohne sie scripting
  • Ändern Sie die Indizes (wie oben)
  • Generieren Sie ein "Nur FK" -Skript mit dem Vergleichstool, um die FKs erneut anzuwenden

Der dritte Schritt erspart das Schreiben von Skripten für Ihre FK-Definitionen oder das Fummeln mit SSMS / SMO

gbn
quelle
Hhm. Ich denke, ich schreibe schneller ein PowerShell-Skript mit SMO, um alle Fremdschlüssel zu skriptieren, als um Red Gate-Tools zu installieren. Übrigens denke ich, es wäre besser, die FKs zu schreiben, bevor man sie fallen lässt. Ich denke, das erwähnte Tool benötigt eine Verbindung zur Datenbank und kann trotz des Namensvergleichstools die FK aus dieser angegebenen Datenbank skripten?
Bernd_k
Ja. Es wird ein Skript mit den Unterschieden generiert (Sie können einige ignorieren). Es gibt andere Tools wie dbghost, die ebenfalls kostenlos sind.
Gbn
Ich habe nach T-SQL-Skripten gesucht, um die FK zu generieren. Ich habe einige gefunden, die nicht perfekt sind und ich werde sie nicht verbessern. Die Wahl zwischen SMO-Skripten und der Verwendung von Tools scheint jedoch eine Frage der persönlichen Vorlieben zu sein. Soweit bleibe ich bei der Kombination von PowerShell und SMO.
Bernd_k
2

Ich bin kein SQL Server-Typ, aber ich weiß, dass Sie in MySQL Fremdschlüsselprüfungen vorübergehend deaktivieren können. Ich habe schnell nachgefragt, ob dies in SQL Server möglich ist, und habe diesen Link gefunden:

/programming/159038/can-foreign-key-constraints-be-temporically-disabled-using-t-sql

Zusammenfassung aus der Antwort:

-- disable all constraints
EXEC sp_msforeachtable "ALTER TABLE ? NOCHECK CONSTRAINT all"

-- enable all constraints
EXEC sp_msforeachtable @command1="print '?'", @command2="ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all"
Derek Downey
quelle
1
Netter Versuch. Ich habe selbst darüber nachgedacht, aber es funktioniert nicht. Gleiche Fehlermeldung wie zuvor.
Bernd_k
gut shucks. Lassen Sie es hier, anstatt es zu löschen, damit jemand anderes nicht die gleiche Idee hat: D
Derek Downey