SQL用户定义的表类型:如果不用作参数,为什么我们可以删除它们?

时间:2016-10-31 09:31:18

标签: sql sql-server tsql user-defined-types

我们都知道,如果SQL用户定义的表值类型(UDT)具有依赖项/依赖项,则不能删除它们。右。

但是,即使他们有家属,今天我也放了一个。唯一的标准是它们不应该用作DB对象的参数,如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,因为它在proc中使用并且不是参数。但是跟随方式它不能被删除。

CREATE PROCEDURE Bar 
    @Identifier FooUDT readonly
as
BEGIN
    --Some operations on @Identifier
END
GO

更有趣的是,在这两种情况下,如果我们检查依赖关系,两者都会显示彼此的名称。然而,前一种情况可以被取消,但后者则不然。为什么会这样呢?或者我错过了什么?

2 个答案:

答案 0 :(得分:4)

SQL Server将存储过程主体存储为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

我会让其他人在这里说话,但我相信如果你试图检查程序主体的依赖关系,你会遇到很多更新异常和级联问题。

答案 1 :(得分:2)

迈克尔·布勒的回答是

只有在drop,存储过程或UDF主体上验证参数;一个简单的例子,说明为什么验证实体是不切实际的,是通过sp_execute_sql存在动态SQL

https://msdn.microsoft.com/en-us/library/ms188001.aspx

另一个原因是需要在每次架构更改时重新编译所有SP / UDF。相反,它们只是按需重新编译,特别是在创建或更改时。

您会看到依赖项,因为它们是在编译时计算的;但由于可能已经发生了变化,因此依赖关系不是最新的,DROP应该适用于不再有效的代码......