【问题标题】:SQL - Insert Using Column Name as ValueSQL - 使用列名作为值插入
【发布时间】:2013-07-11 10:03:15
【问题描述】:

我正在尝试根据 select from table1 插入 into table2,但我无法获得正确的语法。来自 table1 的列名将驱动插入到 table2 的 PD_NO 列中的值,如下例所示。有人可以帮忙吗?

表1:

         (1)     (2)     (3)     (4)     (5)     (6)
| SEQ | PD_01 | PD_02 | PD_03 | PD_04 | PD_05 | PD_06 |
|-----+-------+-------+-------+-------+-------+-------|
| 632 | 10000 |   0   |  500  |   0   | 20000 |   0   |

表2:

| SEQ | PD_NO |  AMT  |
|-----+-------+-------|
| 632 |   1   | 10000 |
|-----+-------+-------|
| 632 |   3   |  500  |
|-----+-------+-------|
| 632 |   5   | 20000 |
|-----+-------+-------|

我知道如果我在另一个方向工作(将 table2 的内容插入 table1),我可以执行以下操作:

INSERT INTO table1
SELECT 
      seq,
      SUM (CASE WHEN pd_no = 1 THEN amt ELSE 0 END) p01_amt,
      SUM (CASE WHEN pd_no = 2 THEN amt ELSE 0 END) p02_amt,
      SUM (CASE WHEN pd_no = 3 THEN amt ELSE 0 END) p03_amt,
      SUM (CASE WHEN pd_no = 4 THEN amt ELSE 0 END) p04_amt,
      SUM (CASE WHEN pd_no = 5 THEN amt ELSE 0 END) p05_amt,
      SUM (CASE WHEN pd_no = 6 THEN amt ELSE 0 END) p06_amt
FROM table2;

【问题讨论】:

  • 请用您正在使用的 RDBMS 品牌标记您的问题。例如。 sql-servermysqloracle

标签: sql oracle select insert pivot-table


【解决方案1】:

insert ... select from 以 1:1 的行为基础:“select”表中的一行数据进入“insert”表的一行。您试图从源表中取出一行并将其转换为目标表中的多行。这是直接不可能的。您必须运行多个插入/选择,每个要拆分的字段一个:

INSERT INTO table2 (SEQ, PD_NO, AMT) SELECT SEQ, PD_01, AMT FROM table1
INSERT INTO table2 (SEQ, PD_NO, AMT) SELECT SEQ, PD_02, AMT FROM table1
INSERT INTO table2 (SEQ, PD_NO, AMT) SELECT SEQ, PD_03, AMT FROM table1
INSERT INTO table2 (SEQ, PD_NO, AMT) SELECT SEQ, PD_04, AMT FROM table1
etc...

【讨论】:

    【解决方案2】:

    在纯sql中可以这样完成:

    INSERT INTO table2 ( SEQ , PD_NO,  AMT )
    SELECT SEQ, 1 as pd_no, PD_01 FROM Table1
    UNION ALL
    SELECT SEQ, 2 as pd_no, PD_02 FROM Table1
    UNION ALL
    SELECT SEQ, 3 as pd_no, PD_03 FROM Table1
    UNION ALL
    SELECT SEQ, 4 as pd_no, PD_04 FROM Table1
    UNION ALL
    SELECT SEQ, 5 as pd_no, PD_05 FROM Table1
    UNION ALL
    SELECT SEQ, 6 as pd_no, PD_06 FROM Table1
    

    有些数据库已经优化了只读取一次源表的命令(上述查询读取源表6次),例如在ORACLE中:

    INSERT ALL
    INTO table2 ( SEQ , PD_NO,  AMT ) VALUES ( seq, 1, PD_01 )
    INTO table2 ( SEQ , PD_NO,  AMT ) VALUES ( seq, 2, PD_02 )
    INTO table2 ( SEQ , PD_NO,  AMT ) VALUES ( seq, 3, PD_03 )
    INTO table2 ( SEQ , PD_NO,  AMT ) VALUES ( seq, 4, PD_04 )
    INTO table2 ( SEQ , PD_NO,  AMT ) VALUES ( seq, 5, PD_05 )
    INTO table2 ( SEQ , PD_NO,  AMT ) VALUES ( seq, 6, PD_06 )
    SELECT * FROM table1
    

    【讨论】:

      【解决方案3】:
      CREATE TABLE 1to6 (i INT PRIMARY KEY);
      INSERT INTO 1to6 (i) VALUES (1), (2), (3), (4), (5), (6);
      
      INSERT INTO table2 (seq, pd_no, amt)
      SELECT seq, i, 
       CASE(i)
       WHEN 1 THEN pd_01
       WHEN 2 THEN pd_02
       WHEN 3 THEN pd_03
       WHEN 4 THEN pd_04
       WHEN 5 THEN pd_05
       WHEN 6 THEN pd_06
       END
      FROM table1 CROSS JOIN 1to6
      

      重新评论:显然 Oracle 不支持多行 INSERT 语法(尽管该语法是标准 SQL-99)。您可以一次插入一行:

      INSERT INTO 1to6 (i) VALUES (1);
      INSERT INTO 1to6 (i) VALUES (2);
      INSERT INTO 1to6 (i) VALUES (3);
      INSERT INTO 1to6 (i) VALUES (4);
      INSERT INTO 1to6 (i) VALUES (5);
      INSERT INTO 1to6 (i) VALUES (6);
      

      【讨论】:

      • 这个选项看起来很干净。但是,尝试在第 2 行插入值时出现“SQL 命令未正确结束”错误。删除“、(2)、(3) 等。”工作正常,并为我提供了一个包含一列的表(i) 值为 1。有什么想法吗?
      【解决方案4】:

      这是一个典型的问题,Oracle 11 提供了 UNPIVOT 子句供查询使用:

      insert  into table2(seq, pd_no, amt)
      select  seq, pd_no, amt
      from    ( select  *
                from    table1
                unpivot (amt for pd_no in (pd_01 as 1, pd_02 as 2, pd_03 as 3, pd_04 as 4, pd_05 as 5, pd_06 as 6))
              );
      

      【讨论】:

      • 托马斯,谢谢。这正是我想要的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-06-11
      • 1970-01-01
      • 1970-01-01
      • 2012-11-12
      • 1970-01-01
      • 2021-09-22
      • 1970-01-01
      相关资源
      最近更新 更多