SQL - 向数据库中的所有表添加一个具有默认值的新列

SQL - Add a new column with a default value to all tables in the DB

我有以下声明:

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 列添加到我的数据库中所有没有它的 table 并将默认值设置为 13。我执行它,它说它成功完成,但没有任何改变。我在这里做错了什么?


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

我不是特别喜欢调试 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 仅包含 table 名称(即: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

'

很可能 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'

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

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

第 1 步(更改 table):

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
'

您提到了默认值。您只使用固定值更新了新列的值,而没有定义默认值。这可能是一个差异,但对于这个问题并不重要。