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

SQL:将所有记录从一个表插入到另一个表,而不指定列,sql,sql-server,syntax,Sql,Sql Server,Syntax,我想将备份表foo_bk中的所有记录插入到foo表中,而不指定列 如果我尝试这个查询 INSERT INTO foo SELECT * FROM foo_bk 我将得到错误“插入错误:提供的值的列名或数量与表定义不匹配。” 是否可以在不提供列名的情况下从一个表大容量插入到另一个表? 我用谷歌搜索过,但似乎找不到答案。所有答案都需要特定的列。您需要至少有相同数量的列,并且每个列必须以完全相同的方式定义,即varchar列不能插入int列 对于批量传输,请查看您正在使用的SQL实现的文档。通常有

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

如果我尝试这个查询

INSERT INTO foo 
SELECT *
FROM foo_bk
我将得到错误“插入错误:提供的值的列名或数量与表定义不匹配。”

是否可以在不提供列名的情况下从一个表大容量插入到另一个表?
我用谷歌搜索过,但似乎找不到答案。所有答案都需要特定的列。

您需要至少有相同数量的列,并且每个列必须以完全相同的方式定义,即varchar列不能插入int列


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

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

SELECT *
INTO Foo
FROM Bar
WHERE x=y
SQL Server 2000-2005中确实存在
INTO
子句,但仍需要指定列名。2008似乎增加了使用SELECT*的功能

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


但是,INTO子句仅在目标表尚不存在时才起作用。如果您希望将记录添加到现有表中,这不会有帮助。

您不应该希望这样做。选择*不应用作插入的基础,因为列可能会四处移动并打断插入(或者更糟糕的是,不要中断插入操作,而是会弄乱数据。假设有人在select表中向表中添加了一列,而不是另一个表,则代码将中断。或者,假设有人出于无法理解但经常发生的原因,决定在表上进行删除和重新创建,并将列移动到不同的顺序。现在,您的最后一个_name是第一个_name最初所在的位置,选择*会将其放在另一个表中的错误列中。如果无法指定列以及一列到感兴趣的表中所需列的特定映射,则这种做法非常糟糕

现在您可能会遇到几个问题,首先是两个结构不直接匹配,其次是要插入的表有一个标识列,因此即使可插入列是直接匹配的,要插入的表也有一个比另一个多的列,如果不指定数据库,则假定您要尝试插入或者您可能有相同数量的列,但其中一列是标识,因此无法插入(尽管我认为这将是不同的错误消息)。

在另一篇文章中:,您可以执行以下操作:

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

按照其他答案指定列名是很重要的。

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

也就是说,既然您提到这里尝试的目的是备份,也许我们可以使用SQL Server解决这个问题。 由于不知道您的具体情况,因此无法在此处给出正确答案,但我假设:

INSERT INTO new_table (Foo, Bar, Fizz, Buzz)
SELECT Foo, Bar, Fizz, Buzz
FROM initial_table
  • 您希望管理表的备份/审核过程
  • 您可能有一些这样的选项,并且希望避免在添加/删除每一列时更改依赖对象
  • 出于审核目的,备份表可能包含其他列
我想为你提出两个选择:

有效的做法(IMO)是使用DDL触发器检测架构更改,并使用它们相应地更改备份表。这将使您能够使用“选择*自…”方法,因为两个表之间的列列表是一致的

我已经成功地使用了这种方法,您可以利用它让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
我希望这有帮助:)

使用这个

SELECT *
INTO new_table_name
FROM current_table_name

出于某种原因,上述所有答案在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
如果您有主键和外键,此版本的我的答案将非常有用。

您可以尝试以下方法:

SELECT * INTO foo FROM foo_bk

是的,您可以在Sql Server 2000Ah中选择*into,感谢您的澄清。答案相应地更改。请注意,这仅在创建新表时有效。例如,它的功能类似于备份。从语句中可以看出这一点,但我想重申。谢谢!它很有用:)您不需要在此查询中创建,这与insert一起也会创建新表