INSERT ALL INTO 抛出 ORA-01722: 无效数字
INSERT ALL INTO throws ORA-01722: invalid number
我想将视图复制到 table。下面的过程抛出 ORA-01722:无效数字
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;
另一方面,如果我用 for 循环尝试,一切都很好:
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;
视图和 table 只有 5 个相同的列。知道为什么插入所有抛出异常吗?
编辑:
添加创建程序:
查看:
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" ;
您没有在 INSERT ALL
语句中指定列的顺序,如果 table 的列顺序不同,那么您会发现使用 SELECT *
和未指定列将尝试将一个 table 中的列放入另一个 table.
中的错误列中
例如:
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;
然后 运行 您的 INSERT ALL
查询失败并显示错误:
SQLCODE: -1722 -SQLERRM: ORA-01722: invalid number
这是因为该语句有效扩展为:
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;
/
而且您可以看到列不匹配。因此,即使列具有相同的类型,列的顺序也很重要。
相反,您可以指定列及其顺序:
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;
/
或使用 INSERT INTO ... SELECT
并指定列:
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;
/
注意:您不需要捕获异常;如果出现错误,它将停止 PL/SQL 块,隐式回滚事务并打印错误跟踪。此外,捕获 OTHERS
被认为是不好的做法。如果你确实想捕获异常,那么你应该捕获特定的预期异常,然后你知道什么时候有未捕获的异常发生了意想不到的事情,你可以调试它;如果您捕捉到所有异常,那么您将失去识别意外行为的能力。
或者,没有 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
我想将视图复制到 table。下面的过程抛出 ORA-01722:无效数字
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;
另一方面,如果我用 for 循环尝试,一切都很好:
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;
视图和 table 只有 5 个相同的列。知道为什么插入所有抛出异常吗?
编辑: 添加创建程序:
查看:
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" ;
您没有在 INSERT ALL
语句中指定列的顺序,如果 table 的列顺序不同,那么您会发现使用 SELECT *
和未指定列将尝试将一个 table 中的列放入另一个 table.
例如:
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;
然后 运行 您的 INSERT ALL
查询失败并显示错误:
SQLCODE: -1722 -SQLERRM: ORA-01722: invalid number
这是因为该语句有效扩展为:
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;
/
而且您可以看到列不匹配。因此,即使列具有相同的类型,列的顺序也很重要。
相反,您可以指定列及其顺序:
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;
/
或使用 INSERT INTO ... SELECT
并指定列:
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;
/
注意:您不需要捕获异常;如果出现错误,它将停止 PL/SQL 块,隐式回滚事务并打印错误跟踪。此外,捕获 OTHERS
被认为是不好的做法。如果你确实想捕获异常,那么你应该捕获特定的预期异常,然后你知道什么时候有未捕获的异常发生了意想不到的事情,你可以调试它;如果您捕捉到所有异常,那么您将失去识别意外行为的能力。
或者,没有 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