Registrieren von benutzerdefinierten Typen in SQL Server
Gilt für:SQL Server
Um einen benutzerdefinierten Typ (USER-Defined Type, UDT) in SQL Server zu verwenden, müssen Sie ihn registrieren. Beim Registrieren eines UDT muss die Assembly registriert werden und der Typ in der Datenbank, in der er verwendet werden soll, erstellt werden. UDTs sind auf eine einzelne Datenbank festgelegt und können nicht in mehreren Datenbanken verwendet werden, es sei denn, die identische Assembly und UDT werden bei jeder Datenbank registriert. Nachdem die UDT-Assembly registriert und der Typ erstellt wurde, können Sie udT in Transact-SQL und im Clientcode verwenden. Weitere Informationen finden Sie unter benutzerdefinierte CLR-Typen.
Verwenden von Visual Studio zum Bereitstellen von UDTs
Die einfachste Möglichkeit zum Bereitstellen Ihres UDT ist die Verwendung von Visual Studio. Verwenden Sie für komplexere Bereitstellungsszenarien und die größte Flexibilität jedoch Transact-SQL, wie weiter unten in diesem Artikel erläutert.
Führen Sie die folgenden Schritte aus, um einen UDT mit Visual Studio zu erstellen und bereitzustellen:
Erstellen Sie ein neues Datenbankprojekt in den Visual Basic - oder Visual C# -Sprachknoten.
Fügen Sie einen Verweis auf die SQL Server-Datenbank hinzu, die das UDT enthält.
Fügen Sie eine benutzerdefinierte Typklasse hinzu.
Erstellen Sie den Code, um den UDT zu implementieren.
Wählen Sie im Menü "Erstellen " die Option "Bereitstellen" aus. Dadurch wird die Assembly registriert und der Typ in der SQL Server-Datenbank erstellt.
Verwenden von Transact-SQL zum Bereitstellen von UDTs
Die Transact-SQL CREATE ASSEMBLY
Syntax wird verwendet, um die Assembly in der Datenbank zu registrieren, in der Sie udT verwenden möchten. Sie wird intern in Datenbanksystemtabellen gespeichert, nicht extern im Dateisystem. Wenn die UDTs von externen Assemblys abhängig sind, müssen sie auch in die Datenbank geladen werden. Die CREATE TYPE
-Anweisung wird verwendet, um die UDT in der Datenbank zu erstellen, in der sie verwendet werden soll. Weitere Informationen finden Sie unter CREATE ASSEMBLY und CREATE TYPE.
Erstellen einer Assembly verwenden
Die CREATE ASSEMBLY
Syntax registriert die Assembly in der Datenbank, in der Sie udT verwenden möchten. Sobald die Assembly registriert wurde, liegen keine Abhängigkeiten vor.
Das Erstellen mehrerer Versionen derselben Assembly in einer bestimmten Datenbank ist nicht zulässig. Es ist jedoch möglich, mehrere Versionen derselben Assembly basierend auf der Kultur in einer bestimmten Datenbank zu erstellen. SQL Server unterscheidet mehrere Kulturversionen einer Assembly durch verschiedene Namen, wie in der Instanz von SQL Server registriert. Weitere Informationen finden Sie unter Erstellen und Verwenden von assemblys mit starkem Namen.
Wenn CREATE ASSEMBLY
mit den SAFE
- oder EXTERNAL_ACCESS
Berechtigungssätzen ausgeführt wird, wird die Assembly überprüft, um sicherzustellen, dass sie überprüfbar und typsicher ist. Wenn Sie die Angabe eines Berechtigungssatzes weglassen, wird SAFE
angenommen. Code mit dem UNSAFE
Berechtigungssatz ist nicht aktiviert. Weitere Informationen zu Assemblyberechtigungssätzen finden Sie unter Designassemblys.
Beispiel
Die folgende Transact-SQL-Anweisung registriert die Point
-Assembly in SQL Server in der AdventureWorks2022
-Datenbank mit dem SAFE
Berechtigungssatz. Wenn die WITH PERMISSION_SET
-Klausel nicht angegeben wird, wird die Assembly mit dem SAFE
Berechtigungssatz registriert.
USE AdventureWorks2022;
CREATE ASSEMBLY Point
FROM '\\ShareName\Projects\Point\bin\Point.dll'
WITH PERMISSION_SET = SAFE;
Die folgende Transact-SQL-Anweisung registriert die Assembly mithilfe <assembly_bits> Arguments in der FROM
-Klausel. Dieser varbinary-Wert stellt die Datei als Bytestrom dar.
USE AdventureWorks2022;
CREATE ASSEMBLY Point
FROM 0xfeac4 ... 21ac78
Verwenden des Typs "Erstellen"
Nachdem die Assembly in die Datenbank geladen wurde, können Sie den Typ mithilfe der Transact-SQL CREATE TYPE
-Anweisung erstellen. Dadurch wird der Typ der Liste mit verfügbaren Typen für diese Datenbank hinzugefügt. Der Typ hat einen Datenbankbereich und kann nur in der Datenbank, in der er erstellt wurde, verwendet werden. Wenn das UDT bereits in der Datenbank vorhanden ist, schlägt die CREATE TYPE
-Anweisung mit einem Fehler fehl.
Hinweis
Die CREATE TYPE
syntax wird auch zum Erstellen nativer SQL Server-Alias-Datentypen verwendet und soll sp_addtype
als Mittel zum Erstellen von Aliasdatentypen ersetzen. Einige der optionalen Argumente in der CREATE TYPE
-Syntax beziehen sich auf das Erstellen von UDTs und gelten nicht für das Erstellen von Alias-Datentypen (z. B. Basistyp).
Weitere Informationen finden Sie unter CREATE TYPE.
Beispiel
Mit der folgenden Transact-SQL-Anweisung wird der Point
Typ erstellt. Die EXTERNAL NAME
wird mithilfe der zweiteiligen Benennungssyntax von <assembly_name>.<udt_name>
angegeben.
CREATE TYPE dbo.Point
EXTERNAL NAME Point.[Point];
Entfernen eines UDT aus der Datenbank
Die DROP TYPE
-Anweisung entfernt ein UDT aus der aktuellen Datenbank. Nachdem ein UDT abgelegt wurde, können Sie die DROP ASSEMBLY
-Anweisung verwenden, um die Assembly aus der Datenbank abzulegen.
Die DROP TYPE
-Anweisung wird in den folgenden Situationen nicht ausgeführt:
Tabellen in der Datenbank, die mit dem UDT definierte Spalten enthalten.
Funktionen, gespeicherte Prozeduren oder Trigger, die Variablen oder Parameter des UDT verwenden, die in der Datenbank mit der
WITH SCHEMABINDING
-Klausel erstellt wurden.
Beispiel
Die folgende Transact-SQL-Anweisung muss in der folgenden Reihenfolge ausgeführt werden. Zuerst muss die Tabelle, die auf die Point
UDT verweist, gelöscht werden, dann den Typ und schließlich die Assembly.
DROP TABLE dbo.Points;
DROP TYPE dbo.Point;
DROP ASSEMBLY Point;
Suchen von UDT-Abhängigkeiten
Wenn abhängige Objekte vorhanden sind, z. B. Tabellen mit UDT-Spaltendefinitionen, schlägt die DROP TYPE
-Anweisung fehl. Es schlägt auch fehl, wenn Funktionen, gespeicherte Prozeduren oder Trigger in der Datenbank mithilfe der WITH SCHEMABINDING
-Klausel erstellt wurden, wenn diese Routinen Variablen oder Parameter des benutzerdefinierten Typs verwenden. Sie müssen zuerst alle abhängigen Objekte ablegen und dann die DROP TYPE
-Anweisung ausführen.
Die folgende Transact-SQL Abfrage sucht alle Spalten und Parameter, die ein UDT in der AdventureWorks2022
-Datenbank verwenden.
USE AdventureWorks2022;
SELECT o.name AS major_name,
o.type_desc AS major_type_desc,
c.name AS minor_name,
c.type_desc AS minor_type_desc,
at.assembly_class
FROM (SELECT object_id,
name,
user_type_id,
'SQL_COLUMN' AS type_desc
FROM sys.columns
UNION ALL
SELECT object_id,
name,
user_type_id,
'SQL_PROCEDURE_PARAMETER'
FROM sys.parameters) AS c
INNER JOIN sys.objects AS o
ON o.object_id = c.object_id
INNER JOIN sys.assembly_types AS at
ON at.user_type_id = c.user_type_id;
Verwalten von UDTs
Sie können ein UDT nicht ändern, nachdem es in einer SQL Server-Datenbank erstellt wurde, obwohl Sie die Assembly ändern können, auf der der Typ basiert. In den meisten Fällen müssen Sie das UDT aus der Datenbank mit der Transact-SQL DROP TYPE
-Anweisung entfernen, Änderungen an der zugrunde liegenden Assembly vornehmen und mithilfe der ALTER ASSEMBLY
-Anweisung neu laden. Anschließend müssen der UDT und abhängige Objekte neu erstellt werden.
Beispiel
Die ALTER ASSEMBLY
-Anweisung wird verwendet, nachdem Sie Änderungen am Quellcode in Ihrer UDT-Assembly vorgenommen und neu kompiliert haben. Die DLL-Datei wird auf den Server kopiert und dort zur neuen Assembly verbunden. Die vollständige Syntax finden Sie unter ALTER ASSEMBLY.
Die folgende Transact-SQL ALTER ASSEMBLY
-Anweisung lädt die Point.dll Assembly vom angegebenen Speicherort auf dem Datenträger neu.
ALTER ASSEMBLY Point
FROM '\\Projects\Point\bin\Point.dll';
Verwenden der Änderungsassembly zum Hinzufügen von Quellcode
Die ADD FILE
-Klausel in der ALTER ASSEMBLY
-Syntax ist in CREATE ASSEMBLY
nicht vorhanden. Sie können sie verwenden, um Quellcode oder beliebige andere Dateien hinzuzufügen, die einer Assembly zugeordnet sind. Die Dateien werden von ihren ursprünglichen Speicherorten kopiert und in Systemtabellen in der Datenbank gespeichert. Dadurch wird sichergestellt, dass stets der Quellcode oder andere Dateien verfügbar sind, wenn Sie die aktuelle Version des UDT neu erstellen oder dokumentieren müssen.
Die folgende Transact-SQL ALTER ASSEMBLY
-Anweisung fügt den Point.cs Klassenquellcode für das Point
UDT hinzu. Dadurch wird der in der datei Point.cs enthaltene Text kopiert und in der Datenbank unter dem Namen PointSource
gespeichert.
ALTER ASSEMBLY Point
ADD FILE FROM '\\Projects\Point\Point.cs' AS PointSource;
Assemblyinformationen werden in der sys.assembly_files
Tabelle in der Datenbank gespeichert, in der die Assembly installiert wurde. Die sys.assembly_files
Tabelle enthält die folgenden Spalten.
Spalte | Beschreibung |
---|---|
assembly_id |
Der für die Assembly definierte Bezeichner. Diese Nummer wird allen Objekten mit Bezug auf dieselbe Assembly zugewiesen. |
name |
Der Name des Objekts. |
file_id |
Eine Zahl, die jedes Objekt identifiziert, wobei das erste Objekt einem bestimmten assembly_id zugeordnet ist, der dem Wert 1 zugewiesen wird. Wenn mehrere Objekte mit demselben assembly_id verknüpft sind, werden alle nachfolgenden file_id Wertschritte um 1 erhöht. |
content |
Die Hexadezimaldarstellung der Assembly oder Datei. |
Sie können die funktion CAST
oder CONVERT
verwenden, um den Inhalt der content
Spalte in lesbaren Text zu konvertieren. Die folgende Abfrage konvertiert den Inhalt der Point.cs
Datei in lesbaren Text, wobei der Name in der WHERE
-Klausel verwendet wird, um das Resultset auf eine einzelne Zeile zu beschränken.
SELECT CAST (content AS VARCHAR (8000))
FROM sys.assembly_files
WHERE name = 'PointSource';
Wenn Sie die Ergebnisse kopieren und in einen Text-Editor einfügen, sehen Sie, dass die Zeilenumbrüche und Leerzeichen, die im Original vorhanden sind, beibehalten werden.
Verwalten von UDTs und Assemblys
Beim Planen der Implementierung von UDTs sollten Sie die Methoden berücksichtigen, die in der UDT-Assembly selbst benötigt werden und die in separaten Assemblys erstellt und als benutzerdefinierte Funktionen oder gespeicherte Prozeduren implementiert werden sollen. Durch das Trennen von Methoden in separate Assemblys können Sie Code aktualisieren, ohne dass sich dies auf Daten auswirkt, die in einer UDT-Spalte in einer Tabelle gespeichert werden können. Sie können UDT-Assemblys ändern, ohne UDT-Spalten und andere abhängige Objekte nur zu löschen, wenn die neue Definition die ehemaligen Werte lesen kann und die Signatur des Typs sich nicht ändert.
Das Trennen von prozeduralen Code, der sich möglicherweise von dem Code ändert, der zum Implementieren des UDT erforderlich ist, vereinfacht die Wartung erheblich. Wenn Sie nur Code einschließen, der für die Funktion von UDT erforderlich ist und Ihre UDT-Definitionen so einfach wie möglich beibehalten werden, verringert sich das Risiko, dass die UDT selbst möglicherweise aus der Datenbank für Coderevisionen oder Fehlerkorrekturen gelöscht werden muss.
Die Währungs-UDT- und Währungsumrechnungsfunktion
Die Currency
UDT in der AdventureWorks2022
Beispieldatenbank bietet ein nützliches Beispiel für die empfohlene Methode zum Strukturieren eines UDT und der zugehörigen Funktionen. Die Currency
UDT wird für die Abwicklung von Geld basierend auf dem Währungssystem einer bestimmten Kultur verwendet und ermöglicht die Speicherung verschiedener Währungstypen, wie Dollar, Euro usw. Die UDT-Klasse macht einen Kulturnamen als Zeichenfolge und einen Geldbetrag als Dezimaldatentyp verfügbar. Alle notwendigen Serialisierungsmethoden sind in der Assembly enthalten, die die Klasse definiert. Die Funktion, die die Währungsumrechnung von einer Kultur in eine andere implementiert, wird als externe Funktion namens ConvertCurrency
implementiert, und diese Funktion befindet sich in einer separaten Assembly. Die ConvertCurrency
-Funktion führt ihre Arbeit durch Abrufen der Konvertierungsrate aus einer Tabelle in der AdventureWorks2022
-Datenbank aus. Wenn sich die Quelle der Konvertierungsraten jemals ändern sollte oder andere Änderungen am vorhandenen Code vorgenommen werden sollen, kann die Assembly problemlos geändert werden, ohne dass sich dies auf die Currency
UDT auswirkt.
Die Codeauflistung für die funktionen Currency
UDT und ConvertCurrency
finden Sie, indem Sie die Beispiele für common language runtime (CLR) installieren.
Verwenden von UDTs in Datenbanken
UDTs sind definitionsgemäß auf eine einzelne Datenbank beschränkt. Daher kann ein in einer Datenbank definiertes UDT nicht in einer Spaltendefinition in einer anderen Datenbank verwendet werden. Um UDTs in mehreren Datenbanken verwenden zu können, müssen Sie die CREATE ASSEMBLY
und CREATE TYPE
Anweisungen in jeder Datenbank für identische Assemblys ausführen. Assemblys gelten als identisch, wenn die folgenden Werte gleich sind: Name, starker Name, Kultur, Version, Berechtigungssatz und binäre Inhalte.
Nachdem der UDT registriert wurde und der Zugriff darauf in beiden Datenbanken erfolgen kann, können Sie einen UDT-Wert aus einer Datenbank für die Verwendung in einer anderen Datenbank konvertieren. Identische UDTs können in den folgenden Szenarios über mehrere Datenbanken hinweg verwendet werden:
Aufrufen einer gespeicherten Prozedur, die in anderen Datenbanken definiert ist.
Abfragen von in anderen Datenbanken definierten Tabellen.
Auswählen von UDT-Daten aus einer UDT-Spalte in einer Datenbanktabelle und Einfügen in eine zweite Datenbank mit einer identischen UDT-Spalte.
In diesen Szenarios findet die für den Server erforderliche Konvertierung automatisch statt. Sie können die Konvertierungen nicht explizit mithilfe der funktionen Transact-SQL CAST
oder CONVERT
ausführen.
Sie müssen keine Aktion für die Verwendung von UDTs ergreifen, wenn das SQL Server-Datenbankmodul Arbeitstabellen in der tempdb
Systemdatenbank erstellt. Dazu gehören die Behandlung von Cursorn, Tabellenvariablen und benutzerdefinierten Tabellenwertfunktionen, die UDTs enthalten und die tempdb
transparent nutzen. Wenn Sie jedoch explizit eine temporäre Tabelle in tempdb
erstellen, die eine UDT-Spalte definiert, muss die UDT in tempdb
auf die gleiche Weise registriert werden wie für eine Benutzerdatenbank.