Reputation: 1094
I want to copy a view into a table. Below procedure throws ORA-01722: invalid number
BEGIN
INSERT ALL
INTO DB_LOCATIONS
SELECT * FROM DB_LOCVIEW ;
COMMIT;
EXCEPTION
WHEN OTHERS
THEN
BEGIN
DBMS_OUTPUT.put_line ('SQLCODE: ' || SQLCODE||' -SQLERRM: '||SQLERRM);
END;
END;
On the other hand, If I try it with for loop, everything is fine:
DECLARE
currow integer := 1;
BEGIN
DBMS_OUTPUT.put_line ('starting.....');
for xxinserteddata in (select * from DB_LOCVIEW )
LOOP
BEGIN
DBMS_OUTPUT.put_line('currow: ' || currow);
INSERT INTO DB_LOCATIONS (
DB_DATE,
LOCATIONID,
MX_ET,
MX_MT,
BAND,
SITE)
VALUES (
xxinserteddata.DB_DATE,
xxinserteddata.LOCATIONID,
xxinserteddata.MX_ET,
xxinserteddata.MX_MT,
xxinserteddata.BAND,
xxinserteddata.SITE );
currow := currow + 1;
END;
END LOOP;
COMMIT;
DBMS_OUTPUT.put_line ('end.');
EXCEPTION
WHEN OTHERS
THEN
BEGIN
DBMS_OUTPUT.put_line ('-currow: ' || currow || ' -SQLCODE: ' || SQLCODE||' -SQLERRM: '||SQLERRM);
END;
END;
Both view and table has only 5 same columns. Any idea why insert all throws exception?
EDIT: Adding create procedures:
View:
CREATE OR REPLACE FORCE VIEW DB_LOCVIEW ("LOCATIONID", "SITE", "MX_ET", "MX_MT", "DB_DATE", "BAND") AS
SELECT
l.LOCATIONID,
l.SITE,
l.MX_ET,
l.MX_MT,
l.CHANGE_DATE AS db_date,
d.BAND
FROM ALL_LOCATIONS l
INNER JOIN LOC_DETATILS d ON (l.location = d.location)
WHERE l.status = 'ACTIVE' ;
Table:
CREATE TABLE DB_LOCATIONS
( "LOCATIONID" NUMBER,
"DB_DATE" DATE,
"MX_ET" NUMBER(10,2),
"MX_MT" NUMBER(10,2),
"SITE" VARCHAR2(8),
"BAND" NUMBER
) SEGMENT CREATION IMMEDIATE
PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255
NOCOMPRESS LOGGING
STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
TABLESPACE "DB_DATA" ;
Upvotes: 1
Views: 597
Reputation: 168001
You do not specify the order of the columns in the INSERT ALL
statement and if the columns of the tables are in different orders then you will find that using SELECT *
and not specifying the columns will attempt to put the column from one table into the wrong column in the other table.
For example:
CREATE TABLE DB_LOCVIEW (DB_DATE, MX_ET, MX_MT, LOCATIONID, BAND, SITE) AS
SELECT SYSDATE, 'ABC', 'DEF', 1, 23, 'GHI' FROM DUAL;
-- Create the table with the columns in a different order
CREATE TABLE DB_LOCATIONS (DB_DATE, LOCATIONID, MX_ET, MX_MT, BAND, SITE) AS
SELECT DB_DATE, LOCATIONID, MX_ET, MX_MT, BAND, SITE FROM DB_LOCVIEW WHERE 1 = 0;
Then running your INSERT ALL
query fails with the error:
SQLCODE: -1722 -SQLERRM: ORA-01722: invalid number
This is because the statement is effectively expanded to:
BEGIN
INSERT ALL
INTO DB_LOCATIONS (DB_DATE, LOCATIONID, MX_ET, MX_MT, BAND, SITE)
SELECT DB_DATE, MX_ET, MX_MT, LOCATIONID, BAND, SITE FROM DB_LOCVIEW;
COMMIT;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.put_line ('SQLCODE: ' || SQLCODE||' -SQLERRM: '||SQLERRM);
END;
/
And you can see that the columns do not match. So, even though the columns have identical types, the order of the columns matters.
Instead, you can specify the columns and their order:
BEGIN
INSERT ALL
INTO DB_LOCATIONS (DB_DATE, MX_ET, MX_MT, LOCATIONID, BAND, SITE)
SELECT DB_DATE, MX_ET, MX_MT, LOCATIONID, BAND, SITE FROM DB_LOCVIEW;
COMMIT;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.put_line ('SQLCODE: ' || SQLCODE||' -SQLERRM: '||SQLERRM);
END;
/
Or use INSERT INTO ... SELECT
and specify the columns:
BEGIN
INSERT INTO DB_LOCATIONS (DB_DATE, LOCATIONID, MX_ET, MX_MT, BAND, SITE)
SELECT DB_DATE, LOCATIONID, MX_ET, MX_MT, BAND, SITE FROM DB_LOCVIEW;
COMMIT;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.put_line ('SQLCODE: ' || SQLCODE||' -SQLERRM: '||SQLERRM);
END;
/
Note: You do not need to catch the exception; if there is an error then it will stop the PL/SQL block, implicitly rollback the transaction and print the error trace. Additionally, catching OTHERS
is considered bad practice. If you do want to catch the exception then you should catch specific expected exceptions then you know when there is an uncaught exception that something unexpected has occurred and you can debug it; if you catch all exceptions then you lose the ability to identify unexpected behaviours.
Or, without PL/SQL:
INSERT INTO DB_LOCATIONS (DB_DATE, LOCATIONID, MX_ET, MX_MT, BAND, SITE)
SELECT DB_DATE, LOCATIONID, MX_ET, MX_MT, BAND, SITE FROM DB_LOCVIEW;
COMMIT;
db<>fiddle here
Upvotes: 3