SQL:将所有记录从一个表插入另一个表而不指定列

时间:2009-08-12 17:00:09

标签: sql sql-server syntax

我想将备份表foo_bk中的所有记录插入到foo表中而不指定列。

如果我尝试这个查询

INSERT INTO foo 
SELECT *
FROM foo_bk

我会收到错误“插入错误:列名或提供的值数与表定义不匹配。”

是否可以在不提供列名的情况下从一个表批量插入到另一个表? 我谷歌它但似乎无法找到答案。所有答案都需要特定的栏目。

8 个答案:

答案 0 :(得分:17)

你不应该这样做。选择*不应该用作插入的基础,因为列可能会移动并破坏插入(或者更糟糕的是不会破坏插入但是会弄乱你的数据。假设有人在select中添加了一列而不是在其他表中,您的代码将会中断。或者假设有人因为超出理解但经常发生的原因,决定执行删除并在表上重新创建并将列移动到不同的顺序。现在您的last_name是第一个名称是在原来和select *会将它放在另一个表中的错误列中。如果没有指定列以及一列到您感兴趣的表中所需列的特定映射,这是一种极其糟糕的做法。

现在你可能有几个问题,首先两个结构不直接匹配,或者第二个被插入的表有一个标识列,所以即使可插入列是直接匹配,插入的表有一个比另一列更多的列并且未指定数据库假定您将尝试插入该列。或者您可能具有相同数量的列,但一个是标识,因此无法插入(尽管我认为这将是一个不同的错误消息)。

答案 1 :(得分:11)

根据其他帖子:Insert all values of a...,您可以执行以下操作:

INSERT INTO new_table (Foo, Bar, Fizz, Buzz)
SELECT Foo, Bar, Fizz, Buzz
FROM initial_table

指定列名称非常重要,如其他答案所示。

答案 2 :(得分:10)

使用此

SELECT *
INTO new_table_name
FROM current_table_name

答案 3 :(得分:2)

您需要至少具有相同数量的列,并且必须以完全相同的方式定义每个列,即无法将varchar列插入到int列中。

对于批量传输,请查看您正在使用的SQL实现的文档。通常有工具可用于将数据从一个表批量传输到另一个表。例如,对于SqlServer 2005,您可以使用SQL Server导入和导出向导。右键单击要尝试移动数据的数据库,然后单击“导出”以访问它。

答案 4 :(得分:1)

如果使用SELECT INTO而不是INSERT INTO / SELECT,SQL 2008允许您放弃在SELECT中指定列名:

SELECT *
INTO Foo
FROM Bar
WHERE x=y

SQL Server 2000-2005中确实存在INTO子句,但仍需要指定列名。 2008似乎增加了使用SELECT *的能力。

有关详细信息,请参阅有关INTO(SQL2005),(SQL2008)的MSDN文章。

但是,INTO子句仅在目标表尚不存在时才有效。如果您要将记录添加到现有表中,这将无济于事。

答案 5 :(得分:0)

正如你可能从之前的答案中所理解的那样,你无法真正做到你所追求的。 我认为您可以理解SQL Server遇到的问题,而不知道如何映射其他/缺少的列。

那就是说,既然你提到你在这里尝试的目的是备份,也许我们可以使用SQL Server并解决问题。 不知道你的具体情况会导致无法在这里找到正确答案,但我假设如下:

  • 您希望管理表格的备份/审核流程。
  • 您可能只有其中的一些,并希望避免在每个列添加/删除时更改依赖对象。
  • 备份表可能包含其他列以供审核。

我想为您提出两个选择:

高效练习(IMO)可以使用DDL触发器检测架构更改,并使用它们相应地更改备份表。这将使您能够使用'select * from ...'方法,因为列表将在两个表之间保持一致。

我已成功使用此方法,您可以利用它来让DDL触发器自动管理审核表。就我而言,我对需要审计的表使用了命名约定,而DDL触发器只是动态管理它。

对您的特定方案可能有用的另一个选项是为对齐列列表的表创建支持视图。这是一个简单的例子:

create table foo (id int, name varchar(50))
create table foo_bk (id int, name varchar(50), tagid int)
go

create view vw_foo as select id,name from foo 
go

create view vw_foo_bk as select id,name from foo_bk
go

insert into vw_foo
    select * from vw_foo_bk 
go

drop view vw_foo
drop view vw_foo_bk
drop table foo
drop table foo_bk
go

我希望这会有所帮助:)

答案 6 :(得分:0)

以上所有答案(由于某种原因或其他原因)在SQL Server 2012上对我均不起作用。我的情况是我不小心删除了所有行而不是仅删除了一行。在我们的DBA将表还原到dbo.foo_bak之后,我使用了以下内容进行还原。 注意:仅当备份表(由dbo.foo_bak表示)和您要写入的表(dbo.foo)具有完全相同的列名时,此方法才有效。

这是我使用一堆不同答案的结果:

USE [database_name];
GO
SET IDENTITY_INSERT dbo.foo ON;
GO
INSERT INTO [dbo].[foo]
           ([rown0]
           ,[row1]
           ,[row2]
           ,[row3]
           ,...
           ,[rown])
     SELECT * FROM [dbo].[foo_bak];
GO
SET IDENTITY_INSERT dbo.foo OFF;
GO

如果您具有主键和外键,则此版本的答案很有帮助。

答案 7 :(得分:0)

您可以尝试以下方法:

SELECT * INTO foo FROM foo_bk