2

我正在尝试使用单个语句执行多个插入来实现这一点,我正在使用 Insert into select 语句。但是当两列在插入中具有相同的值时,我面临着。我收到的错误消息是ORA-00918: column ambiguously defined.

询问

INSERT INTO sample (
    HOST,
    TOTAL_PING,
    TOTAL_UNAVAILABLE_PING
)

SELECT * FROM (

    SELECT 'FR3158-73-1',
    82,
    82
    FROM DUAL
    UNION ALL

    SELECT 'FR3158-76-2',
    80,
    10
    FROM DUAL
)

如果我将一个值更改为有效的值,则在第一个选择语句中存在两个值是 82 和 82 的问题。即使列值相同,我也不知道如何使这项工作。

- - 更新 - -

表定义

CREATE TABLE sample
(
  ID                      NUMBER GENERATED ALWAYS as IDENTITY(START with 1 INCREMENT by 1) PRIMARY KEY,
  HOST                    VARCHAR2(15 BYTE),
  TOTAL_PING              INTEGER,
  TOTAL_UNAVAILABLE_PING  INTEGER,
  ADDED_ON                TIMESTAMP(6)          DEFAULT systimestamp
);
4

3 回答 3

6

在这种情况下,您不需要子查询 - 正如@Littlefoot 所示。但是如果你这样做了,在更复杂的情况下,你可以通过在子查询中为列表达式设置别名来避免错误:

INSERT INTO sample (
    HOST,
    TOTAL_PING,
    TOTAL_UNAVAILABLE_PING
)

SELECT * FROM (

    SELECT 'FR3158-73-1' as host,
    82 as total_ping,
    82 as total_unavailable_ping 
    FROM DUAL
    UNION ALL

    SELECT 'FR3158-76-2',
    80,
    10
    FROM DUAL
)
/

2 rows inserted.

问题是子查询本身会获得隐含的列别名,这些别名源自查询的第一个分支中的值:

SELECT 'FR3158-73-1',
82,
82 
FROM DUAL
UNION ALL

SELECT 'FR3158-76-2',
80,
10
FROM DUAL

'FR3158-73-         82         82
----------- ---------- ----------
FR3158-73-1         82         82
FR3158-76-2         80         10

第二列和第三列都称为"82",这是 ORA-00918 抱怨的歧义,从外部select。如果您添加消失的别名:

SELECT 'FR3158-73-1' as host,
82 as total_ping,
82 as total_unavailable_ping 
FROM DUAL
UNION ALL

SELECT 'FR3158-76-2',
80,
10
FROM DUAL

HOST        TOTAL_PING TOTAL_UNAVAILABLE_PING
----------- ---------- ----------------------
FR3158-73-1         82                     82
FR3158-76-2         80                     10

所以外部查询不再混淆。请注意,您只需要联合的第一个分支中的别名(通常,无论如何) - 将它们放在所有分支中并没有什么坏处,它们只会被忽略,但如果您是手动创建它。在这种情况下,实际的别名也无关紧要,它们必须是唯一的;具体来说,它们不必与您插入的列相匹配 - 但如果它们匹配,则更容易遵循。

如果您按照@Littlefoot 显示的那样进行操作,则表明您没有中间结果集select,因此不需要评估派生名称(如果可以说它们根本存在的话),因此看不到歧义-纯粹位置的。

于 2020-02-07T08:47:01.850 回答
4

删除select * from( (和尾随))。

INSERT INTO sample (HOST, TOTAL_PING, TOTAL_UNAVAILABLE_PING)
   SELECT 'FR3158-73-1', 82, 82 FROM DUAL
           UNION ALL
           SELECT 'FR3158-76-2', 80, 10 FROM DUAL

[编辑,在评论它仍然不起作用后]

好吧,它可以工作,至少在我的 11gXE 中:

SQL> select * From v$version where rownum = 1;

BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Express Edition Release 11.2.0.2.0 - 64bit Production

SQL> CREATE TABLE sample
  2  (
  3    ID                      NUMBER,
  4    HOST                    VARCHAR2(15 BYTE),
  5    TOTAL_PING              INTEGER,
  6    TOTAL_UNAVAILABLE_PING  INTEGER,
  7    ADDED_ON                TIMESTAMP(6)          DEFAULT systimestamp
  8  );

Table created.

SQL> INSERT INTO sample (HOST, TOTAL_PING, TOTAL_UNAVAILABLE_PING)
  2     SELECT 'FR3158-73-1', 82, 82 FROM DUAL
  3             UNION ALL
  4             SELECT 'FR3158-76-2', 80, 10 FROM DUAL;

2 rows created.

12c 也没有错误:

SQL> select * from v$version where rownum = 1;

BANNER                                                                               CON_ID
-------------------------------------------------------------------------------- ----------
Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production              0

SQL> CREATE TABLE sample
  2  (
  3    ID                      NUMBER,
  4    HOST                    VARCHAR2(15 BYTE),
  5    TOTAL_PING              INTEGER,
  6    TOTAL_UNAVAILABLE_PING  INTEGER,
  7    ADDED_ON                TIMESTAMP(6)          DEFAULT systimestamp
  8  );

Table created.

SQL> INSERT INTO sample (HOST, TOTAL_PING, TOTAL_UNAVAILABLE_PING)
  2     SELECT 'FR3158-73-1', 82, 82 FROM DUAL
  3             UNION ALL
  4             SELECT 'FR3158-76-2', 80, 10 FROM DUAL;

2 rows created.

SQL>

现在,请证明它不适用于您的数据库。

于 2020-02-07T08:41:51.440 回答
0

尝试命名列:

    INSERT INTO sample (HOST, TOTAL_PING, TOTAL_UNAVAILABLE_PING)
       SELECT 'FR3158-73-1' as host, 82 as total_ping, 82 as total_UNAVAILABLE_PING FROM DUAL
          UNION ALL
       SELECT 'FR3158-76-2' as host, 80 as total_ping, 10 as total_UNAVAILABLE_PING FROM DUAL
;

但更好的方法是:

    INSERT INTO sample (HOST, TOTAL_PING, TOTAL_UNAVAILABLE_PING) values ('FR3158-73-1',82,82);
    INSERT INTO sample (HOST, TOTAL_PING, TOTAL_UNAVAILABLE_PING) values ('FR3158-76-2',80,10);

你避免子查询。如果您有大量数据要插入数据库,请考虑使用 SQL*Loader 并从文本文件加载。 https://docs.oracle.com/en/database/oracle/oracle-database/12.2/sutil/oracle-sql-loader-concepts.html#GUID-DD843EE2-1FAB-4E72-A115-21D97A501ECC

于 2020-02-07T08:50:07.110 回答