问题
I am trying to execute multiple insert with single statement to achieve this I am using Insert into select statement. But I am facing when two columns have same value in insert. Error message that I am getting is ORA-00918: column ambiguously defined.
Query
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
)
Issue is there in first select statement where two values are 82 and 82, if I change one value to something works. I don't know how to make this work even if column values are same.
--- Updates ---
Table Definition
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
);
回答1:
In this case you don't need the subquery - as @Littlefoot showed. But if you did, with a more complicated scenario, you can avoid the error by aliasing the column expressions in the subquery:
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.
The problem is that the subquery on its own gets implied column aliases, derived from the values in the first branch of the query:
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
The second and third columns are both called "82", which is the ambiguity the ORA-00918 is complaining about, from the outer select. If you add aliases that goes away:
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
so the outer query is no longer confused. Note that you only need the aliases in the first branch of the union (usually, anyway) - it doesn't hurt to have them in all branches, they'll just be ignored, but it saves a bit of typing if you're creating this manually. The actual alias names also don't matter in this case, they just have to be unique; specifically, they don't have to match the columns you're inserting into - but it makes it easier to follow if they do.
If you do it as @Littlefoot showed you don't have the intermediate result set select, so the derived names don't need to be evaluated (if they can be said to exist at all), so the ambiguity is not seen - it's purely positional.
回答2:
Remove select * from ( (and trailing )).
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
[EDIT, after a comment that it still doesn't work]
Well, it works, at least in my 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.
No error on 12c either:
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>
Now, please, prove that it doesn't work on your database.
回答3:
Try to name columns:
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
;
But better way is:
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);
you avoid subquery. If you have lots of data to insert into the database consider SQL*Loader and loading from text file. https://docs.oracle.com/en/database/oracle/oracle-database/12.2/sutil/oracle-sql-loader-concepts.html#GUID-DD843EE2-1FAB-4E72-A115-21D97A501ECC
来源:https://stackoverflow.com/questions/60109730/oracle-12c-ambiguous-column-in-insert-into-select-query-ora-00918