插入…值(SELECT…FROM…)


1426

我正在尝试INSERT INTO使用来自另一个表的输入的表。尽管对于许多数据库引擎来说这是完全可行的,但我似乎总是很难记住当今SQL引擎(MySQLOracleSQL ServerInformixDB2)的正确语法。

是否有来自SQL标准(例如SQL-92)的Silver-bullet语法,该语法可让我插入值而无需担心基础数据库?


1
这个例子的工作原理:INSERT INTO tag_zone选择@标签了zoneid,GETDATE(),@从区域positiong.STIntersects(多边形)
维吾尔族Gümüşhan

Answers:


1611

尝试:

INSERT INTO table1 ( column1 )
SELECT  col1
FROM    table2  

这是标准的ANSI SQL,适用于任何DBMS

它绝对适用于:

  • 甲骨文
  • MS SQL服务器
  • 的MySQL
  • Postgres
  • SQLite v3
  • Teradata
  • DB2
  • Sybase公司
  • Vertica
  • 数据库
  • H2
  • AWS RedShift
  • SAP HANA

944

克劳德·侯勒(Claude Houle)的回答:应该可以正常工作,并且您还可以具有多个列和其他数据:

INSERT INTO table1 ( column1, column2, someInt, someVarChar )
SELECT  table2.column1, table2.column2, 8, 'some string etc.'
FROM    table2
WHERE   table2.ID = 7;

我只在Access,SQL 2000/2005 / Express,MySQL和PostgreSQL中使用了这种语法,因此应该将它们包括在内。它也应该与SQLite3一起使用。


1
如果,where条件更改为table2.country并返回大于一的行数怎么办?我在这里遇到了类似的问题:stackoverflow.com/questions/36030370/…–
vijayrana

1
插入多行应该没有问题。
rinukkusu

我们是否需要将其插入表的所有列中
maheshmnj

1
@maheshmnj否,只有设置为NOT NULL且没有默认值的列才需要包括,其他任何列都将设置为其默认值或NULL
travis

感谢您的信息
maheshmnj

148

为了INSERT从另一个表中获取多值中的一个值,我在SQLite3中执行了以下操作:

INSERT INTO column_1 ( val_1, val_from_other_table ) 
VALUES('val_1', (SELECT  val_2 FROM table_2 WHERE val_2 = something))

4
只是为了澄清:这对于SQLite3是不正确的。按照文档,对于源数据INSERT任一 VALUES或一个SELECT语句,而不是两个。

2
的确文档没有列出它,但是它确实起作用。无论如何,我认为使用select语句代替值确实使它更具可读性。
Banjocat 2014年

1
它适用于在一行中指定一个值,但是更一般的情况是需要获取很多行。
Luchostein 2015年

如果val_1在各行之间没有变化,那么以下语法可能在SQLite3中起作用?从some_table中选择'foo',some_column-在SQLServer 2014中起作用
Chris B

文档的确列出了此内容(现在?):该语法为INSERT INTO ... VALUES ([expr], [expr], ...)并且其中的路径之一[expr]{{NOT} EXISTS} ([select-stmt])-请注意,select语句周围的括号是必需的({}意思是可选的)
zapl

64

我看到的两个答案都特别适合在Informix中使用,并且基本上都是标准SQL。即表示法:

INSERT INTO target_table[(<column-list>)] SELECT ... FROM ...;

与Informix以及所有DBMS配合使用都很好。(从5年前开始,MySQL并不总是支持这种东西;现在,它已经对这种标准SQL语法提供了不错的支持,并且AFAIK可以在这种表示法上正常工作。)列列表是可选的,但按顺序指示目标列,因此SELECT结果的第一列将进入列出的第一列,依此类推。在没有列列表的情况下,SELECT结果的第一列进入目标表的第一列。

系统之间可能会有所不同的是用于标识不同数据库中的表的表示法-该标准对数据库间(更不用说DBMS间)操作了无话可说。使用Informix,可以使用以下表示法来标识表:

[dbase[@server]:][owner.]table

也就是说,您可以指定一个数据库,如果该数据库不在当前服务器中,则可以选择标识托管该数据库的服务器,然后是可选的所有者,点,最后是实际的表名。SQL标准使用术语架构来表示Informix称为所有者。因此,在Informix中,以下任何一种表示法都可以标识一个表:

table
"owner".table
dbase:table
dbase:owner.table
dbase@server:table
dbase@server:owner.table

所有者通常不需要被报价;但是,如果确实使用引号,则需要正确拼写所有者名称-区分大小写。那是:

someone.table
"someone".table
SOMEONE.table

都标识同一张表。使用Informix,使用MODE ANSI数据库会有一个复杂的问题,其中所有者名称通常会转换为大写(informix是例外)。也就是说,在MODE ANSI数据库(不常用)中,您可以编写:

CREATE TABLE someone.table ( ... )

并且系统目录中的所有者名称将为“ SOMEONE”,而不是“ someone”。如果将所有者名称用双引号引起来,则其作用类似于分隔标识符。使用标准SQL,分隔符可以在很多地方使用。使用Informix,您只能在所有者名称周围使用它们-在其他情况下,Informix会将单引号和双引号字符串都视为字符串,而不是将单引号字符串和字符串分开以及将双引号字符串作为分隔标识符。(当然,出于完整性考虑,可以将环境变量DELIMIDENT设置为任何值,但Y最安全-表示双引号始终包围定界标识符,单引号始终包围字符串。)

请注意,MS SQL Server设法使用方括号中包含的[定界标识符]。在我看来,这很奇怪,并且肯定不是SQL标准的一部分。


40

为了在第一个答案中添加一些内容,当我们只希望从另一个表中获取很少的记录时(在此示例中,仅一个):

INSERT INTO TABLE1
(COLUMN1, COLUMN2, COLUMN3, COLUMN4) 
VALUES (value1, value2, 
(SELECT COLUMN_TABLE2 
FROM TABLE2
WHERE COLUMN_TABLE2 like "blabla"),
value4);

4
此方法仅适用于仅选择一列的子查询。对于多列子查询,将引发错误“子查询必须仅返回一列”。然后采用@travis的答案。
snowfox '16

34

大多数数据库都遵循基本语法,

INSERT INTO TABLE_NAME
SELECT COL1, COL2 ...
FROM TABLE_YOU_NEED_TO_TAKE_FROM
;

我用下面的语法即每个数据库DB2SQL ServerMY SQLPostgresQL


34

代替查询的VALUES一部分INSERT,只需使用SELECT以下查询。

INSERT INTO table1 ( column1 , 2, 3... )
SELECT col1, 2, 3... FROM table2

32

使用select子查询插入的两种方法。

  1. 使用SELECT子查询,返回结果为1行
  2. 使用SELECT子查询,返回多行结果。

1.使用SELECT子查询返回一行结果的方法。

INSERT INTO <table_name> (<field1>, <field2>, <field3>) 
VALUES ('DUMMY1', (SELECT <field> FROM <table_name> ),'DUMMY2');

在这种情况下,假设SELECT子查询仅基于WHERE条件或SQL聚合函数(如SUM,MAX,AVG等)返回仅一行结果。否则将引发错误

2.使用SELECT子查询返回多行结果的方法。

INSERT INTO <table_name> (<field1>, <field2>, <field3>) 
SELECT 'DUMMY1', <field>, 'DUMMY2' FROM <table_name>;

第二种方法适用于两种情况。


29

INSERT INTO如果要为零件中的所有列提供值,则无需指定零件中的列即可完成此操作SELECT

假设table1有两列。此查询应该工作:

INSERT INTO table1
SELECT  col1, col2
FROM    table2

这将不起作用(col2未指定的值):

INSERT INTO table1
SELECT  col1
FROM    table2

我正在使用MS SQL Server。我不知道其他RDMS如何工作。



21

当表列顺序已知时,简单插入:

    Insert into Table1
    values(1,2,...)

简单插入提及列:

    Insert into Table1(col2,col4)
    values(1,2)

当表(#table2)的选定列数等于插入表(Table1)时的批量插入

    Insert into Table1 {Column sequence}
    Select * -- column sequence should be same.
       from #table2

当您只想插入表(table1)的所需列时进行批量插入:

    Insert into Table1 (Column1,Column2 ....Desired Column from Table1)  
    Select Column1,Column2..desired column from #table2
       from #table2

17

这是另一个使用多个表获取源的示例:

INSERT INTO cesc_pf_stmt_ext_wrk( 
  PF_EMP_CODE    ,
  PF_DEPT_CODE   ,
  PF_SEC_CODE    ,
  PF_PROL_NO     ,
  PF_FM_SEQ      ,
  PF_SEQ_NO      ,
  PF_SEP_TAG     ,
  PF_SOURCE) 
SELECT
  PFl_EMP_CODE    ,
  PFl_DEPT_CODE   ,
  PFl_SEC         ,
  PFl_PROL_NO     ,
  PF_FM_SEQ       ,
  PF_SEQ_NO       ,
  PFl_SEP_TAG     ,
  PF_SOURCE
 FROM cesc_pf_stmt_ext,
      cesc_pfl_emp_master
 WHERE pfl_sep_tag LIKE '0'
   AND pfl_emp_code=pf_emp_code(+);

COMMIT;

17

只需对SELECT子句使用括号插入INSERT。例如这样:

INSERT INTO Table1 (col1, col2, your_desired_value_from_select_clause, col3)
VALUES (
   'col1_value', 
   'col2_value',
   (SELECT col_Table2 FROM Table2 WHERE IdTable2 = 'your_satisfied_value_for_col_Table2_selected'),
   'col3_value'
);

感谢@Das它的工作对我来说....
拉吉摹

16

这是从多个表插入的方法。此特定示例在多对多场景中都有一个映射表:

insert into StudentCourseMap (StudentId, CourseId) 
SELECT  Student.Id, Course.Id FROM Student, Course 
WHERE Student.Name = 'Paddy Murphy' AND Course.Name = 'Basket weaving for beginners'

(我知道在学生姓名上进行匹配可能返回多个值,但您明白了。当Id是Identity列且未知时,在Id之外进行其他匹配是必要的。)


14
INSERT INTO yourtable
SELECT fielda, fieldb, fieldc
FROM donortable;

这适用于所有DBMS


14

如果要使用SELECT * INTO表插入所有列,可以尝试此操作。

SELECT  *
INTO    Table2
FROM    Table1;

13

我实际上更喜欢SQL Server 2008中的以下内容:

SELECT Table1.Column1, Table1.Column2, Table2.Column1, Table2.Column2, 'Some String' AS SomeString, 8 AS SomeInt
INTO Table3
FROM Table1 INNER JOIN Table2 ON Table1.Column1 = Table2.Column3

它省去了添加Insert()集的步骤,而您只需选择表中包含的值即可。


13

这为我工作:

insert into table1 select * from table2

该句子与Oracle的句子有些不同。


12

对于Microsoft SQL Server,我将建议学习解释MSDN上提供的SYNTAX。使用Google,查找语法比以往任何时候都容易。

对于这种特殊情况,请尝试

Google:插入站点:microsoft.com

第一个结果将是http://msdn.microsoft.com/en-us/library/ms174335.aspx

如果发现难以解释页面顶部给出的语法,请向下滚动至示例(“使用SELECT和EXECUTE选项插入其他表中的数据”)。

[ WITH <common_table_expression> [ ,...n ] ]
INSERT 
{
        [ TOP ( expression ) [ PERCENT ] ] 
        [ INTO ] 
        { <object> | rowset_function_limited 
          [ WITH ( <Table_Hint_Limited> [ ...n ] ) ]
        }
    {
        [ ( column_list ) ] 
        [ <OUTPUT Clause> ]
        { VALUES ( { DEFAULT | NULL | expression } [ ,...n ] ) [ ,...n     ] 
        | derived_table       <<<<------- Look here ------------------------
        | execute_statement   <<<<------- Look here ------------------------
        | <dml_table_source>  <<<<------- Look here ------------------------
        | DEFAULT VALUES 
        }
    }
}
[;]

这应该适用于那里可用的任何其他RDBMS。记住所有产品IMO的所有语法是没有意义的。


我完全不同意,多年来我一直在关注这些语法语句,但仍然无法做出正面或反面的结论。示例更有用
reggaeguitar

这不是答案,而是说“阅读文档”,就是这样
reggaeguitar

12
INSERT INTO FIRST_TABLE_NAME (COLUMN_NAME)
SELECT  COLUMN_NAME
FROM    ANOTHER_TABLE_NAME 
WHERE CONDITION;

@ggorlen对我来说似乎很不言而喻
reggaeguitar

它在审阅队列中标记为仅代码答案。不过,我可以在这里看到您的观点-在此页面上的大多数答案中,鉴于我在自然环境中看到的内容,因此无需多说。
ggorlen

9
select *
into tmp
from orders

看起来不错,但是仅当tmp不存在(创建并填充)时才有效。(SQL服务器)

插入现有的tmp表:

set identity_insert tmp on

insert tmp 
([OrderID]
      ,[CustomerID]
      ,[EmployeeID]
      ,[OrderDate]
      ,[RequiredDate]
      ,[ShippedDate]
      ,[ShipVia]
      ,[Freight]
      ,[ShipName]
      ,[ShipAddress]
      ,[ShipCity]
      ,[ShipRegion]
      ,[ShipPostalCode]
      ,[ShipCountry] )
      select * from orders

set identity_insert tmp off

9

从任何其他表插入多个记录的最佳方法。

INSERT  INTO dbo.Users
            ( UserID ,
              Full_Name ,
              Login_Name ,
              Password
            )
            SELECT  UserID ,
                    Full_Name ,
                    Login_Name ,
                    Password
            FROM    Users_Table
            (INNER JOIN / LEFT JOIN ...)
            (WHERE CONDITION...)
            (OTHER CLAUSE)

2

如果您使用INSERT VALUES路由插入多行,请确保使用括号将VALUES划分为集合,因此:

INSERT INTO `receiving_table`
  (id,
  first_name,
  last_name)
VALUES 
  (1002,'Charles','Babbage'),
  (1003,'George', 'Boole'),
  (1001,'Donald','Chamberlin'),
  (1004,'Alan','Turing'),
  (1005,'My','Widenius');

否则,MySQL对象会出现“列数与第1行的值计数不匹配”的情况,最终当您弄清楚该怎么做时,您将写一篇琐碎的文章。


6
问题是“使用另一个表的输入插入表中 ”。您的答案如何解决这个问题?
Quality Catalyst

3
呃不要对他太刻薄。当我四处搜寻时,它回答了我的问题。@QualityCatalyst
Cameron Belt



0

如果您想在表中插入一些数据而又不想写列名。

INSERT INTO CUSTOMER_INFO
   (SELECT CUSTOMER_NAME,
           MOBILE_NO,
           ADDRESS
      FROM OWNER_INFO cm
     WHERE ID>100)

这些表在哪里:

            CUSTOMER_INFO               ||            OWNER_INFO
----------------------------------------||-------------------------------------
CUSTOMER_NAME | MOBILE_NO | ADDRESS     || CUSTOMER_NAME | MOBILE_NO | ADDRESS 
--------------|-----------|---------    || --------------|-----------|--------- 
      A       |     +1    |   DC        ||       B       |     +55   |   RR  

结果:

            CUSTOMER_INFO               ||            OWNER_INFO
----------------------------------------||-------------------------------------
CUSTOMER_NAME | MOBILE_NO | ADDRESS     || CUSTOMER_NAME | MOBILE_NO | ADDRESS 
--------------|-----------|---------    || --------------|-----------|--------- 
      A       |     +1    |   DC        ||       B       |     +55   |   RR
      B       |     +55   |   RR        ||
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.