SQL - 将具有默认值的新列添加到DB中的所有表

时间:2017-10-05 14:45:11

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

我有以下声明:

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的表,因此"[]"。我不知道这是否会增加额外的复杂性。

3 个答案:

答案 0 :(得分: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和您的语法的替代解决方案;请注意:

  • 您需要PARSENAME sp_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

'

答案 1 :(得分:1)

很可能无法识别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'

答案 2 :(得分:1)

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

在执行之前评估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
'

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