【问题标题】:Insert into ... values ( SELECT ... FROM ... )插入 ... 值( SELECT ... FROM ... )
【发布时间】:2010-09-06 18:14:10
【问题描述】:

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

是否有来自 SQL 标准(例如 SQL-92)的灵丹妙药语法允许我插入值而不必担心底层数据库?

【问题讨论】:

  • 这个例子有效:插入到 tag_zone select @tag,zoneid,GETDATE(),@positiong.STIntersects(polygon) from zone

标签: sql database syntax database-agnostic ansi-sql-92


【解决方案1】:

试试:

INSERT INTO table1 ( column1 )
SELECT  col1
FROM    table2  

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

它绝对适用于:

  • 甲骨文
  • MS SQL 服务器
  • MySQL
  • Postgres
  • SQLite v3
  • Teradata
  • DB2
  • Sybase
  • 垂直
  • HSQLDB
  • H2
  • AWS RedShift
  • SAP HANA
  • 谷歌扳手

【讨论】:

  • 如何实现这个? “插入内容为 c (ContentP) 从标题中选择标题为 t wehre c.pageno = t.pageno”。谢谢
  • 我非常怀疑他们是否都立即支持它——只有 SQLite 有最低版本,但对其他人来说也会很有趣,尤其是 ORACLE。
  • @MindRoasterMir 你不能那样做。如果您执行插入,您将在表中创建一个新行,因此您不能拥有可以与之比较的现有行 (c.pageno = t.pageno)。您可能正在寻找 UPDATE 或 MERGE (MS Sql)
【解决方案2】:

Claude Houle's answer: 应该可以正常工作,你也可以有多个列和其他数据:

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。

【讨论】:

  • 如果 where 条件更改为 table2.country 并返回大于一的行数怎么办?我在这里遇到了类似的问题:stackoverflow.com/questions/36030370/…
  • 插入多行应该没有问题。
  • 是否有必要插入到表的所有列中
  • @maheshmnj 不,只需要包含设置为 NOT NULL 且没有默认值的列,任何其他列将设置为其默认值或 NULL
  • 非常适合我,谢谢
【解决方案3】:

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

【讨论】:

  • 只是为了澄清:这对于 SQLite3 是不正确的。根据the documentationINSERT 的源数据是 either VALUESSELECT 语句,而不是两者。
  • 确实文档没有列出它,但它确实有效。无论如何,我认为使用 select 语句而不是 values 确实使它更具可读性。
  • 它适用于指定行内的值,但更一般的情况需要获取很多行。
  • 如果 val_1 不跨行更改,那么以下语法可能在 SQLite3 中有效? select 'foo', some_column from some_table - 适用于 SQLServer 2014
  • 文档确实列出了这个(现在?):这个语法是INSERT INTO ... VALUES ([expr], [expr], ...)[expr] 中的路径之一是{{NOT} EXISTS} ([select-stmt]) - 请注意,选择语句周围的括号是必需的(@ 987654331@ 表示可选)
【解决方案4】:

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

请注意,MS SQL Server 设法使用括在方括号中的 [delimited identifiers]。我觉得它很奇怪,而且肯定不是 SQL 标准的一部分。

【讨论】:

    【解决方案5】:

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

    1. SELECT 子查询返回一行的结果。
    2. SELECT 子查询返回多行的结果。

    1. With SELECT 子查询返回结果的方法一行

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

    在这种情况下,它假设SELECT子查询根据WHERE条件或SUM、MAX、AVG等SQL聚合函数只返回一行结果,否则会抛出错误

    2。 With SELECT 子查询返回结果的方法多行

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

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

    【讨论】:

      【解决方案6】:

      在第一个答案中添加一些东西,当我们只需要另一个表中的几条记录时(在这个例子中只有一条):

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

      【讨论】:

      • 这种方法只适用于只选择一列的子查询。在多列子查询的情况下,将引发错误“子查询必须只返回一列”。那就采纳@travis 的回答吧。
      【解决方案7】:

      而不是VALUES 部分INSERT 查询,只需使用SELECT 查询如下。

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

      【讨论】:

        【解决方案8】:

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

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

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

        【讨论】:

          【解决方案9】:

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

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

          INSERT INTO table1
          SELECT  col1, col2
          FROM    table2
          

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

          INSERT INTO table1
          SELECT  col1
          FROM    table2
          

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

          【讨论】:

            【解决方案10】:

            这是另一个使用选择值的示例:

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

            【讨论】:

            • 旧答案,仍然有用。非常简单明了,但完全满足了我的需求。谢谢!
            【解决方案11】:

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

                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
            

            【讨论】:

              【解决方案12】:

              只需使用括号将 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'
              );
              

              【讨论】:

                【解决方案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 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 以外的内容是必要的。)

                  【讨论】:

                    【解决方案15】:

                    如果您想使用SELECT * INTO 表插入所有列,您可以试试这个。

                    SELECT  *
                    INTO    Table2
                    FROM    Table1;
                    

                    【讨论】:

                      【解决方案16】:

                      我实际上更喜欢 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() 集合的步骤,您只需选择表中的值即可。

                      【讨论】:

                        【解决方案17】:

                        这对我有用:

                        insert into table1 select * from table2
                        

                        这句话和Oracle的有点不同。

                        【讨论】:

                          【解决方案18】:
                          INSERT INTO yourtable
                          SELECT fielda, fieldb, fieldc
                          FROM donortable;
                          

                          这适用于所有 DBMS

                          【讨论】:

                            【解决方案19】:

                            对于 Microsoft SQL Server,我建议学习解释 MSDN 上提供的语法。使用 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 的所有语法是没有意义的。

                            【讨论】:

                            • 我完全不同意,多年来我一直在研究这些语法语句,但仍然无法对它们做出正面或反面。例子更有用
                            • 这不是答案,而是说“阅读文档”,仅此而已
                            【解决方案20】:
                            INSERT INTO FIRST_TABLE_NAME (COLUMN_NAME)
                            SELECT  COLUMN_NAME
                            FROM    ANOTHER_TABLE_NAME 
                            WHERE CONDITION;
                            

                            【讨论】:

                            • @ggorlen 这对我来说很明显
                            • 它在审查队列中被标记为纯代码答案。不过,我可以在此处看到您的观点-由于我在自然环境中看到它,因此在此页面上的大多数答案的上下文中没有什么可说的。
                            【解决方案21】:

                            从任何其他表中插入多条记录的最佳方式。

                            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)
                            

                            【讨论】:

                              【解决方案22】:
                              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
                              

                              【讨论】:

                                【解决方案23】:

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

                                INSERT INTO CUSTOMER_INFO
                                   (SELECT CUSTOMER_NAME,
                                           MOBILE_NO,
                                           ADDRESS
                                      FROM OWNER_INFO cm)
                                

                                表格在哪里:

                                            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        ||
                                

                                【讨论】:

                                  【解决方案24】:

                                  如果您使用 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');
                                  

                                  否则,“列计数与第 1 行的值计数不匹配”的 MySQL 对象,当您最终弄清楚该怎么做时,您最终会写一篇微不足道的帖子。

                                  【讨论】:

                                  • 问题是“使用来自另一个表的输入插入一个表”。您的回答如何解决这个问题?
                                  • 呃,别对他太苛刻了。当我四处搜索时,它回答了我的问题。 @QualityCatalyst
                                  【解决方案25】:

                                  如果你先创建表,你可以这样使用;

                                    select * INTO TableYedek From Table
                                  

                                  此方法插入值,但与创建新副本表不同。

                                  【讨论】:

                                  • 如果您将整个表保存为备份,请使用此查询..select * INTO TableYedek_Backup From TableYedek
                                  【解决方案26】:

                                  在informix中,它就像克劳德所说的那样工作:

                                  INSERT INTO table (column1, column2) 
                                  VALUES (value1, value2);    
                                  

                                  【讨论】:

                                    【解决方案27】:

                                    Postgres 支持下一个: 创建表company.monitor2 as select * from company.monitor;

                                    【讨论】:

                                      猜你喜欢
                                      • 1970-01-01
                                      • 1970-01-01
                                      • 1970-01-01
                                      • 1970-01-01
                                      • 1970-01-01
                                      • 1970-01-01
                                      • 1970-01-01
                                      相关资源
                                      最近更新 更多