【问题标题】:Unable to change my custom type in sql server无法更改我在 sql server 中的自定义类型
【发布时间】:2013-11-25 22:25:38
【问题描述】:

我有一个使用以下内容创建的自定义类型:

IF EXISTS (SELECT * FROM sys.types WHERE is_table_type = 1 AND name = 'LineItemType')
BEGIN
    DROP TYPE dbo.LineItemType
END
GO

CREATE TYPE dbo.LineItemType
AS TABLE
(
  Id UNIQUEIDENTIFIER,
  Invoice_Id UNIQUEIDENTIFIER,
  Cost INT,
  Quantity INT,
  Total INT,
  [Description] NVARCHAR(250) 
);
GO

这种类型用作我的一个存储过程的参数,如下所示:

IF EXISTS (SELECT 1 FROM sys.procedures WHERE name = 'AddSomething' AND SCHEMA_NAME(schema_id) = 'dbo')
BEGIN
    DROP PROCEDURE dbo.AddSomething
END
GO

CREATE PROCEDURE AddSomething
    ...
    @LineItems AS dbo.LineItemType READONLY

AS
BEGIN 
    ...

我的问题是我已经决定在我的类型中添加一些列,我在添加列的上方更新了我的脚本,并希望它在我运行它时简单地删除并重新创建,但我得到了这个错误:

消息 3732,级别 16,状态 1,第 4 行无法删除类型 'dbo.LineItemType' 因为它被对象引用 '添点什么'。可能有其他对象引用此类型。 消息 219,级别 16,状态 1,第 8 行类型“dbo.LineItemType”已经 存在,或者您没有创建它的权限。

我错过了什么?如何随时删除我的类型并重新创建它?

谢谢。

【问题讨论】:

    标签: sql sql-server


    【解决方案1】:

    我认为您必须按以下顺序执行此操作。

    1. 删除所有使用 LineItemType 类型的过程。
    2. 删除 LineItemType 类型。
    3. 创建新的 LineItemType 类型。
    4. 创建所有使用 LineItemType 类型的过程。

    简而言之,为所有使用 LineItemType 类型的存储过程生成 CREATE 和 DROP 脚本,然后按照上述顺序。

    【讨论】:

    • 你可以自动化这个过程,看我的回答here
    【解决方案2】:

    我认为您必须按以下顺序执行此操作。

    1. 重命名 LineItemType 类型。

    2. 创建新的 LineItemType 类型

    3.执行所有使用 LineItemType 类型的过程。

    1. 删除 LineItemType 类型。(重命名)

    【讨论】:

      【解决方案3】:

      使用 SSDT 将解决必须手动删除和重新创建引用过程的问题,但此脚本应该会有所帮助:

      create table #tmp(name nvarchar(200), module nvarchar(max))
      insert into #tmp (name, module)
          select distinct '['+ps.name+'].['+p.name+']', m.[definition] from sys.procedures p
              join sys.schemas ps on ps.schema_id=p.schema_id
              join sys.parameters r on r.object_id=p.object_id
              join sys.types t on t.user_type_id=r.user_type_id
              join sys.schemas ts on ts.schema_id=t.schema_id
              join sys.sql_modules m on m.object_id=p.object_id
          where ts.name='dbo' and t.name='ttCustom'    --### pay attention to this line ###
      select * from #tmp
      declare procs scroll cursor for select * from #tmp
          open procs
              declare @name nvarchar(200), @body nvarchar(max)
              while 1=1 begin
                  fetch next from procs into @name, @body
                  if @@FETCH_STATUS <> 0 break
                  set @body = 'drop procedure '+@name
                  exec sp_sqlexec @body
              end
      
              --### re-create the type here ###
              DROP TYPE [dbo].[ttCustom]
              CREATE TYPE [dbo].[ttCustom] AS TABLE (whatever nvarchar(30))
      
              fetch first from procs into @name, @body
              while @@FETCH_STATUS = 0 begin
                  exec sp_sqlexec @body
                  fetch next from procs into @name, @body
              end
          close procs
      deallocate procs
      drop table #tmp
      

      我没有针对其他程序调用的程序对其进行测试,但我认为它们不会成为问题。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-10-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-05-20
        • 1970-01-01
        相关资源
        最近更新 更多