将数据追加到具有相同列但顺序不同的另一个表中

时间:2019-08-09 21:09:40

标签: sql-server sql-insert

我正在使用SQL Server,我想编写一个查询以将表1中的数据追加到表2中,该表中已经有一些数据。

这是我当前正在使用的,但这仅在列以完全相同的顺序完全相同时才起作用。我的2个表具有相同的列,但是顺序不同。有200多个列,所以我不想手动对其重新排序或在查询中列出它们。

INSERT INTO table2
    SELECT * FROM table1

这是我可以做到的一种方法,但是有没有一种方法可以将table1中的数据追加到table2中而不必指定每一列?

INSERT INTO table2
    SELECT column1, column2 (in the order of table2 columns)
    FROM table1

3 个答案:

答案 0 :(得分:0)

我同意Elaskanator关于明确列出您的列名的警告。但是,此方法将起作用。

在table1上创建一个具有table2列顺序的视图(vw_table1)。您将需要在视图中指定正确的列顺序。

INSERT INTO table2
SELECT * FROM vw_table1

如果您只需要用逗号分隔的列列表,则可以通过多种方式获得...

  • 查询table2,并指定结果为文本,然后将所有空格替换为一个逗号和一个可读性的空格。
  • 查询table2,将带有标题的内容复制到Excel,另存为CSV,然后从结果文件中复制第一行。
  • 如果您具有RedGate,请在SELECT * FROM table2中的“ *”之后单击“ Tab”,它将为您列出它们。

答案 1 :(得分:0)

使用exec进行构建是一种不太整洁但可能实用的方法。 string_agg仅在2017年可用

declare @col_names nvarchar(max) = (
  select string_agg(column_name, ',')
  from information_schema.columns
  where table_name = N'table1'
)

exec ('insert into table2 (' + @col_names + ') select ' + @col_names + ' from table1')

对于SQL Server 2017之前的评论:

declare @col_names nvarchar(max)
select @col_names = ISNULL(@col_names + ', [' + column_name + ']', '[' + column_name + ']')
from information_schema.columns
where table_name = @dest

答案 2 :(得分:0)

永远不要编写缺少明确列列表的INSERT语句,否则将来如果有人重新排序列(在表中间添加新列时也会发生这种情况) ),所有内容都会突然开始崩溃(希望如此,因为您可能最终会插入隐式转换一段时间的值,稍后导致随机故障,这将使您的生活陷入困境)。

如果您最关心的是列的数量庞大,这使得编写该语句非常困难(您是在水平存储数据还是在某种程度上保存数据?),请使用动态SQL来朝正确的方向前进:

DECLARE @TableName NVARCHAR(255) = N'MyBigassTable'--SET ME
DECLARE @ColumnList NVARCHAR(MAX) = NULL--build column list string
SELECT @ColumnList = ISNULL(@ColumnList + CHAR(13) + CHAR(10) + CHAR(9) + ',', CHAR(9) + ' ') + QUOTENAME(C.name)
FROM--ordering is guaranteed to match with the current table definition, presumably from clustered index on the sys.columns table?
    sys.tables AS T
    INNER JOIN sys.columns AS C ON
        C.object_id = T.object_id
        AND C.is_identity = 0--https://docs.microsoft.com/en-us/sql/t-sql/statements/set-identity-insert-transact-sql
        AND C.is_computed = 0--https://docs.microsoft.com/en-us/sql/relational-databases/tables/specify-computed-columns-in-a-table
WHERE T.name = @TableName--beware if you have multiple schemas with the same table name
--form the insert statement
DECLARE @InsertQuery NVARCHAR(MAX) =
    N'INSERT INTO ' + QUOTENAME(@TableName) + CHAR(13) + CHAR(10)
    +'(' + CHAR(13) + CHAR(10)
    + @ColumnList + CHAR(13) + CHAR(10)
    + ')' + CHAR(13) + CHAR(10)
    + 'SELECT' + CHAR(13) + CHAR(10)
    + @ColumnList
--output results, handling maximum print size limitation
DECLARE @i INT = 1, @Step INT = 4000
WHILE @i < LEN(@InsertQuery) BEGIN
    PRINT SUBSTRING(@InsertQuery, @i, @Step)--you will have to manually fix newlines created by PRINT batches
    SET @i += @Step
END

抽样结果

INSERT INTO [MyBigassTable]
(
     [ID]
    ,[Name]
    ...
)
SELECT
     [ID]
    ,[Name]
    ...

请注意,CHAR(13) + CHAR(10)\r\n(回车加换行符,或 Return ),而CHAR(9)\t Tab < / kbd>)。

现在根据需要自定义结果。