Getting ORA-00904 invalid identifier executing multi table insert query - insert

I'm just trying 'multi table insert'. Below is my insert query. I'm trying to insert values from employees table to table t1,t2 and t3. After executing the query i'm getting an error.
ERROR at line 4:
ORA-00904: "EMPLOYEES"."LAST_NAME": invalid identifier
The column last_name is exist in employees table. But why i'm getting this error.
insert all
into t1(id,l_name) values(employees.employee_id,employees.last_name)
into t2(id,l_name) values(employees.employee_id,employees.last_name)
into t3(id,l_name) values(employees.employee_id,employees.last_name)
select * from employees;
/
I've also tried replacing table name and column name to upper case. Still facing the same error. I'm using Oracle 10g.
Thanks

After removing the reference table name employees from column name its working.
Answer:
INSERT ALL
INTO t1(id, l_name) VALUES (employee_id, last_name)
INTO t2(id, l_name) VALUES (employee_id, last_name)
INTO t3(id, l_name) VALUES (employee_id, last_name)
SELECT * FROM employees;

Related

Automatically inserting data into a table using a procedure

I would like to ask you a rather easy question but I cannot get my head around it as I am a beginner in SQL.
My task is: Enter initial data into BankStats2 by inserting rows into BankStats2 that
contain the branch names together with how many loans are in the Loan
table for that branch name.
desc BankStats2
Name Null? Type
----------------------------------------- -------- ----------------------------
BRANCHNAME NOT NULL VARCHAR2(20)
NUMBEROFLOANS NUMBER(38)
desc Loan
Name Null? Type
----------------------------------------- -------- ----------------------------
CUSTOMERNAME CHAR(20)
BRANCHNAME CHAR(20)
AMOUNT NUMBER(38)
LOANNUMBER NOT NULL NUMBER(38)
select branchName,count(customerName) from Loan group by branchName;
BRANCHNAME COUNT(CUSTOMERNAME)
-------------------- -------------------
Yorkshire 3
RoyalBank 1
Midlands 3
Basically, I would like to insert this information in the BankStats2 table and the way I thought of doing it is by creating a procedure which I will show below.
CREATE OR REPLACE PROCEDURE PopulateBankStats AS
CURSOR someLoanRows IS
SELECT branchName,COUNT(customerName) FROM loan GROUP BY branchName;
aBranchNameRow loan.branchName%TYPE;
numberOfLoans INT;
BEGIN
OPEN someLoanRows;
LOOP
FETCH someLoanRows INTO aBranchNameRow, numberOfLoans;
INSERT INTO BankStats2 VALUES (aBranchNameRow,numberOfLoans);
EXIT WHEN someLoanRows%NOTFOUND;
END LOOP;
CLOSE someLoanRows;
END;
/
But executing it give me the following error:
ERROR at line 1:
ORA-00001: unique constraint (N0757934.SYS_C0034405) violated
ORA-06512: at "N0757934.POPULATEBANKSTATS", line 10
ORA-06512: at line 1
Any help would be greatly appreciated. Thank you for your time!
This insert fails: INSERT INTO BankStats2 VALUES (aBranchNameRow,numberOfLoans); due to the error: ORA-00001: unique constraint (N0757934.SYS_C0034405) violated
This means that there is an unique constraint created on some of the columns of the table BankStats2.
In order to find which column has unique constraint, run this query:
select * from USER_IND_COLUMNS where index_name = 'SYS_C0034405';
Your procedure is trying to insert a record with a value of this column which already is existing in the table.
Have a look on the INSERT statement.
What your procedure is doing is exactly this insert statement:
INSERT INTO BankStats2 (BRANCHNAME,NUMBEROFLOANS)
SELECT branchName,COUNT(customerName) FROM loan GROUP BY branchName;
It is always preferable to use SQL statement (if possible) instead of the PL/SQL cursor loop logik - search Tom Kyte's "row by row - slow by slow" for an explantion.
Even if you want to use a procedure at all cost - use this INSERT in the preocedure.
Your exception means that you try to insert a value of the column BRANCHNAME that already exists in the table BankStats2.
This could be by an accident or a systematic problem.
If it is an accident, simple clean the data, i.e. DELETE the row(s) with the corresponding keys from the BankStats2 table.
This query returns the values existing in both tables
select BRANCHNAME from BankStats2
intersect
select branchName FROM loan;
If you want to systematically avoid inserting the duplicated row, add this logik in your INSERT statement:
INSERT INTO BankStats2 (BRANCHNAME,NUMBEROFLOANS)
SELECT branchName,COUNT(customerName)
FROM loan
WHERE branchName IS NOT NULL
and branchName NOT IN (select BRANCHNAME from BankStats2)
GROUP BY branchName;
Note that the SELECT excludes the row with the value that already exists in the target table - using NOT IN (subquery).
Note also that I'm approaching your next possible problem. The column BRANCHNAME is non nullable in BankStats2, but is nullable (i.e. may contain NULL) in loan, so you would fail to insert the row with NULL to the table BankStats2. Therefore I exclude those rows with the branchName IS NOT NULL predicate.
If you want to process the existing keys with an UPDATE logik, check the MERGE statement.

Inner query not throwing error in postgres

There is a scenario in which we are retrieving some result from inner query and using the result to perform some operation
create table test1(key integer,value varchar)
insert into test1 values(1,'value 1');
insert into test1 values(2,'value 2');
insert into test1 values(3,'value 3');
second table as
create table test2(key1 integer, valuein varchar);
insert into test2 values (2,'value inside is 2');
insert into test2 values (4,'value inside is 4');
insert into test2 values (5,'value inside is 5');
the below query is giving result but in my view it should give an error
select * from test1 where key in
(select key from test2)
because key column does not exist in test2 table.
but it is giving result in postgres
but when run in oracle it is giving error as
ORA-00904: "KEY": invalid identifier
00904. 00000 - "%s: invalid identifier"
This is the correct behavior as specified in the SQL standard. The inner query has access to all columns of the outer query - and because test1 has a column named key (which, btw is a horrible name for a column) the inner select is valid.
See these discussions on the Postgres mailing list:
http://postgresql.nabble.com/BUG-13336-Unexpected-result-from-invalid-query-td5850684.html

Leave column out of Oracle insert statement

I have an insert statement that I am trying to run against an Oracle database. The insert statement is very simple, and I only want to insert a value into one column. The table itself has more than one column, but I am only interested in filling one of the columns with data. The format of my query is similar to the one below:
insert into myTable (col1) Values (val1)
However, this throws the following error:
ORA-00904: "col1": invalid identifier
I've checked to make sure that the column is named correctly, and my only other thought is that something is wrong with my syntax. There are no constraints on the table such as primary keys. Is it possible to only insert values into certain columns when executing an insert statement in Oracle?
Check that you didn't quote the column name on creation of the table. If you did, the column name is stored as you quoted it. For example:
create table table1 (
id number(2)
)
has a different column name to this
create table table2 (
"id" number(2)
)
Oracle by default stores the (unquoted) column names in uppercase. Quoted are stored as is.
You can use a DESC table_name to see how the columns are stored.
The following
select id from table1
select iD from table1
select ID from table1
fetch the records, while only
select "id" from table2
will fetch records.
select id from table2
will throw the ORA-00904 : "ID" : invalid identifier error.
You may have inadvertently done the quoting during creation while using tools as established below:
https://community.oracle.com/thread/2349926
Btw: Yes it is possible to insert records for only one column, as long as the other columns do not have a NOT NULL constraint on them.
Actually, I think you may be double quoting the column in the insert statement (not on table creation), although your example is misleading. I guess this because of your error, which says "col1" is invalid, not "COL1" is invalid. Consider this simple test:
SQL> create table mytable
(
col1 varchar2(10)
)
Table created.
SQL> -- incorrect column name, without double quotes
SQL> insert into mytable(col2) values ('abc')
insert into mytable(col2) values ('abc')
Error at line 9
ORA-00604: error occurred at recursive SQL level 1
ORA-06502: PL/SQL: numeric or value error: character string buffer too small
ORA-06512: at line 11
ORA-00904: "COL2": invalid identifier
SQL> -- incorrect column name, with double quotes
SQL> insert into mytable("col2") values ('abc')
insert into mytable("col2") values ('abc')
Error at line 12
ORA-00604: error occurred at recursive SQL level 1
ORA-06502: PL/SQL: numeric or value error: character string buffer too small
ORA-06512: at line 11
ORA-00904: "col2": invalid identifier
SQL> -- correct column name, without double quotes (works)
SQL> insert into mytable(col1) values ('abc')
1 row created.
SQL> -- correct column name, with double quotes (fails)
SQL> insert into mytable("col1") values ('abc')
insert into mytable("col1") values ('abc')
Error at line 18
ORA-00604: error occurred at recursive SQL level 1
ORA-06502: PL/SQL: numeric or value error: character string buffer too small
ORA-06512: at line 11
ORA-00904: "col1": invalid identifier
The last failed insert attempt is what I think you may be doing:
insert into mytable("col1") values ...
based on the error message:
ORA-00904: "col1": invalid identifier
So the solution would simply be remove the double quoting around the column name in the insert.
It's most probably a syntax error
Desc myTable;
insert into myTable (col1) Values ('val1')
Ensure col1 is a valid column in the table, and you're simply not trying to say 'select the left-most column.
edit: Is it possible to only insert values into certain columns when executing an insert statement in Oracle?
Yes if you want to only insert into certain columns then simply specify it
e.g.
insert into myTable (col1, col2, col6) Values ('val1', 'val2', 'val3');
This will only work if the column itself doesn't have a NOT NULL constraint - in which case it will not allow a value to be enetered (unless again there's a default value).

Insert content of table variable into table

I have the following table, two types based on it, and a function that reads from this table:
CREATE TABLE myTable (
ID RAW(16) NULL,
NAME NVARCHAR2(200) NULL,
ENTITYID RAW(16) NOT NULL
);
CREATE TYPE myRowType AS OBJECT (
NAME NVARCHAR2(200),
ENTITYID RAW(16)
);
CREATE TYPE myTableType IS TABLE OF myRowType;
CREATE FUNCTION myFunction(...) RETURN myTableType ...
As you can see, the type myRowType is similar to myTable, but not exactly.
My goal is to insert rows into myTable based on the results of myFunction.
The naive approach would be to just write:
INSERT INTO myTable(ID, NAME, ENTITYID)
SELECT sys_guid(), NAME, ENTITYID
FROM TABLE(myFunction(...));
But since myFunction reads from myTable, this leads to the following error:
ORA-04091: table myTable is mutating, trigger/function may not see it
So I have to split the myFunction call from the insert statement. I tried it like this:
DECLARE
tbl myTableType;
BEGIN
SELECT myRowType(x.NAME, x.ENTITYID)
BULK COLLECT INTO tbl
FROM TABLE(myFunction(...)) x;
INSERT INTO myTable
(ID, NAME, ENTITYID)
SELECT sys_guid(), x.NAME, x.ENTITYID
FROM tbl x;
END;
But here, Oracle doesn't seem to understand the FROM tbl clause. It shows the error
ORA-00942: table or view does not exist
How can I insert the rows in tbl into myTable?
Since you can't use a locally defined nested table as an argument for TABLE function, maybe you would consider using the FORALL bulk insert? I see you are using Oracle 11g, so you will be able to access fields of myRowType. You would then replace your INSERT from your PL/SQL block with this:
FORALL v_i IN tbl.FIRST..tbl.LAST
INSERT INTO myTable VALUES (sys_guid(), tbl(v_i).name, tbl(v_i).entityid);
I recommend this great article by Tim Hall: BULK COLLECT & FORALL

How can I implement conditional updating in Oracle?

I'm new to oracle and having a problem with one of my SQL Queries.
There are 2 Users: User1 and User2:
Tab1 Tab2
-------- --------
EmpNo EmpNo
EmpName EmpName
ContactNo Salary
Location
User2 has all privileges in User1.Tab1, and there is no foreign key relationship between the two tables.
The Problem:
I wanted to add a column in tab2 "NameDesignation" And I wanted to insert the value in this column after checking the following condition:
WHEN User1.Tab1.EmpNo = User2.Tab2.EmpNo THEN
INSERT INTO Tab2 VALUES (&designation)
I really have no idea how to do this, and was hoping for a little help. Any thoughts?
try this:
update user2.tab2.empno t2
set NameDesignation= &designation
where exists (select ''
from user1.tab1 t1
where t1.empno=t2.empno)
(statement updated to match the edited question)
You would need a set of triggers,
After insert or update:
CREATE OR REPLACE TRIGGER tab1_after_changed
AFTER INSERT OR UPDATE
ON tab1
FOR EACH ROW
BEGIN
DELETE FROM User2.Tab2 WHERE EmpNo=:NEW.EmpNo;
INSERT INTO User2.Tab2(EmpNo,EmpName,NameDesignation)
VALUES (:NEW.EmpNo,:NEW.EmpName, (SELECT DesignationName FROM Designation where DesignationID=:NEW.DesignationID));
END;
I just imagined a table with Designation (DesignationID number, DesignationName varchar2(xx)), and Tab1 having DesignationID(number).

Resources