Implementing User-defined Types
This topic describes how to create and drop common language runtime (CLR) user-defined types in SQL Server.
Creating User-defined Types
To create a user-defined type in SQL Server, the following steps must be performed in order:
Define the user-defined type as a class or structure in a language supported by the Microsoft .NET Framework. For more information about how to program types in the CLR, see CLR User-Defined Types. Then, compile the class or structure to build an assembly in the .NET Framework using the appropriate language compiler.
Register the assembly in SQL Server by using the CREATE ASSEMBLY statement. For more information about assemblies in SQL Server, see Assemblies (Database Engine).
Create the type that references the registered assembly.
Deploying a SQL Server Project in MicrosoftVisual Studio registers an assembly in the database that was specified for the project. Deploying the project also creates CLR user-defined types in the database for all class definitions annotated with the SqlUserDefinedType attribute. For more information, see Deploying CLR Database Objects.
To create, modify, or drop an assembly
To create a user-defined type
Dropping User-defined Types
To drop a user-defined type
User-defined types cannot be modified after they are created, because changes could invalidate data in tables or indexes. To modify a type, you must either drop the type and then re-create it, or issue an ALTER ASSEMBLY statement by using the WITH UNCHECKED DATA clause.
You cannot drop a user-defined type until all references to that type have been removed. These references can include the following:
Columns defined on the type.
Computed columns and CHECK constraints whose expressions reference the type.
Schema-bound views and functions with expressions in their definitions that reference the type.
Parameters of functions and stored procedures.
To find columns dependent on a user-defined type
The following example retrieves metadata about columns defined on user-defined type ComplexNumber.
SELECT * FROM sys.columns WHERE user_type_id = TYPE_ID('ComplexNumber');
The following example retrieves limited metadata for least-privileged users about columns defined on user-defined type ComplexNumber.
SELECT * FROM sys.column_type_usages WHERE user_type_id = TYPE_ID('ComplexNumber');
To find computed column expressions, CHECK constraint expressions, and module expressions dependent on a user-defined type
The following example retrieves the names of computed columns (and their tables) with a dependency on user-defined type SimpleUdt.
SELECT OBJECT_SCHEMA_NAME (referencing_id) AS referencing_schema_name, OBJECT_NAME(referencing_id) AS referencing_name, COL_NAME(referencing_id, referencing_minor_id) AS column_name, is_caller_dependent, is_ambiguous FROM sys.sql_expression_dependencies WHERE referenced_id = TYPE_ID('SimpleUdt') AND referenced_class = 6 AND OBJECTPROPERTY(referencing_id, 'IsTable')=1;
The following example retrieves the names of CHECK constraints (and the objects on which they are defined) with a dependency on user-defined type SimpleUdt.
SELECT SCHEMA_NAME(o.schema_id) AS schema_name, OBJECT_NAME(o.parent_object_id) AS table_name, OBJECT_NAME(o.object_id) AS constraint_name FROM sys.sql_expression_dependencies AS d JOIN sys.objects AS o ON o.object_id = d.referencing_id WHERE referenced_id = TYPE_ID('SimpleUdt') AND referenced_class = 6 AND OBJECTPROPERTY(o.object_id, 'IsCheckCnst')=1;
The following example retrieves the names of modules whose definitions reference user-defined type SimpleUdt.
USE AdventureWorks; GO SELECT referencing_schema_name, referencing_entity_name, referencing_id, referencing_class_desc, is_caller_dependent FROM sys.dm_sql_referencing_entities ('SimpleUdt', 'TYPE'); GO
To find parameters dependent on a user-defined type
The following example retrieves the names of parameters (and the objects to which they belong) defined on user-defined type ComplexNumber.
SELECT OBJECT_NAME(object_id) AS object_name, NULL AS procedure_number, name AS param_name, parameter_id AS param_num, TYPE_NAME(p.user_type_id) AS type_name FROM sys.parameters AS p WHERE p.user_type_id = TYPE_ID('ComplexNumber') ORDER BY object_name, procedure_number, param_num;
The following example retrieves limited metadata for least-privileged users about parameters defined on user-defined type ComplexNumber.
SELECT * FROM sys.parameter_type_usages WHERE user_type_id = TYPE_ID('ComplexNumber');