SQL Server 2012 - 在没有活动依赖项时无法删除用户定义的 (table) 类型

SQL Server 2012 - Cannot drop User defined (table) type while there are no active dependencies

我有一个用户定义类型,其中一个 VARCHAR 列的大小需要增加。由于依赖关系(使用该类型的存储过程),无法更改类型。所以,我尝试了以下方法:

场景是这样的:

  1. 将类型从 T_MyType 重命名为 T_MyType_1,
  2. 要求 Management Studio 为类型 T_MyType_1
  3. 构建创建脚本
  4. 编辑脚本,从类型名称中删除“_1”并增加一个字段的大小,然后运行脚本,
  5. 运行 导致 t运行cation 问题(列长度)并获得成功结果(没有 t运行cation 或错误消息)的过程,
  6. 尝试删除类型 T_MyType_1 并收到错误,指出该类型正在被过程 ABC 使用,
  7. 在过程 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(它应该仍然适用于更高版本,即使它可能做的工作比必要的更多)。