无法修改用户定义的表类型

时间:2015-08-04 08:05:33

标签: sql sql-server stored-procedures sql-server-2012 user-defined-types

我有一个SQL User-Defined Table Type。它使用了很多 存储过程。现在我需要更改该表类型中的列。 我试图删除并重新创建User-Defined Table Type。但是SQL Server 不允许这样做。它显示以下错误。

Msg 3732, Level 16, State 1, Line 3
Cannot drop type 'dbo.UserDefinedTableType' because it is being referenced by object 'SP_DoSomething'. There may be other objects that reference this type.
Msg 219, Level 16, State 1, Line 3
The type 'dbo.UserDefinedTableType' already exists, or you do not have permission to create it.

如何在不修改使用User-Defined Table Type的所有存储过程的情况下更改User-Defined Table Type

4 个答案:

答案 0 :(得分:3)

您在SP_DoSomething存储过程中具有约束力。您要更改的类型将用于该存储过程。

您需要保存该程序的脚本。算了吧。更改dbo.UserDefinedTableType并再次创建程序。

有一个类似的帖子here。检查是一些可以帮助你的答案。 @norlando的回答似乎很有希望。

答案 1 :(得分:1)

下面的代码虽然不完整应该是一个好的开始。请注意其他许多事情:

  • 你必须适应它(我使用的是用户类型,而不是表类型)并进行测试。
  • 它只处理过程。
  • 如果你的procs定义以alter开头,你需要添加代码和逻辑来控制它并在游标中处理它(先创建空proc然后再改变)。
  • 使用它还将删除所有已授予的权限。
  • ...

    Begin Try 
    Begin Tran
        Declare @procs Table(code nvarchar(max), pname sysname, pschema sysname)
    Declare @sql nvarchar(max), @code nvarchar(max), @pname sysname, @pschema sysname
    Declare cur_drop Cursor For
        Select sp.definition, obj.name, schema_name(obj.schema_id) From sys.sql_modules as sp
        Inner Join sys.objects as obj on obj.object_id = sp.object_id
        Inner Join sys.dm_sql_referencing_entities ('dbo.TestType', 'TYPE') as dep on dep.referencing_id = sp.object_id
        Where obj.Type = 'P'
    Open cur_drop
    Fetch Next From cur_drop Into @code, @pname, @pschema
    
    While @@FETCH_STATUS = 0
    Begin
        Print 'Drop '+@pname 
        Insert into @procs(code, pname, pschema) Select @code, @pname, @pschema
    
        Set @sql = 'Drop proc ['+@pschema+'].['+@pname+']'
        Exec sp_executesql @sql
    
        Fetch Next From cur_drop Into @code, @pname, @pschema
    End
    Close cur_drop
    Deallocate cur_drop
    
    -- Drop Type
    -- Create Type
    
    Declare cur_create Cursor For
        Select code, pname, pschema From @procs
    Open cur_create
    Fetch Next From cur_create Into @code, @pname, @pschema
    
    While @@FETCH_STATUS = 0
    Begin
        Print 'Create '+@pname 
        Exec sp_executesql @code
        Fetch Next From cur_create Into @code, @pname, @pschema
    End
    Close cur_create
    Deallocate cur_create
    
    Commit
    End Try
    Begin Catch
        rollback;
        throw;
    End Catch
    

答案 2 :(得分:1)

您应该删除使用此用户定义表类型的所有函数和存储过程。然后,您可以删除用户定义的表类型并重新创建它。然后,您应该重新创建在上一步中删除的所有存储过程和函数。

您可以使用此命令删除并重新创建所有SP和函数。 我建议您使用Print line运行此命令以创建Drop(s)和Create(s)命令。然后你可以在Drop(s)命令和Create(s)之间输入你的修改。

Declare @fullObjectName NVarChar(1000) = 'ref.Employee'

Declare @CreateCommand VarChar(Max), @DropCommand VarChar(Max)
Declare @ProcList Table 
(  
    RowId Int,
    CreateCommand NVarChar(Max),
    DropCommand NVarChar(Max)
)
Insert Into @ProcList
SELECT ROW_NUMBER() OVER (ORDER BY OBJECT_NAME(m.object_id)) RowId, 
    definition As CreateCommand,
    'DROP ' +
                        CASE OBJECTPROPERTY(referencing_id, 'IsProcedure')
                        WHEN 1 THEN 'PROC '
                        ELSE
                                CASE
                                        WHEN OBJECTPROPERTY(referencing_id, 'IsScalarFunction') = 1 OR OBJECTPROPERTY(referencing_id, 'IsTableFunction') = 1 OR OBJECTPROPERTY(referencing_id, 'IsInlineFunction') = 1 THEN 'FUNCTION '
                                        ELSE ''
                                END
                        END
                + SCHEMA_NAME(o.schema_id) + '.' +
                + OBJECT_NAME(m.object_id)  As DropCommand  
FROM sys.sql_expression_dependencies d
JOIN sys.sql_modules m 
    ON m.object_id = d.referencing_id
JOIN sys.objects o 
    ON o.object_id = m.object_id
WHERE referenced_id = TYPE_ID(@fullObjectName)

-----
Declare cur_drop SCROLL Cursor For Select CreateCommand, DropCommand From @ProcList
OPEN cur_drop
Fetch Next From cur_drop Into @CreateCommand, @DropCommand 
While @@FETCH_STATUS = 0
Begin
        --Exec sp_executesql @DropCommand
        PRINT @DropCommand
        Fetch Next From cur_drop Into @CreateCommand, @DropCommand 
End

/*
Drop And ReCreate User Defined Table Type
*/

Fetch First From cur_drop Into @CreateCommand, @DropCommand 
While @@FETCH_STATUS = 0
Begin
        --Exec sp_executesql @CreateCommand
        PRINT @CreateCommand
        Fetch Next From cur_drop Into @CreateCommand, @DropCommand 
End

Close cur_drop
Deallocate cur_drop

答案 3 :(得分:0)

您可以自动执行临时删除依赖项的过程,然后重新创建它们,因此如果您有很多依赖项,则不应该费心。有关如何自动执行此过程的详细信息,请参阅我的回答here

相关问题