【问题标题】:How to ALTER the Table Value Parameter如何更改表值参数
【发布时间】:2010-12-16 14:42:47
【问题描述】:

当我右击 TVP 时,我没有得到像“ALTER TO”这样的选项

【问题讨论】:

  • 更改为 TVP?? TVP 是函数/过程定义的一部分。本身不是一个实体!?
  • ALTER TO 选项未启用 RT ?
  • 表值参数是 SQL Server 2008 中的一种新参数类型。表值参数是使用用户定义的表类型声明的。我猜你是在问关于 ALTERing 用户定义的表类型?据我所知,您可以创建和删除用户定义的表类型,但不能更改它。

标签: sql-server tsql table-valued-parameters


【解决方案1】:

做不到。您必须删除/重新创建。如果您对 TVP 有依赖项,则必须:

  1. 以新名称创建新 TVP
  2. 更改要使用的依赖项 (1)
  3. 放弃旧的 TVP
  4. 以原始名称重新创建 (1)
  5. 更改要使用的依赖项 (4)
  6. 掉落 (1)

【讨论】:

  • 谢谢,但麻烦很糟糕。
  • 为什么要使用新名字?
  • 你不能有两个同名的类型,如果它被另一个对象引用,你不能删除旧类型。如果您不介意先删除所有引用对象,然后删除类型,那么您可以直接使用相同的名称重新创建它,而无需经历这种舞蹈。但是,如果您不能承受首先删除引用对象的代价,因为您承受不起任何停机时间,那么您必须经历这个过程。
【解决方案2】:

我找到了一个blog post on sqltreeo.com,它可以通过临时删除依赖项然后重新创建它们来自动化该过程。

我只是稍微修改了一下。

1.您应该创建以下程序:

-- Find all referencing objects to user-defined table type in @fullObjectName parameter
-- and generate DROP scripts and CREATE scripts for them
CREATE PROC [dbo].[alterTableType] (@fullObjectName VARCHAR(200))
AS
BEGIN
    SET NOCOUNT ON

    IF (TYPE_ID (@fullObjectName) IS NULL)
    BEGIN
        RAISERROR ('User-defined table type ''%s'' does not exists. Include full object name with schema.', 16,1, @fullObjectName)
        RETURN
    END;

    WITH sources
    AS
    (
        SELECT ROW_NUMBER() OVER (ORDER BY OBJECT_NAME(m.object_id)) RowId, definition
        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)
    )
    SELECT 'BEGIN TRANSACTION'
    UNION ALL   
    SELECT 

        '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)    

    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)
    UNION  ALL
    SELECT  'GO'
    UNION ALL
    SELECT CHAR(13) + CHAR(10) + '---- WRITE HERE SCRIPT TO DROP OLD USER DEFINED TABLE TYPE AND CREATE A NEW ONE ----' + CHAR(13) + CHAR(10)
    UNION  ALL
    SELECT
        CASE
            WHEN number = RowId    THEN DEFINITION
            ELSE 'GO'
        END
     FROM sources s
    JOIN (SELECT DISTINCT number FROM master.dbo.spt_values) n ON n.number BETWEEN RowId AND RowId+1
    UNION ALL
    SELECT 'COMMIT'
END

2.然后你应该使用你的表类型名称作为输入参数来运行它。以网格格式显示结果(因为文本格式可能会截断长文本),选择整个结果表并将其复制到新的查询窗口。

【讨论】:

  • 带有 Create 的行似乎缺少 CR+LF。当我将其粘贴到新的查询窗口或文本编辑器中时,它粘贴为一大行。我使用的是在 SS 2008 R2 上运行的 SSMS 2016。
  • 查看此答案以使 SSMS 网格结果在副本上保留 CR/LF stackoverflow.com/a/37284582/3055415
  • 出色的工具 - CR+LF。是个问题,但这节省了很多时间
【解决方案3】:

问题

您不能删除用户定义的表类型,只要它被其他任何东西引用:

无法删除类型“dbo.MyTableType”,因为对象“MyStoredProcedure”正在引用它。可能有其他对象引用此类型。

如果 SSMS 为您提供所有其他对象的列表,那就太好了,但如果您没有很多,部分手动的方法可能会很好。

查找用法

要获取所有使用您的TVP类型的SP列表,您可以查询sys.sql_expression_dependencies

SELECT OBJECT_NAME(d.referencing_id)
FROM sys.sql_expression_dependencies d
WHERE d.referenced_id = TYPE_ID('MyTableType')

步骤

  1. 选择上面确定的所有 SP 并选择 DROP and CREATE to new window
  2. 浏览每个窗口,然后突出显示/执行DROP PROCEDURE 部分
  3. 现在您可以选择您的类型并选择DROP and CREATE to新窗口并进行任何更改
  4. 返回您打开的 SP 窗口列表并执行 CREATE 部分

进一步阅读

【讨论】:

    【解决方案4】:
    1. 删除所有使用您要更改的 TVP 的 SP。(不要忘记获取 SP 和 TVP 的备份)
    2. 现在删除您必须更改的 TVP。
    3. 修改您在第 2 步中删除的同一 TVP 并再次创建它。(此处更改了 TVP)。
    4. 现在再次创建您在第一步中丢弃的所有 SP。 (您的 SP 已准备好与更改的 TVP 一起使用)。

    您将取回 TVP 和所有使用相同 TVP 的 Sp。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-19
      • 1970-01-01
      • 1970-01-01
      • 2022-11-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多