无法修改用户定义的 Table 类型
Unable to Modify User-Defined Table Type
我有一个SQLUser-Defined Table Type
。它用于许多
存储 procedures.Now 我需要更改 table 类型的列。
我试图删除并重新创建 User-Defined Table Type
。但是 SQL 服务器
不允许这样做。它显示以下错误。
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
?
您在 SP_DoSomething
存储过程中有绑定。您要更改的类型已在该存储过程中使用。
您需要保存该程序的脚本。算了吧。更改 dbo.UserDefinedTableType
并重新创建过程。
还有一个类似的posthere。检查是一些答案可以帮助你。 @norlando 的回答似乎很有希望。
下面的代码虽然不完整,但应该是一个好的开始。请注意,除其他事项外:
- 你必须调整它(我使用的是用户类型,而不是 table 类型)并测试它。
- 它只处理过程。
- 如果你的procs定义以alter开始,你需要添加代码和逻辑来控制它并在游标中处理它(先创建空proc然后alter)。
- 使用它也将删除所有授予的 procs 权限。
...
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
您可以自动执行临时删除依赖项然后重新创建它们的过程,因此如果您有很多依赖项,则不必费心。有关如何自动执行此过程的说明,请参阅我的回答 here。
总的来说,您应该删除所有使用此用户定义 Table 类型的函数和存储过程。然后您可以删除 User-Defined Table Type 并重新创建它。然后您应该重新创建您在上一步中删除的所有存储过程和函数。
您可以使用此命令删除并重新创建所有 SP 和函数。
我建议您使用 运行 这个带有 Print 行的命令来创建 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
我有一个SQLUser-Defined Table Type
。它用于许多
存储 procedures.Now 我需要更改 table 类型的列。
我试图删除并重新创建 User-Defined Table Type
。但是 SQL 服务器
不允许这样做。它显示以下错误。
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
?
您在 SP_DoSomething
存储过程中有绑定。您要更改的类型已在该存储过程中使用。
您需要保存该程序的脚本。算了吧。更改 dbo.UserDefinedTableType
并重新创建过程。
还有一个类似的posthere。检查是一些答案可以帮助你。 @norlando 的回答似乎很有希望。
下面的代码虽然不完整,但应该是一个好的开始。请注意,除其他事项外:
- 你必须调整它(我使用的是用户类型,而不是 table 类型)并测试它。
- 它只处理过程。
- 如果你的procs定义以alter开始,你需要添加代码和逻辑来控制它并在游标中处理它(先创建空proc然后alter)。
- 使用它也将删除所有授予的 procs 权限。
...
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
您可以自动执行临时删除依赖项然后重新创建它们的过程,因此如果您有很多依赖项,则不必费心。有关如何自动执行此过程的说明,请参阅我的回答 here。
总的来说,您应该删除所有使用此用户定义 Table 类型的函数和存储过程。然后您可以删除 User-Defined Table Type 并重新创建它。然后您应该重新创建您在上一步中删除的所有存储过程和函数。
您可以使用此命令删除并重新创建所有 SP 和函数。 我建议您使用 运行 这个带有 Print 行的命令来创建 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