Ändern benutzerdefinierter Tabellentypen in SQL Server

Antworten:

69

Meines Wissens ist es unmöglich, einen Tabellentyp zu ändern. Sie können den Typ mit einem anderen Namen erstellen und dann den alten Typ löschen und in den neuen Namen ändern

Credits an jkrajes

Wie pro Msdn ist es wie ‚Die benutzerdefinierte Tabellentypdefinition nicht geändert werden kann , nachdem es erstellt wird‘.

Manivannan Nagarajan
quelle
2
Ich verwende eine Reihe von generierten Drop / Create-Skripten aller Objekte, abhängig vom benutzerdefinierten Typ und vom benutzerdefinierten Typ selbst.
Ronnie Overby
6
Wie bekomme ich mehr als 20.000 Zeilen-Skripte in SQL? Löschen / Erstellen aller Abhängigkeiten von Tabellentypen, die Sie ändern müssen. : P
Spacemonkey
14
Das ist schrecklich (Microsoft), jetzt muss ich ALLE SPs ändern, wenn ich Änderungen an diesen Tabellen vornehme, dann alle Verweise darauf löschen, neu erstellen und zurückgehen und aktualisieren. Schlecht durchdacht .. Ich weiß, das ist ein Scherz, aber was dachten sie?
schmoopy
1
Es scheint auch, dass Sie nicht einmal den Eigentümer eines benutzerdefinierten Tabellentyps ändern dürfen. Das Löschen des Tabellentyps und das erneute Erstellen mit einem neuen Eigentümernamen scheint die einzige Möglichkeit zu sein, den Eigentümernamen zu ändern, falls Sie dies ändern müssen. sp_changeobjectowner funktioniert nicht mit benutzerdefinierten Tabellentypen ...
Jeff
38

Dies ist eine Art Hack, scheint aber zu funktionieren. Im Folgenden finden Sie die Schritte und ein Beispiel zum Ändern eines Tabellentyps. Ein Hinweis ist, dass das sp_refreshsql-Modul fehlschlägt, wenn die Änderung, die Sie am Tabellentyp vorgenommen haben, eine wichtige Änderung an diesem Objekt ist, normalerweise eine Prozedur.

  1. Verwenden Sie sp_renameden Tabellentyp umbenennen, ich in der Regel nur hinzufügen , z an den Anfang des Namens.
  2. Erstellen Sie einen neuen Tabellentyp mit dem ursprünglichen Namen und allen Änderungen, die Sie am Tabellentyp vornehmen müssen.
  3. Durchlaufen Sie jede Abhängigkeit und führen Sie sp_refreshsqlmodulesie aus.
  4. Löschen Sie den umbenannten Tabellentyp.

EXEC sys.sp_rename 'dbo.MyTableType', 'zMyTableType';
GO
CREATE TYPE dbo.MyTableType AS TABLE(
    Id INT NOT NULL,
    Name VARCHAR(255) NOT NULL
);
GO
DECLARE @Name NVARCHAR(776);

DECLARE REF_CURSOR CURSOR FOR
SELECT referencing_schema_name + '.' + referencing_entity_name
FROM sys.dm_sql_referencing_entities('dbo.MyTableType', 'TYPE');

OPEN REF_CURSOR;

FETCH NEXT FROM REF_CURSOR INTO @Name;
WHILE (@@FETCH_STATUS = 0)
BEGIN
    EXEC sys.sp_refreshsqlmodule @name = @Name;
    FETCH NEXT FROM REF_CURSOR INTO @Name;
END;

CLOSE REF_CURSOR;
DEALLOCATE REF_CURSOR;
GO
DROP TYPE dbo.zMyTableType;
GO

WARNUNG:

Dies kann sich nachteilig auf Ihre Datenbank auswirken. Sie sollten dies daher zunächst in einer Entwicklungsumgebung testen.

norlando
quelle
Bemerkung zu sp_refreshsqlmodule unter MSDN-Link: msdn.microsoft.com/en-us/library/bb326754.aspx ist ziemlich bedrohlich. Aktualisiert dieser SP jedoch auch den Text der referenzierten Objekte oder aktualisiert nur das dort kompilierte Formular? Ich meine, wenn ich SP_HELPTEXT auf einem meiner referenzierten SP ausführen werde, bekomme ich dann dort den neuen Typnamen oder nicht?
Yogi
Dadurch wird der Tabellentyp in Ihrem gespeicherten Prozess nicht in den Tabellentyp z geändert. Alles, was es tut, aktualisiert das Schema so wie es ist, korrigiert aber den Verweis auf Ihren Tabellentyp. Wenn Sie sp_refreshsqlmodlenach dem Neuerstellen des Tabellentyps nicht auf Ihrem Store-Proc ausgeführt werden, schlägt der gespeicherte Proc fehl, dass der Tabellentyp geändert wurde. Ich empfehle, dies auf einer Entwicklungsversion Ihrer Datenbank auszuführen, bevor Sie es in der Produktion ausführen.
Norwegen
1
Diese Antwort hat bei mir nicht funktioniert. Sobald sp_rename ausgeführt wird, wird der Parametertyp auf SP aktualisiert, um auf das neue UDTT zu verweisen. Später kann das umbenannte UDTT nicht mehr gelöscht werden. sp_rename erzwingt Abhängigkeiten. Diese Antwort setzt voraus, dass sp_rename den Parametertyp beim Verweisen auf SPs nicht aktualisiert.
Murtazat
sp_renameauf benutzerdefinierten Datentyp werfen Sie mir einen Fehler: Either the parameter @objname is ambiguous or the claimed @objtype ((null)) is wrong.Was könnte falsch sein?
Muflix
1
@Muflix, möglicherweise müssen Sie den Objekttyp wie folgt übergeben EXEC sys.sp_rename 'dbo.MyTableType', 'zMyTableType', 'OBJECT';. Stellen Sie außerdem sicher, dass Sie das Schema für den ersten Parameter und nicht für den zweiten einschließen.
Norwegen
15

Hier sind einfache Schritte, die Langeweile minimieren und keine fehleranfälligen halbautomatischen Skripte oder teuren Tools erfordern.

Beachten Sie, dass Sie im Fenster "Objekt-Explorer-Details" DROP / CREATE-Anweisungen für mehrere Objekte generieren können (bei dieser Generierung werden DROP- und CREATE-Skripte gruppiert, wodurch das Einfügen von Logik zwischen Drop- und Create-Aktionen vereinfacht wird):

Ablegen und erstellen an

  1. Sichern Sie Ihre Datenbank für den Fall, dass etwas schief geht!
  2. Generieren Sie automatisch die DROP / CREATE-Anweisungen für alle Abhängigkeiten (oder generieren Sie sie für alle "Programmierbarkeit" -Objekte, um die mühsame Suche nach Abhängigkeiten zu vermeiden).
  3. Fügen Sie zwischen den Anweisungen DROP und CREATE [Abhängigkeiten] (nach allen DROP, vor allen CREATE) generierte DROP / CREATE-Anweisungen [Tabellentyp] ein und nehmen Sie die erforderlichen Änderungen mit CREATE TYPE vor.
  4. Führen Sie das Skript aus, das alle Abhängigkeiten / UDTTs löscht und dann [UDTTs mit Änderungen] / Abhängigkeiten neu erstellt.

Wenn Sie kleinere Projekte haben, in denen es möglicherweise sinnvoll ist, die Infrastrukturarchitektur zu ändern, sollten Sie benutzerdefinierte Tabellentypen entfernen. Mit Entity Framework und ähnlichen Tools können Sie den größten Teil, wenn nicht den gesamten Teil Ihrer Datenlogik in Ihre Codebasis verschieben, wo die Wartung einfacher ist.

Lichtmotor
quelle
1
Ich habe Ihren Rat befolgt und überlegt, Hunderttausende von Codezeilen zu migrieren, um Entity Framework zu verwenden, damit wir nicht einen benutzerdefinierten Tabellentyp löschen und neu erstellen müssen. Aber nach einer Sekunde entschied ich, dass das Löschen und Neuerstellen des Tabellentyps ein einfacherer Weg war.
Papillon
1
@PapillonUK, ich bin bei dir. Ich habe ein größeres Projekt, daher treffe ich immer noch die gleiche Entscheidung wie Sie (und die oben beschriebene Methode ist so schnell, dass ich sie auf absehbare Zeit wahrscheinlich fortsetzen werde). Ich erwähnte die Abkehr von UDTTs für diejenigen, die kleinere Projekte haben, bei denen es möglicherweise sinnvoll ist, die Architektur jetzt zu ändern, um zukünftige Änderungen zu vereinfachen. Deshalb habe ich meine Antwort entsprechend aktualisiert. Vielen Dank.
Lichtmotor
8

Simon Zeinstra hat die Lösung gefunden!

Aber ich habe Visual Studio Community 2015 verwendet und musste nicht einmal Schemavergleich verwenden.

Mit SQL Server Object Explorer habe ich meinen benutzerdefinierten Tabellentyp in der Datenbank gefunden. Ich habe mit der rechten Maustaste auf den Tabellentyp geklickt und ausgewählt. Dadurch wurde eine Code-Registerkarte in der IDE geöffnet, in der der TSQL-Code sichtbar und bearbeitbar war . Ich habe einfach die Definition geändert (in meinem Fall nur ein nvarchar-Feld vergrößert) und oben links auf der Registerkarte auf die Schaltfläche Datenbank aktualisieren geklickt .

Hey Presto! - Eine schnelle Überprüfung in SSMS und die udtt-Definition wurde geändert.

Genial - danke Simon.

BioEcoSS
quelle
1
Dies ist wahrscheinlich besser als Kommentar zur Antwort geeignet, nicht als eigenständige Antwort.
Phil Cooper
TBH Ich fand das sehr nützlich, war ein einfacher Weg, um dieses Problem für mich zu lösen, und erklärte Leuten wie mir, die mit Datenbankprojekten in Visual Studio nicht allzu vertraut sind, wie dies zu tun ist.
Steve Kennaird
Ich fand diese Antwort auch hilfreich
Padmika
Danke, dass
du das geteilt hast
7

Wenn Sie ein Datenbankprojekt in Visual Studio verwenden können, können Sie Ihre Änderungen im Projekt vornehmen und den Schemavergleich verwenden, um die Änderungen mit Ihrer Datenbank zu synchronisieren.

Auf diese Weise wird das Löschen und Neuerstellen der abhängigen Objekte vom Änderungsskript behandelt.

Simon Zeinstra
quelle
Ich fand diese Antwort hilfreich zusammen mit der Antwort von
BioEcoSS
4

Sie sollten den alten Tabellentyp löschen und einen neuen erstellen. Wenn es jedoch Abhängigkeiten gibt (gespeicherte Prozeduren, die es verwenden), können Sie es nicht löschen. Ich habe eine weitere Antwort veröffentlicht, wie der Prozess des temporären Löschens aller gespeicherten Prozeduren, des Änderns der Tabellentabelle und des anschließenden Wiederherstellens der gespeicherten Prozeduren automatisiert werden kann.

BornToCode
quelle
Ist es nicht selbstverständlich, dass es Abhängigkeiten haben würde, warum sollten Sie es sonst zuerst erstellen lassen?
LarryBud
@LarryBud - Ein einfaches Beispiel könnte sein, dass jemand es gerade erstellt hat und noch keine Chance hatte, es in einer gespeicherten Prozedur usw. zu verwenden.
BornToCode
3

Sie können Ihren Typ nicht ändern / ändern. Sie müssen das vorhandene löschen und mit dem richtigen Namen / Datentyp neu erstellen oder eine neue Spalte hinzufügen

user2767892
quelle