簡體   English   中英

T-SQL:更改表以添加另一個表中存在的列

[英]T-SQL: alter table to add a column that exists in another table

我正在使用SQL Server 2008中的兩個表: foofoo_mod ,它們具有以下架構:

CREATE TABLE foo
(
    [bar] DATETIME NULL ,
    [bar1] VARCHAR(20) NULL ,
    [different_column] VARCHAR(50) NOT NULL 
)

CREATE TABLE foo_mod
(
     [bar] DATETIME NULL ,
     [bar1] VARCHAR(20) NULL
)

我想構建一個執行以下操作的SQL腳本:

對於foo每一列,請檢查foo_mod中是否存在該列,如果不存在,請更改foo_mod以添加缺少的列。

在此示例中,我的腳本將返回以下內容:

IF COL_LENGTH('foo_mod','bar') IS NULL BEGIN
ALTER TABLE foo_mod 
  ADD bar DATETIME NULLL;
END
IF COL_LENGTH('foo_mod','bar1') IS NULL BEGIN
ALTER TABLE foo_mod 
  ADD bar1 VARCHAR(20) NULL;
END
IF COL_LENGTH('foo_mod','different_column') IS NULL BEGIN
ALTER TABLE foo_mod 
  ADD different_column VARCHAR(50) NOT NULL;
END

現在,我的腳本使用游標從第一個表中遍歷INFORMATION_SCHEMA.COLUMNS

DECLARE @column_name VARCHAR(max);
DECLARE @is_nullable VARCHAR(3);
DECLARE @data_type NVARCHAR(128);
DECLARE @default NVARCHAR(4000);
DECLARE @max_lengh INT;
DECLARE @sql VARCHAR(max);
DECLARE @output VARCHAR(max);
SET @output = '';

DECLARE col_names_cursor CURSOR
FOR
SELECT COLUMN_NAME, IS_NULLABLE, DATA_TYPE, COLUMN_DEFAULT, CHARACTER_MAXIMUM_LENGTH
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = N'foo'

OPEN col_names_cursor
FETCH NEXT FROM col_names_cursor INTO @column_name, @is_nullable, @data_type,@default, @max_lengh;
WHILE @@FETCH_STATUS = 0
BEGIN
    SET @sql = 'IF COL_LENGTH(''foo_mod'','''@column_name''') IS NULL BEGIN ALTER TABLE ''foo_mod'' ADD '
    SET @sql += ? -- build sql script from informations
    FETCH NEXT FROM col_names_cursor INTO @column_name, @is_nullable, @data_type,@default, @max_lengh;
END
CLOSE col_names_cursor;
DEALLOCATE col_names_cursor;

有沒有一種簡單的方法可以根據給定的信息構建SQL語句?

謝謝!

我傾向於在這里使用目錄視圖,而不是INFORMATION_SCHEMA ,因為INFORMATION_SCHEMA不處理標識列或計算列:

為了說明這一點,我對表foo些微改動:

CREATE TABLE foo
(
    ID INT IDENTITY(1, 1),
    [bar] DATETIME NULL ,
    [bar1] VARCHAR(20) NULL ,
    [different_column] VARCHAR(50) NOT NULL ,
    ComputedColumn AS bar1 + different_column
)

然后,您可以查詢目錄視圖以構建您的語句:

SELECT  'ALTER TABLE dbo.Foo_mod ADD ' + c.Name + ' ' + 
            CASE WHEN c.is_computed = 1 THEN 'AS ' + cc.definition
                ELSE t.Name + 
                    CASE WHEN c.is_identity = 1
                            THEN ' IDENTITY(' + CONVERT(VARCHAR(10), ic.seed_value) + ',' + CONVERT(VARCHAR(10), ic.increment_value) + ')'
                        WHEN t.name IN ('CHAR', 'NCHAR', 'VARCHAR', 'NVARCHAR', 'DATETIME2') 
                            THEN '(' + CONVERT(VARCHAR(10), c.max_length) + ')'
                        WHEN t.name IN ('NUMERIC', 'DECIMAL') 
                            THEN '(' + CONVERT(VARCHAR(10), c.precision) + ', ' + CONVERT(VARCHAR(10), c.scale) + ')'
                        ELSE ''
                    END
            END + ';
        GO
        '
FROM    sys.columns AS c
        INNER JOIN sys.types AS t
            ON t.system_type_id = c.system_type_id
            AND t.user_type_id = c.user_type_id
        LEFT JOIN sys.computed_columns AS cc
            ON cc.object_id = c.object_id
            AND cc.column_id = c.column_id
        LEFT JOIN sys.identity_columns AS ic
            ON ic.object_id = c.object_id
            AND ic.column_id = c.column_id
WHERE   c.object_id = OBJECT_ID(N'dbo.foo', 'U')
AND     NOT EXISTS
        (   SELECT  1
            FROM    sys.columns AS c2
            WHERE   c2.object_id = OBJECT_ID(N'dbo.foo_mod')
            AND     c2.name = c.name
        )
ORDER BY c.column_id;

會產生:

ALTER TABLE dbo.Foo_mod ADD ID int IDENTITY(1,1);
GO
ALTER TABLE dbo.Foo_mod ADD different_column varchar(50);
GO
ALTER TABLE dbo.Foo_mod ADD ComputedColumn AS ([bar1]+[different_column]);
GO

現在,您需要做的就是通過將行串聯為一行將其捕獲到變量中並執行它:

DECLARE @SQL NVARCHAR(MAX);

SELECT  @SQL = (SELECT  'ALTER TABLE dbo.Foo_mod ADD ' + c.Name + ' ' + 
                            CASE WHEN c.is_computed = 1 THEN 'AS ' + cc.definition
                                ELSE t.Name + 
                                    CASE WHEN c.is_identity = 1
                                            THEN ' IDENTITY(' + CONVERT(VARCHAR(10), ic.seed_value) + ',' + CONVERT(VARCHAR(10), ic.increment_value) + ')'
                                        WHEN t.name IN ('CHAR', 'NCHAR', 'VARCHAR', 'NVARCHAR', 'DATETIME2') 
                                            THEN '(' + CONVERT(VARCHAR(10), c.max_length) + ')'
                                        WHEN t.name IN ('NUMERIC', 'DECIMAL') 
                                            THEN '(' + CONVERT(VARCHAR(10), c.precision) + ', ' + CONVERT(VARCHAR(10), c.scale) + ')'
                                        ELSE ''
                                    END
                            END + ';
                        GO
                        '
                FROM    sys.columns AS c
                        INNER JOIN sys.types AS t
                            ON t.system_type_id = c.system_type_id
                            AND t.user_type_id = c.user_type_id
                        LEFT JOIN sys.computed_columns AS cc
                            ON cc.object_id = c.object_id
                            AND cc.column_id = c.column_id
                        LEFT JOIN sys.identity_columns AS ic
                            ON ic.object_id = c.object_id
                            AND ic.column_id = c.column_id
                WHERE   c.object_id = OBJECT_ID(N'dbo.foo', 'U')
                AND     NOT EXISTS
                        (   SELECT  1
                            FROM    sys.columns AS c2
                            WHERE   c2.object_id = OBJECT_ID(N'dbo.foo_mod')
                            AND     c2.name = c.name
                        )
                ORDER BY c.column_id
                FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)');

PRINT @SQL;         
EXECUTE sp_executesql @SQL;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM