SQL Server 2012 - 在没有活动依赖项时无法删除用户定义的 (table) 类型
SQL Server 2012 - Cannot drop User defined (table) type while there are no active dependencies
我有一个用户定义类型,其中一个 VARCHAR 列的大小需要增加。由于依赖关系(使用该类型的存储过程),无法更改类型。所以,我尝试了以下方法:
场景是这样的:
- 将类型从
T_MyType
重命名为 T_MyType_1
,
- 要求 Management Studio 为类型
T_MyType_1
、 构建创建脚本
- 编辑脚本,从类型名称中删除“
_1
”并增加一个字段的大小,然后运行脚本,
- 运行 导致 t运行cation 问题(列长度)并获得成功结果(没有 t运行cation 或错误消息)的过程,
- 尝试删除类型
T_MyType_1
并收到错误,指出该类型正在被过程 ABC 使用,
- 在过程 ABC 的正文中搜索
T_MyType_1
,未找到字符串。
所以,我遇到了一个需要删除的定义类型。
编辑
我认为这个问题与建议的重复问题不同。
我永远不会重命名对象。通常不推荐这样做,我知道这可能会导致问题。这很可能是您问题的核心,我怀疑所有这一切背后都有一些隐藏的映射。
一般来说:如果 ALTER
不可用,那么重命名就没有用。
我建议找到所有依赖项,构建所需的删除并创建脚本,从而确保一切正常。所有这一切甚至可以通过一个脚本来完成,该脚本遍历系统表并提取您需要的脚本。另一种方法是找到依赖项并通过生成脚本命令编写脚本,从而确保脚本以正确的顺序生成。
重命名是一种危险的消遣,因为它不能很好地适应 SQL 服务器依赖性跟踪的有限实现,以及存储过程的延迟名称解析。我实际上无法在 SQL Server 2017 上重现此特定场景(如果在过程主体中使用了 UDT,则可以正确跟踪依赖项)因此这种情况可能已得到改进。当然,如果您将 UDT 用作 参数 它实际上会检测到问题并给出适当的错误消息:
CREATE TYPE BadUdt FROM NVARCHAR(10);
GO
CREATE PROCEDURE AreUdtsBadThough(@T BadUdt) AS BEGIN
RETURN;
END;
GO
EXEC sp_rename 'BadUdt', 'GoodUdt';
GO
CREATE TYPE BadUdt FROM NVARCHAR(20);
GO
EXEC AreUdtsBadThough NULL
Msg 496, Level 16, State 1, Procedure AreUdtsBadThough, Line 6 [Batch
Start Line 16] The parameter "@T" is not the same type as the type it
was created with. Drop and recreate the module using a two-part name
for the type, or use sp_refreshsqlmodule to refresh its parameters
metadata.
尽管名称发生了变化,AreUdtsBadThough
的参数仍然通过 ID 链接到旧类型,这就是为什么你不能删除它的原因:
SELECT p.[name], t.[name]
FROM sys.parameters p
JOIN sys.types t ON p.user_type_id = t.user_type_id
WHERE [object_id] = OBJECT_ID('AreUdtsBadThough')
+------+---------+
| name | name |
+------+---------+
| @T | GoodUdt |
+------+---------+
该错误有助于描述依赖性问题的一般解决方案:调用 sp_refreshsqlmodule
,它强制有效地重新编译存储过程(或函数、触发器或视图)并更新依赖性:
EXEC sp_refreshsqlmodule 'AreUdtsBadThough'
SELECT p.[name], t.[name]
FROM sys.parameters p
JOIN sys.types t ON p.user_type_id = t.user_type_id
WHERE [object_id] = OBJECT_ID('AreUdtsBadThough')
+------+--------+
| name | name |
+------+--------+
| @T | BadUdt |
+------+--------+
现在 GoodUdt
不再有依赖关系,可以删除了。
依赖关系并不总是得到正确更新(不限于重命名)的问题促使一些人想出了更永久的解决方案。由于改进了依赖性检查,Aaron Bertrand 对 SQL Server 2008 的依赖性自动更新有一个 article(它应该仍然适用于更高版本,即使它可能做的工作比必要的更多)。
我有一个用户定义类型,其中一个 VARCHAR 列的大小需要增加。由于依赖关系(使用该类型的存储过程),无法更改类型。所以,我尝试了以下方法:
场景是这样的:
- 将类型从
T_MyType
重命名为T_MyType_1
, - 要求 Management Studio 为类型
T_MyType_1
、 构建创建脚本
- 编辑脚本,从类型名称中删除“
_1
”并增加一个字段的大小,然后运行脚本, - 运行 导致 t运行cation 问题(列长度)并获得成功结果(没有 t运行cation 或错误消息)的过程,
- 尝试删除类型
T_MyType_1
并收到错误,指出该类型正在被过程 ABC 使用, - 在过程 ABC 的正文中搜索
T_MyType_1
,未找到字符串。
所以,我遇到了一个需要删除的定义类型。
编辑
我认为这个问题与建议的重复问题不同。
我永远不会重命名对象。通常不推荐这样做,我知道这可能会导致问题。这很可能是您问题的核心,我怀疑所有这一切背后都有一些隐藏的映射。
一般来说:如果 ALTER
不可用,那么重命名就没有用。
我建议找到所有依赖项,构建所需的删除并创建脚本,从而确保一切正常。所有这一切甚至可以通过一个脚本来完成,该脚本遍历系统表并提取您需要的脚本。另一种方法是找到依赖项并通过生成脚本命令编写脚本,从而确保脚本以正确的顺序生成。
重命名是一种危险的消遣,因为它不能很好地适应 SQL 服务器依赖性跟踪的有限实现,以及存储过程的延迟名称解析。我实际上无法在 SQL Server 2017 上重现此特定场景(如果在过程主体中使用了 UDT,则可以正确跟踪依赖项)因此这种情况可能已得到改进。当然,如果您将 UDT 用作 参数 它实际上会检测到问题并给出适当的错误消息:
CREATE TYPE BadUdt FROM NVARCHAR(10);
GO
CREATE PROCEDURE AreUdtsBadThough(@T BadUdt) AS BEGIN
RETURN;
END;
GO
EXEC sp_rename 'BadUdt', 'GoodUdt';
GO
CREATE TYPE BadUdt FROM NVARCHAR(20);
GO
EXEC AreUdtsBadThough NULL
Msg 496, Level 16, State 1, Procedure AreUdtsBadThough, Line 6 [Batch Start Line 16] The parameter "@T" is not the same type as the type it was created with. Drop and recreate the module using a two-part name for the type, or use sp_refreshsqlmodule to refresh its parameters metadata.
尽管名称发生了变化,AreUdtsBadThough
的参数仍然通过 ID 链接到旧类型,这就是为什么你不能删除它的原因:
SELECT p.[name], t.[name]
FROM sys.parameters p
JOIN sys.types t ON p.user_type_id = t.user_type_id
WHERE [object_id] = OBJECT_ID('AreUdtsBadThough')
+------+---------+
| name | name |
+------+---------+
| @T | GoodUdt |
+------+---------+
该错误有助于描述依赖性问题的一般解决方案:调用 sp_refreshsqlmodule
,它强制有效地重新编译存储过程(或函数、触发器或视图)并更新依赖性:
EXEC sp_refreshsqlmodule 'AreUdtsBadThough'
SELECT p.[name], t.[name]
FROM sys.parameters p
JOIN sys.types t ON p.user_type_id = t.user_type_id
WHERE [object_id] = OBJECT_ID('AreUdtsBadThough')
+------+--------+
| name | name |
+------+--------+
| @T | BadUdt |
+------+--------+
现在 GoodUdt
不再有依赖关系,可以删除了。
依赖关系并不总是得到正确更新(不限于重命名)的问题促使一些人想出了更永久的解决方案。由于改进了依赖性检查,Aaron Bertrand 对 SQL Server 2008 的依赖性自动更新有一个 article(它应该仍然适用于更高版本,即使它可能做的工作比必要的更多)。