SQL 用户定义 Table 类型:如果不用作参数,为什么我们可以删除它们?
SQL User Defined Table Types: Why can we drop them if not used as parameter?
我们都知道 SQL 用户定义 Table 值 Table 类型 (UDT) 如果有 dependents/dependencies 则不能删除。对。
但是,今天我放弃了一个,即使他们有家属。唯一的标准是它们不应该用作 proc 或 func 等数据库对象的参数。
CREATE TYPE FooUDT AS TABLE
(
ID int NOT NULL
)
依赖
CREATE PROCEDURE Bar
as
BEGIN
DECLARE @Identifier FooUDT
--Some operations on @Identifier
END
GO
FooUDT
可以删除,因为它在过程中使用并且不是参数。但是下面的方法是不能删除的。
CREATE PROCEDURE Bar
@Identifier FooUDT readonly
as
BEGIN
--Some operations on @Identifier
END
GO
更有趣的是,在这两种情况下,如果我们检查依赖关系,两者都会显示彼此的名称。但是前者可以去掉,后者不能。这是为什么呢?还是我遗漏了什么?
SQL 服务器将存储过程主体存储为您的 DECLARE @Identifier FooUDT
在过程主体中的文本。
Select text, *
from sysobjects A
JOIN syscomments B
On A.id = B.id
where xtype = 'P'
然而,参数存储在元数据中。您可以按以下方式查看它们...
SELECT SCHEMA_NAME(SCHEMA_ID) AS[Schema],
SO.name AS[ObjectName],
SO.Type_Desc AS[ObjectType(UDF / SP)],
P.parameter_id AS[ParameterID],
P.name AS[ParameterName],
TYPE_NAME(P.user_type_id) AS[ParameterDataType],
P.max_length AS[ParameterMaxBytes],
P.is_output AS[IsOutPutParameter]
FROM sys.objects AS SO
INNER JOIN sys.parameters AS P
ON SO.OBJECT_ID = P.OBJECT_ID
WHERE SO.OBJECT_ID IN(SELECT OBJECT_ID FROM sys.objects WHERE TYPE IN('P', 'FN'))
ORDER BY[Schema], SO.name, P.parameter_id
我会让其他人在这里插话,但我相信如果您尝试检查过程主体的依赖关系,您会 运行 陷入相当多的更新异常和级联问题。
Michael Buller 的回答很准确
只有参数在删除时被验证,存储过程或 UDF 主体不是;为什么验证主体不切实际的一个简单示例是动态 SQL 到 sp_execute_sql
的存在
https://msdn.microsoft.com/en-us/library/ms188001.aspx
另一个原因是需要在每次架构更改时重新编译所有 SPs/UDFs。相反,它们只会根据需要重新编译,尤其是在创建或更改时。
您看到依赖项是因为它们是在编译时计算的;但由于可能发生了变化,依赖项不一定是最新的,DROP 应该适用于不再有效的代码...
我们都知道 SQL 用户定义 Table 值 Table 类型 (UDT) 如果有 dependents/dependencies 则不能删除。对。
但是,今天我放弃了一个,即使他们有家属。唯一的标准是它们不应该用作 proc 或 func 等数据库对象的参数。
CREATE TYPE FooUDT AS TABLE
(
ID int NOT NULL
)
依赖
CREATE PROCEDURE Bar
as
BEGIN
DECLARE @Identifier FooUDT
--Some operations on @Identifier
END
GO
FooUDT
可以删除,因为它在过程中使用并且不是参数。但是下面的方法是不能删除的。
CREATE PROCEDURE Bar
@Identifier FooUDT readonly
as
BEGIN
--Some operations on @Identifier
END
GO
更有趣的是,在这两种情况下,如果我们检查依赖关系,两者都会显示彼此的名称。但是前者可以去掉,后者不能。这是为什么呢?还是我遗漏了什么?
SQL 服务器将存储过程主体存储为您的 DECLARE @Identifier FooUDT
在过程主体中的文本。
Select text, *
from sysobjects A
JOIN syscomments B
On A.id = B.id
where xtype = 'P'
然而,参数存储在元数据中。您可以按以下方式查看它们...
SELECT SCHEMA_NAME(SCHEMA_ID) AS[Schema],
SO.name AS[ObjectName],
SO.Type_Desc AS[ObjectType(UDF / SP)],
P.parameter_id AS[ParameterID],
P.name AS[ParameterName],
TYPE_NAME(P.user_type_id) AS[ParameterDataType],
P.max_length AS[ParameterMaxBytes],
P.is_output AS[IsOutPutParameter]
FROM sys.objects AS SO
INNER JOIN sys.parameters AS P
ON SO.OBJECT_ID = P.OBJECT_ID
WHERE SO.OBJECT_ID IN(SELECT OBJECT_ID FROM sys.objects WHERE TYPE IN('P', 'FN'))
ORDER BY[Schema], SO.name, P.parameter_id
我会让其他人在这里插话,但我相信如果您尝试检查过程主体的依赖关系,您会 运行 陷入相当多的更新异常和级联问题。
Michael Buller 的回答很准确
只有参数在删除时被验证,存储过程或 UDF 主体不是;为什么验证主体不切实际的一个简单示例是动态 SQL 到 sp_execute_sql
的存在https://msdn.microsoft.com/en-us/library/ms188001.aspx
另一个原因是需要在每次架构更改时重新编译所有 SPs/UDFs。相反,它们只会根据需要重新编译,尤其是在创建或更改时。
您看到依赖项是因为它们是在编译时计算的;但由于可能发生了变化,依赖项不一定是最新的,DROP 应该适用于不再有效的代码...