【问题标题】:SQL - Add a new column with a default value to all tables in the DBSQL - 向数据库中的所有表添加具有默认值的新列
【发布时间】:2017-10-05 14:45:10
【问题描述】:

我有如下声明:

EXEC sp_MSforeachtable '
    DECLARE @defaultId integer;
    SET @defaultId = 13;

    IF EXISTS(SELECT name FROM sys.sysobjects WHERE Name = N''?'' AND xtype = N''U'')
    BEGIN   
        IF COL_LENGTH(''[?]'',''NewColumn'') IS NULL
        BEGIN
            ALTER TABLE [?] ADD NewColumn integer null
            UPDATE [?]
            SET NewColumn = @defaultId
        END
    END
'

我正在尝试将NewColumn 列添加到我的数据库中没有它的所有表中,并将默认值设置为13。我执行它,它说它成功完成,但没有任何改变。我在这里做错了什么?


注意:我有一个名为 User 的表,因此是 "[]"。我不知道这是否会增加额外的复杂性。

【问题讨论】:

  • 旁白:您可能想看看QuoteName()。提示:使用适当的软件(MySQL、Oracle、DB2 等)和版本标记数据库问题很有帮助,例如sql-server-2014。语法和功能的差异通常会影响答案。请注意,tsql 缩小了选择范围,但没有指定数据库。
  • @HABO 谢谢。我已经相应地更新了标签。
  • 虽然在下面接受的答案中提到:名为 USER 的表在这里不是问题。

标签: sql sql-server tsql sql-server-2016


【解决方案1】:

我不是特别喜欢调试sp_MSforeachtable 代码所以我建议你这个方法:

DECLARE @Name AS VARCHAR(128)

DECLARE C_Table CURSOR FOR
    SELECT sys.objects.Name
    FROM sys.objects
    WHERE sys.objects.type = 'U' AND
        sys.objects.Name NOT IN (
            SELECT DISTINCT sys.objects.Name
            FROM sys.objects INNER JOIN
            sys.columns ON sys.objects.object_id = sys.columns.object_id 
            WHERE sys.objects.type = 'U' AND
                sys.columns.Name = 'NewColumn'
        )

OPEN C_Table
FETCH NEXT FROM C_Table INTO @Name

WHILE @@FETCH_STATUS = 0
BEGIN

    EXEC('ALTER TABLE ' + @Name + ' ADD NewColumn INTEGER NULL')
    EXEC('ALTER TABLE ' + @Name + ' ADD CONSTRAINT DF_' + @Name + '_A DEFAULT 13 FOR NewColumn')
    EXEC('UPDATE ' + @Name + ' SET NewColumn = 13')

    FETCH NEXT FROM C_Table INTO @Name

END

CLOSE C_Table
DEALLOCATE C_Table

这是使用sp_MSforeachtable 和您的语法的替代解决方案;请注意:

  • 你需要PARSENAMEsp_MSforeachtable提供的名称(即[yourschema].[yourtable]),因为sys.objects.name只包含表名(即:yourtable
  • 您必须使用 2 步,因为似乎无法在 sp_MSforeachtable 内使用 GO
  • 你不能在ALTER TABLE中使用变量,但你必须指定一个固定的DEFAULT

这是代码:

EXEC sp_MSforeachtable '

    IF EXISTS(SELECT * FROM sys.sysobjects WHERE Name = PARSENAME(''?'', 1) AND xtype = N''U'')
    BEGIN   
        IF COL_LENGTH(PARSENAME(''?'', 1), ''NewColumn'') IS NULL
        BEGIN
            ALTER TABLE ? ADD NewColumn INT NULL DEFAULT(13)
        END
    END

'

EXEC sp_MSforeachtable '

    DECLARE @defaultId INT
    SELECT @defaultId = 13

    IF EXISTS(SELECT * FROM sys.sysobjects WHERE Name = PARSENAME(''?'', 1) AND xtype = N''U'')
    BEGIN   
        IF NOT COL_LENGTH(''?'', ''NewColumn'') IS NULL
        BEGIN
            UPDATE ? SET NewColumn = @defaultId
        END
    END

'

【讨论】:

  • 遇到了问题,因为我有一个名为 User 的表,但我已将其重命名为其他名称,现在可以使用了。
  • @kei:这不是你的问题的答案。你的说法有两个问题:1.你需要解析正确的表名。 2.你必须分开步骤。它与名为 USER 的表无关
【解决方案2】:

NewColumn 很可能无法识别。试试

EXEC sp_MSforeachtable '
DECLARE @defaultId integer;
SET @defaultId = 13;
IF EXISTS(SELECT name FROM sys.sysobjects WHERE Name = PARSENAME(''?'',1) AND xtype = N''U'')
BEGIN   
    IF COL_LENGTH(''?'',''NewColumn'') IS NULL
    BEGIN
        ALTER TABLE ? ADD NewColumn integer null
        EXEC(CONCAT(''UPDATE ? SET NewColumn = '', @defaultId))
    END
END'

【讨论】:

  • @kei 将其放在这里,以便您了解最初问题的原因。 ? 包括架构,所以首先 IF 总是返回 false。更新了我的答案以供将来参考
【解决方案3】:

您需要分两步完成此操作。

update语句在执行前被求值,会抛出错误(因为此时没有列)

第 1 步(更改表):

EXEC sp_MSforeachtable '

IF EXISTS(SELECT * FROM sys.sysobjects WHERE Name = parsename(N''?'', 1) AND xtype = N''U'')
BEGIN   
    IF COL_LENGTH(''[?]'',''NewColumn'') IS NULL
    BEGIN
        ALTER TABLE [?] ADD NewColumn integer null
    END
END
'

第2步(设定值):

EXEC sp_MSforeachtable '
DECLARE @defaultId integer;
SET @defaultId = 13;

IF EXISTS (SELECT * FROM sys.sysobjects WHERE Name = parsename(N''?'', 1) AND xtype = N''U'')
BEGIN   
    IF COL_LENGTH(''[?]'',''NewColumn'') IS not NULL
    BEGIN
        UPDATE [?]
        SET NewColumn = @defaultId
    END
END
'

您提到了一个默认值。您仅使用固定值更新了新列的值,而没有定义默认值。这可能是一个区别,尽管对于这个问题并不重要。

【讨论】:

  • 没有错误信息。与我在原始代码中得到的类似。
  • 更改并添加了 parsename-function。 MS_foreachtable 返回“schema.table”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-06-08
  • 2010-09-08
  • 2017-08-31
  • 2010-09-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多