SQL - Error 'ORA-00918: column ambiguously defined' in SQL Developer - sql

So I'm having some issues producing a query with multiple temporary tables.
First I created the temporary tables.
CREATE GLOBAL TEMPORARY TABLE DIDV (DID VARCHAR(50))
INSERT INTO DIDV VALUES ('8090630909077434001');
INSERT INTO DIDV VALUES ('7471990179373590001');
INSERT INTO DIDV VALUES ('7605256906013877001');
INSERT INTO DIDV VALUES ('1604387368720407001');
INSERT INTO DIDV VALUES ('3512739534818409001');
CREATE GLOBAL TEMPORARY TABLE KEYW (KEW VARCHAR(50))
INSERT INTO KEYW VALUES ('%Corporate Insurance Pol%');
INSERT INTO KEYW VALUES ('%Tax Return%');
INSERT INTO KEYW VALUES ('%Audit%');
INSERT INTO KEYW VALUES ('%Corporate Governance%');
INSERT INTO KEYW VALUES ('%Board%');
INSERT INTO KEYW VALUES ('%Shareholder%');
Then I write my query as follows. It seems like a simple query. However, I get the error 'ORA-00918: column ambiguously defined'. I don't know if I can do a join of the 2 temporary tables, especially they do not have any relationship. I just want to query result where the unique id's are in the DIDV table and where the title and comment columns do not contain the KEW fields.
SELECT TO_CHAR(DID) DID, TO_CHAR(DROOTPARENTID) PARENTID, DBARCODE,
DDOCTITLE, XCOMMENTS, XDIVISION, DEXTOBJECTTYPE
FROM PSA.URM_EXTITEMS_PSA, DIDV, KEYW
WHERE PSA.URM_EXTITEMS_PSA.DID = DIDV.DID
AND PSA.URM_EXTITEMS_PSA.DDOCTITLE NOT LIKE KEYW.KEW
AND PSA.URM_EXTITEMS_PSA.XCOMMENTS NOT LIKE KEYW.KEW;
Any help understanding this is appreciated.
Please let me know if any clarification is needed.

A table DIDV contains a column named DID
A table URM_EXTITEMS_PSA also contains a column named DID (I know this because a where condition contains a clause WHERE PSA.URM_EXTITEMS_PSA.DID = DIDV.DID ).
A select statement in your query contains an expression referencing the column DID:
SELECT TO_CHAR(DID) ....
Oracle doesn't really know (I don't know too) which DID do you want to get in a result - the 'DID' column which comes from DIDV table or the DID column which comes from URM_EXTITEMS_PSA table. Therefore Oracle throws an error ORA-00918: column ambiguously defined.
Just append an aliast to this DIV column in the select clause, either DIDV or URM_EXTITEMS_PSA, in this way:
SELECT TO_CHAR(DIDV.DID) ....
I know that WHERE clause contains PSA.URM_EXTITEMS_PSA.DID = DIDV.DID and actually both DIDs are equal, so Oracle should be smart enaugh to say Oh, yes, he wrote PSA.URM_EXTITEMS_PSA.DID = DIDV.DID, so I can pick DID from any table ....
Unfortunatelu Oracle is not so smart (maybe they improve this in a new version ?), and for now you must append an alias or a table name.

Related

Does Oracle allow an SQL INSERT INTO using a SELECT statement for VALUES if the destination table has an GENERATE ALWAYS AS IDENTITY COLUMN

I am trying to insert rows into an Oracle 19c table that we recently added a GENERATED ALWAYS AS IDENTITY column (column name is "ID"). The column should auto-increment and not need to be specified explicitly in an INSERT statement. Typical INSERT statements work - i.e. INSERT INTO table_name (field1,field2) VALUES ('f1', 'f2'). (merely an example). The ID field increments when typical INSERT is executed. But the query below, that was working before the addition of the IDENTITY COLUMN, is now not working and returning the error: ORA-00947: not enough values.
The field counts are identical with the exception of not including the new ID IDENTITY field, which I am expecting to auto-increment. Is this statement not allowed with an IDENTITY column?
Is the INSERT INTO statement, using a SELECT from another table, not allowing this and producing the error?
INSERT INTO T.AUDIT
(SELECT r.IDENTIFIER, r.SERIAL, r.NODE, r.NODEALIAS, r.MANAGER, r.AGENT, r.ALERTGROUP,
r.ALERTKEY, r.SEVERITY, r.SUMMARY, r.LASTMODIFIED, r.FIRSTOCCURRENCE, r.LASTOCCURRENCE,
r.POLL, r.TYPE, r.TALLY, r.CLASS, r.LOCATION, r.OWNERUID, r.OWNERGID, r.ACKNOWLEDGED,
r.EVENTID, r.DELETEDAT, r.ORIGINALSEVERITY, r.CATEGORY, r.SITEID, r.SITENAME, r.DURATION,
r.ACTIVECLEARCHANGE, r.NETWORK, r.EXTENDEDATTR, r.SERVERNAME, r.SERVERSERIAL, r.PROBESUBSECONDID
FROM R.STATUS r
JOIN
(SELECT SERVERSERIAL, MAX(LASTOCCURRENCE) as maxlast
FROM T.AUDIT
GROUP BY SERVERSERIAL) gla
ON r.SERVERSERIAL = gla.SERVERSERIAL
WHERE (r.LASTOCCURRENCE > SYSDATE - (1/1440)*5 AND gla.maxlast < r.LASTOCCURRENCE)
) )
Thanks for any help.
Yes, it does; your example insert
INSERT INTO table_name (field1,field2) VALUES ('f1', 'f2')
would also work as
INSERT INTO table_name (field1,field2) SELECT 'f1', 'f2' FROM DUAL
db<>fiddle demo
Your problematic real insert statement is not specifying the target column list, so when it used to work it was relying on the columns in the table (and their data types) matching the results of the query. (This is similar to relying on select *, and potentially problematic for some of the same reasons.)
Your query selects 34 values, so your table had 34 columns. You have now added a 35th column to the table, your new ID column. You know that you don't want to insert directly into that column, but in general Oracle doesn't, at least at the point it's comparing the query with the table columns. The table has 35 columns, so as you haven't said otherwise as part of the statement, it is expecting 35 values in the select list.
There's no way for Oracle to know which of the 35 columns you're skipping. Arguably it could guess based on the identity column, but that would be more work and inconsistent, and it's not unreasonable for it to insist you do the work to make sure it's right. It's expecting 35 values, it sees 34, so it throws an error saying there are not enough values - which is true.
Your question sort of implies you think Oracle might be doing something special to prevent the insert ... select ... syntax if there is an identity column, but in facts it's the opposite - it isn't doing anything special, and it's reporting the column/value count mismatch as it usually would.
So, you have to list the columns you are populating - you can't automatically skip one. So you statement needs to be:
INSERT INTO T.AUDIT (IDENTIFIER, SERIAL, NODE, ..., PROBESUBSECONDID)
SELECT r.IDENTIFIER, r.SERIAL, r.NODE, ..., r.PROBESUBSECONDID
FROM ...
using the actual column names of course if they differ from the query column names.
If you can't change that insert statement then you could make the ID column invisible; but then you would have to specify it explicitly in queries, as select * won't see it - but then you shouldn't rely on * anyway.
db<>fiddle

INSERT statement for one column to populate each row

I have a table called books that I just altered to have a column called yearPUB. I'm trying to populate each row with a year but it's not working. This is the INSERT statement I'm using.
INSERT INTO books (yearPub)
VALUES (2002),
(2006),
(1999),
(2005),
(2003),
(2001),
(1998),
(1968),
(2009),
(1988),
Can someone tell me why it doesn't work?
You need to insert them one at a time, e.g.:
INSERT INTO books (yearPub) VALUES (2002);
INSERT INTO books (yearPub) VALUES (2006);
Alternatively, you could insert using a subquery with a select statement. The syntax may differ depending on what database you are using. For example, you could follow an example here and write something like:
INSERT INTO books (yearPub)
SELECT yearNumber FROM othertablename;

SQL: Insert multiple row with common columns

I have a table into which i will insert and it has 4 columns.
While inserting 3 columns will be same and the other one column will be different for each and it will be taken from another table.
How could i do that?
For exmaple;
INSERT INTO sendMsg (Type,Name,SenderName,Message) values(4, 'john','Mike','Hi, blabla')
i will insert same message also for Bob, instead of john.
and the names which i will send are contained in Names table.
Thank you.
Use a select statement to build up your insert. Something like this could work (as you didn't provide more details):
INSERT INTO sendMsg (Type,Name,SenderName,Message)
SELECT 4, "name" ,'Mike','Hi, blabla' FROM anothertable
-- WHERE ....
Column names are in ", so don't be confused. It's to ensure difference between string and database object.
Inside optinal WHERE you could do maybe something like
WHERE name in ('Bob', 'John', ...)
or whichever algorithm you need to determine the names.

SQL Insert Query With Condition

I am trying to insert values into 1 column of a table when a condition is satisfied.
Note: The table already contains data for all the columns but for 1 which is empty. I would like to insert value into this 1 column depending on the WHERE clause.
I have this query:
INSERT INTO <TABLE_NAME>
(COLUMN_NAME)
(VALUE)
WHERE <CONDITION>
I am getting an exception:
Incorrect Syntax Near WHERE Keyword
I am able to do this using UPDATE:
UPDATE <TABLE_NAME>
SET <COL_NAME>
WHERE <CONDITION>
But was wondering why the INSERT query was failing. Any advise appreciated.
As I understand your problem, you already have data in one row, and one column in that row does not have value, so you want to add value in to that column.
This the scenario for Update existing row, not the insert new row. You have to use UPDATE clause when data already present and you want to modify record(s). Choose insert when You want to insert new row in table.
So in your current scenario, Update Clause is your friend with Where Clause as you want to modify subset of records not all.
UPDATE <TABLE_NAME>
SET <COL_NAME>
WHERE <CONDITION>
INSERT Clause does not have any Where Clause as per any RDBMS syntax(I think). Insert is condition less sql query, While SELECT, UPDATE, DELETE all are conditional commands, you can add Where Clause in all later ones.
In order to add a value into the one column when the rows are already populated, you will need to use the update statement.
If you need to insert a new row that has a where clause, you will need to use an insert into select statement:
INSERT INTO <table> (<columns>)
SELECT <columns>
FROM <table>
WHERE <condition>;
The SQL Insert dont accept where parameters, you could check this: SQL Insert Definition...
I do not know the whole question of what you want to do, but just using the INSERT statement is not possible, however it is possible to condition the insertion of data into a table, if this data is dependent on another table or comes from another table ... check here... SQL Insert explain in wikipedia
like this:
Copying rows from other tables
INSERT INTO phone_book2
SELECT *
FROM phone_book
WHERE name IN ('John Doe', 'Peter Doe')
or
INSERT INTO phone_book2 ( [name], [phoneNumber] )
SELECT [name], [phoneNumber]
FROM phone_book
WHERE name IN ('John Doe', 'Peter Doe')
Based on your question I have the feeling that you are trying to UPDATE a column in a table rather than insert.
Something like:
UPDATE column SET value WHERE different_column_value = some_value
I know this is kinda late, for those who still want to use the where clause in an insert query, it's kinda possible with a hack.
My understanding is that, you want to insert only if a condition is true. Let's assume you have a column in your database "surname" and you want to insert only if a surname doesn't exist from the table.
You kinda want something like INSERT INTO table_name blha blha blah WHERE surname!="this_surname".
The solution is to make that cell unique from your admin panel.
Insert statement will insert a new record. You cannot apply a where clause to the record that you are inserting.
The where clause can be used to update the row that you want.
update SET = where .
But insert will not have a where clause.
Hope this answers your question
INSERT syntax cannot have WHERE clause. The only time you will find INSERT has WHERE clause is when you are using INSERT INTO...SELECT statement.
I take it the code you included is simply a template to show how you structured your query. See the SO questions here, here and the MSDN question here.
In SQL Server (which uses Transact-SQL aka T-SQL) you need an UPDATE query for INSERT where columns already have values - by using the answer #HaveNoDisplayName gave :)
If you are executing INSERT / UPDATE from code (or if you need it regularly) I would strongly recommend using a stored procedure with parameters.
You could extend the procedure further by adding an INSERT block to the procedure using an IF-ELSE to determine whether to execute INSERT new record or UPDATE an existing, as seen in this SO answer.
Finally, take a look at SQLFiddle for a sandbox playground to test your SQL without risk to your RDMS :-)
Private case I found useful: Conditional insert which avoids duplications:
-- create a temporary table with desired values
SELECT 'Peter' FirstName, 'Pan' LastName
INTO #tmp
-- insert only if row doesn't exist
INSERT INTO Persons (FirstName, LastName)
SELECT *
FROM #tmp t
WHERE NOT EXISTS (SELECT * FROM Persons where FirstName=t.FirstName and LastName=t.LastName)
If the data need to be added for a column for an existing row then it’s UPDATE.
INSERT is creating a new row in the table.
For conditional INSERT, you can use the MERGE command.

SQL Server: Insert INTO Statement syntax [duplicate]

This question already has answers here:
Why are dot-separated prefixes ignored in the column list for INSERT statements?
(3 answers)
Closed 8 years ago.
Why does not the following INSERT statement give any error?
CREATE TABLE Table1(id INT,name VARCHAR(10))
INSERT INTO Table1(xx.id,yyyy.name) Values (1,'A')
Why does the above statement ignore xx. and yyyy.? What does this imply ?
I checked the below query also.
INSERT INTO Table11(xx.xx.xx.xx.xx.xx.xx.id,yy.yy.yy.yy.yy.yy.yy.yy.name)
Values (1,'A')
It also got worked. Usually we use alias for joins. As I know, For Insert query Using alias near table name is restricted in sql. In the case of column name, the query use only the string next to the last Dot(.).
I conclude it as, The Insert query don't care about the string prefixed to the column name separated by Dot(.).
The only thing I can think of is that the database engine is ignoring the name space as the query's scope is limited to the Table's scope when dealing with INSERT INTO. When it comes to say UPDATE where multiple tables can be part of the scope, the below would fail. Don't know why this happens but if I were to guess, probably all values to the left of the last period'.' is ignored
If you analyze the execution plan for the below query
CREATE TABLE Table1(id INT,name VARCHAR(10))
INSERT INTO Table1(Table2.dbo.id,...................name) Values (1,'A')
AS
INSERT INTO [Table1]([id],[name]) Values(#1,#2)
This implies the namespace of something...
For example:
SELECT object.id, object.name FROM table object WHERE object.name = 'Foo';
/ \
| |
object is the name space for the table.
And if you haven't a namespace created the query fails.
As far as I know, the syntax you are using generally means table.column
So in other words you are trying to insert into Table1 but declaring columns from other tables.
You should do something like this
CREATE TABLE Table1(id INT,name VARCHAR(10))
INSERT INTO Table1(id,name) Values (1,'A')