在Sql Server中改变用户定义的types

我在DB中创build了几个用户定义的types,如下所示

CREATE TYPE [dbo].[StringID] FROM [nvarchar](20) NOT NULL 

并分配到各种表格。 我在db中的表格是在不同的模式(不仅是dbo)

但我意识到我需要更大的领域,我需要改变,例如从nvarchar增加到nvarchar,但没有ALTER TYPE语句

我需要一个脚本临时表/光标任何和保存在那里我的types使用的所有表和字段。 然后将现有字段更改为基本types – 例如从CustID [StringID]到CustID [nvarchar(20)]。 删除用户types并用新types重新创build – 例如nvarchar(50),最后将字段设置为用户types

我没有关于types的规则定义,所以不必删除规则并重新添加它们

我不是很熟悉T-Sql,所以任何帮助表示赞赏。

这是我通常使用,虽然有点手动:

 /* Add a 'temporary' UDDT with the new definition */ exec sp_addtype t_myudt_tmp, 'numeric(18,5)', NULL /* Build a command to alter all the existing columns - cut and ** paste the output, then run it */ select 'alter table dbo.' + TABLE_NAME + ' alter column ' + COLUMN_NAME + ' t_myudt_tmp' from INFORMATION_SCHEMA.COLUMNS where DOMAIN_NAME = 't_myudt' /* Remove the old UDDT */ exec sp_droptype t_mydut /* Rename the 'temporary' UDDT to the correct name */ exec sp_rename 't_myudt_tmp', 't_myudt', 'USERDATATYPE' 

这里有一个更全面的脚本的一个很好的例子

值得注意的是,如果你有任何的脚本,这个脚本将包含视图。 我运行它,而不是执行内联生成一个脚本作为输出,然后我调整和运行。

而且,如果你有使用用户被阻止的types的函数/ sprocs,你需要在运行你的脚本之前删除它们。

经验教训:将来,不要打扰UDTs,他们比他们的价值更麻烦。

 SET NOCOUNT ON DECLARE @udt VARCHAR(150) DECLARE @udtschema VARCHAR(150) DECLARE @newudtschema VARCHAR(150) DECLARE @newudtDataType VARCHAR(150) DECLARE @newudtDataSize smallint DECLARE @OtherParameter VARCHAR(50) SET @udt = 'Name' -- Existing UDDT SET @udtschema = 'dbo' -- Schema of the UDDT SET @newudtDataType = 'varchar' -- Data type for te new UDDT SET @newudtDataSize = 500 -- Lenght of the new UDDT SET @newudtschema = 'dbo' -- Schema of the new UDDT SET @OtherParameter = ' NULL' -- Other parameters like NULL , NOT NULL DECLARE @Datatype VARCHAR(50), @Datasize SMALLINT DECLARE @varcharDataType VARCHAR(50) DECLARE @Schemaname VARCHAR(50), @TableName VARCHAR(50), @FiledName VARCHAR(50) CREATE TABLE #udtflds ( Schemaname VARCHAR(50), TableName VARCHAR(50), FiledName VARCHAR(50) ) SELECT TOP 1 @Datatype = Data_type, @Datasize = character_maximum_length FROM INFORMATION_SCHEMA.COLUMNS WHERE Domain_name = @udt AND Domain_schema = @udtschema SET @varcharDataType = @Datatype IF @DataType Like '%char%' AND @Datasize IS NOT NULL AND ( @newudtDataType <> 'varchar(max)' OR @newudtDataType <> 'nvarchar(max)' ) BEGIN SET @varcharDataType = @varcharDataType + '(' + CAST(@Datasize AS VARCHAR(50)) + ')' END INSERT INTO #udtflds SELECT TABLE_SCHEMA, TABLE_NAME, Column_Name FROM INFORMATION_SCHEMA.COLUMNS WHERE Domain_name = @udt AND Domain_schema = @udtschema DECLARE @exec VARCHAR(500) DECLARE alter_cursor CURSOR FOR SELECT Schemaname, TableName, FiledName FROM #udtflds OPEN alter_cursor FETCH NEXT FROM alter_cursor INTO @Schemaname, @TableName, @FiledName WHILE @@FETCH_STATUS = 0 BEGIN SET @exec = 'Alter Table ' + @Schemaname + '.' + @TableName + ' ALTER COLUMN ' + @FiledName + ' ' + @varcharDataType EXECUTE ( @exec ) FETCH NEXT FROM alter_cursor INTO @Schemaname, @TableName, @FiledName END CLOSE alter_cursor SET @exec = 'DROP TYPE [' + @udtschema + '].[' + @udt + ']' EXEC ( @exec ) SET @varcharDataType = @newudtDataType IF @newudtDataType Like '%char%' AND @newudtDataSize IS NOT NULL AND ( @newudtDataType <> 'varchar(max)' OR @newudtDataType <> 'nvarchar(max)' ) BEGIN SET @varcharDataType = @varcharDataType + '(' + CAST(@newudtDataSize AS VARCHAR(50)) + ')' END SET @exec = 'CREATE TYPE [' + @newudtschema + '].[' + @udt + '] FROM ' + @varcharDataType + ' ' + @OtherParameter EXEC ( @exec ) OPEN alter_cursor FETCH NEXT FROM alter_cursor INTO @Schemaname, @TableName, @FiledName WHILE @@FETCH_STATUS = 0 BEGIN SET @exec = 'Alter Table ' + @Schemaname + '.' + @TableName + ' ALTER COLUMN ' + @FiledName + ' ' + '[' + @newudtschema + '].[' + @udt + ']' EXECUTE ( @exec ) FETCH NEXT FROM alter_cursor INTO @Schemaname, @TableName, @FiledName END CLOSE alter_cursor DEALLOCATE alter_cursor SELECT * FROM #udtflds DROP TABLE #udtflds 

1 : http : //www.sql-server-performance.com/2008/how-to-alter-a-uddt/已取代http://www.sql-server-performance.com/faq/How_to_alter_a%20_UDDT_p1。; ASPX

我们正在使用下面的过程,它允许我们从头开始重新创build一个types,这是“一个开始”。 它重命名现有的types,创buildtypes,重新编译存储的特效,然后删除旧的types。 这照顾了简单地删除旧的types定义由于对该types的引用而失败的场景。

用法示例:

 exec RECREATE_TYPE @schema='dbo', @typ_nme='typ_foo', @sql='AS TABLE([bar] varchar(10) NOT NULL)' 

码:

 CREATE PROCEDURE [dbo].[RECREATE_TYPE] @schema VARCHAR(100), -- the schema name for the existing type @typ_nme VARCHAR(128), -- the type-name (without schema name) @sql VARCHAR(MAX) -- the SQL to create a type WITHOUT the "CREATE TYPE schema.typename" part AS DECLARE @scid BIGINT, @typ_id BIGINT, @temp_nme VARCHAR(1000), @msg VARCHAR(200) BEGIN -- find the existing type by schema and name SELECT @scid = [SCHEMA_ID] FROM sys.schemas WHERE UPPER(name) = UPPER(@schema); IF (@scid IS NULL) BEGIN SET @msg = 'Schema ''' + @schema + ''' not found.'; RAISERROR (@msg, 1, 0); END; SELECT @typ_id = system_type_id FROM sys.types WHERE UPPER(name) = UPPER(@typ_nme); SET @temp_nme = @typ_nme + '_rcrt'; -- temporary name for the existing type -- if the type-to-be-recreated actually exists, then rename it (give it a temporary name) -- if it doesn't exist, then that's OK, too. IF (@typ_id IS NOT NULL) BEGIN exec sp_rename @objname=@typ_nme, @newname= @temp_nme, @objtype='USERDATATYPE' END; -- now create the new type SET @sql = 'CREATE TYPE ' + @schema + '.' + @typ_nme + ' ' + @sql; exec sp_sqlexec @sql; -- if we are RE-creating a type (as opposed to just creating a brand-spanking-new type)... IF (@typ_id IS NOT NULL) BEGIN exec recompile_prog; -- then recompile all stored procs (that may have used the type) exec sp_droptype @typename=@temp_nme; -- and drop the temporary type which is now no longer referenced END; END GO CREATE PROCEDURE [dbo].[recompile_prog] AS BEGIN SET NOCOUNT ON; DECLARE @v TABLE (RecID INT IDENTITY(1,1), spname sysname) -- retrieve the list of stored procedures INSERT INTO @v(spname) SELECT '[' + s.[name] + '].[' + items.name + ']' FROM (SELECT sp.name, sp.schema_id, sp.is_ms_shipped FROM sys.procedures sp UNION SELECT so.name, so.SCHEMA_ID, so.is_ms_shipped FROM sys.objects so WHERE so.type_desc LIKE '%FUNCTION%') items INNER JOIN sys.schemas s ON s.schema_id = items.schema_id WHERE is_ms_shipped = 0; -- counter variables DECLARE @cnt INT, @Tot INT; SELECT @cnt = 1; SELECT @Tot = COUNT(*) FROM @v; DECLARE @spname sysname -- start the loop WHILE @Cnt <= @Tot BEGIN SELECT @spname = spname FROM @v WHERE RecID = @Cnt; --PRINT 'refreshing...' + @spname BEGIN TRY -- refresh the stored procedure EXEC sp_refreshsqlmodule @spname END TRY BEGIN CATCH PRINT 'Validation failed for : ' + @spname + ', Error:' + ERROR_MESSAGE(); END CATCH SET @Cnt = @cnt + 1; END; END 

正如devio所说的那样,如果UDT正在使用中,则无法简单地编辑UDT。

通过SMS为我工作的工作是生成一个创build脚本,并进行适当的更改; 重命名现有的UDT; 运行创build脚本; 重新编译相关的sprocs并删除重命名的版本。

此处提供的解决scheme仅适用于仅在表定义中使用用户定义的types以及UDT列未编入索引的情况。

一些开发人员也有使用UDT参数的SP和函数,但是也没有涉及。 (请参阅Robin链接和Connect条目的评论 )

从2007年的连接入口终于在3年后closures:

感谢您提交这个build议,但是考虑到我们队列中其他许多项目的重要性,我们不太可能真正完成这个build议。 因此,我们正在closures这个build议,因为“不会修复”。

我试图解决一个类似的问题, 改变XML SCHEMA COLLECTIONS ,这些步骤似乎也主要适用于ALTER TYPE:

要删除UDT,需要执行以下步骤:

  • 如果表列引用UDT,则必须将其转换为基础types
  • 如果表列具有默认约束,则删除默认约束
  • 如果某个过程或函数具有UDT参数,则必须删除该过程或函数
  • 如果在UDT列上有索引,则索引必须被删除
  • 如果索引是主键,则必须删除所有外键
  • 如果有基于UDT列的计算列,则必须删除计算列
  • 如果这些计算列上有索引,则索引必须被删除
  • 如果存在基于包含UDT列的表的模式绑定视图,函数或过程,则必须删除这些对象

最简单的方法是通过Visual Studio的对象浏览器(Community Explorer)支持。

一旦连接到SQL服务器,浏览到types,右键单击并select查看代码,对用户定义types的模式进行更改,然后单击更新。 Visual Studio应该会显示该对象的所有依赖关系,并生成脚本来更新types并重新编译依赖关系。

重命名旧的UDT,
2.执行查询,3.删除旧的UDT。

一个老问题的新答案:

Visual Studio数据库项目处理删除并在部署更改时重新创build进程。 它将删除使用UDDT的存储过程,然后在删除和重新创build数据types后重新创build它们。

简单的DROP TYPE首先然后CREATE TYPE与更正/更改?

有一个简单的testing,看看它是否被定义之前,你放下它…很像一个表,过程或函数 – 如果我不在工作,我会看看是什么?

(我也只是在上面掠过…如果我看错了,我提前道歉!