提问



我正在尝试使用另一个表的输入INSERT INTO表。虽然这对于许多数据库引擎来说完全可行,但我似乎总是很难记住当前SQL引擎(MySQL,Oracle,SQL Server,Informix和DB2)的正确语法。[46] [47] [48] [49] [50]


是否有来自SQL标准的银弹语法(例如,SQL-92)允许我插入值而不必担心底层数据库?[51]

最佳参考


尝试:


INSERT INTO table1 ( column1 )
SELECT  col1
FROM    table2  


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


它肯定适用于:



  • Oracle

  • MS SQL Server

  • MySQL

  • Postgres

  • SQLite v3

  • Teradata的

  • DB2

  • 的Sybase

  • Vertica的

  • HSQLDB

  • H2

  • AWS RedShift

  • SAP HANA


其它参考1


@ Shadow_x99:这应该可以正常工作,你也可以有多列和其他数据:


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一起使用。

其它参考2


要从另一个表中获取多值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))

其它参考3


我看到的两个答案都在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标准使用术语schema来表示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,而不是某人。如果将所有者名称括在双引号中,则它就像一个分隔标识符。使用标准SQL,可以在许多地方使用分隔标识符。使用Informix,您只能在所有者名称周围使用它们 - 在其他上下文中,Informix将单引号和双引号字符串视为字符串,而不是将单引号字符串分隔为字符串,将双引号字符串分隔为分隔标识符。 (当然,只是为了完整性,有一个环境变量,DELIMIDENT,可以设置 - 任何值,但Y是最安全的 - 表示双引号始终围绕分隔标识符,单引号始终包围字符串。)


请注意,MS SQL Server设法使用括在方括号中的[[分隔标识符]]。它看起来很怪异,当然不是SQL标准的一部分。

其它参考4


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


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


我使用的每个数据库都遵循这种语法,即DB2SQL ServerMY SQLPostgresQL

其它参考5


要在第一个答案中添加内容,当我们只需要来自另一个表的少量记录时(在此示例中只有一个):


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

其它参考6


如果要为SELECT部分中的所有列提供值,则可以在不指定INSERT INTO部分中的列的情况下完成此操作。


让我们说table1有两列。这个查询应该有效:


INSERT INTO table1
SELECT  col1, col2
FROM    table2


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


INSERT INTO table1
SELECT  col1
FROM    table2


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

其它参考7


这是使用select和值的另一个示例:


INSERT INTO table1(desc, id, email) 
SELECT "Hello World", 3, email FROM table2 WHERE ...

其它参考8


表列序列已知时的简单插入:


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


简单插入提示栏:


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


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


    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

其它参考9


它的简单,而不是INSERT部分的INSERT部分,只需使用SELECT查询,如下所示。


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

其它参考10


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


这适用于所有DBMS

其它参考11


这里是如何从多个表中插入的。这个特殊的例子是你在多对多场景中有一个映射表的地方:


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之外的其他内容。)

其它参考12


我实际上更喜欢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 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;

其它参考14


这对我有用:


insert into table1 select * from table2


这句话与甲骨文有点不同。

其它参考15


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


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



  谷歌:插入网站:microsoft.com



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


如果您发现难以解释页面顶部给出的语法,请向下滚动到示例(使用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的所有语法都没有意义。

其它参考16


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


SELECT  *
INTO    Table2
FROM    Table1;

其它参考17



  • INSERT INTO SELECT语句从一个表复制数据
    将其插入另一个表。

  • INSERT INTO SELECT要求源表和目标表中的数据类型匹配
    目标表中的现有记录不受影响



INSERT INTO SELECT语法: -


INSERT INTO table2
SELECT * FROM table1
WHERE condition;


INSERT INTO SELECT示例: -


INSERT INTO Customers (CustomerName, ContactName, Address, City, PostalCode, Country)
SELECT SupplierName, ContactName, Address, City, PostalCode, Country FROM Suppliers;

其它参考18


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

其它参考19


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


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)

其它参考20


如果您使用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行的值计数,并且当你最终弄清楚如何处理它时,你最终会写一个微不足道的帖子。

其它参考21


插入FIRST_TABLE_NAME(COLUMN_NAME)
SELECT COLUMN_NAME
来自ANOTHER_TABLE_NAME
在什么条件;