检查架构中的 IF 表 EXISTS 时发生 Oracle PL/SQL 过程错误 [重复]
Posted
技术标签:
【中文标题】检查架构中的 IF 表 EXISTS 时发生 Oracle PL/SQL 过程错误 [重复]【英文标题】:Oracle PL/SQL Procedure Error while checking IF table EXISTS in schema [duplicate] 【发布时间】:2014-04-30 06:33:37 【问题描述】:我正在使用 SQL Developer Tool 创建一个过程,该过程检查名为 TRANSPORT_PRODUCT 的表是否存在,如果存在则截断它,如果不存在则创建它。
场景 1:当架构中不存在 TRANSPORT_PRODUCT 并且我编译过程时,编译过程时出现以下错误
Error(44,2): PL/SQL: SQL Statement ignored
Error(44,14): PL/SQL: ORA-00942: table or view does not exist
场景 2: 如果我创建表 TRANSPORT_PRODUCT 然后创建过程并运行,一切看起来都很好,除了我在过程中使用以下查询来检查表是否存在,其中变量 TABLE_EXISTS 初始化为 0,
select COUNT(*) INTO TABLE_EXISTS from user_tables where table_name= TABLE_NAME;
DBMS_OUTPUT.PUT_LINE('IF 0 THEN TABLE DOES NOT EXISTS ELSE TABLE EXISTS -'||TO_CHAR(TABLE_EXISTS,99));
值 48 存储在 TABLE_EXISTS 中 .. 这对我来说很奇怪 :(
场景 3: 如果我创建 TRANSPORT_PRODUCT 表然后创建程序,删除 TRANSPORT_PRODUCT 并运行程序,我会收到以下消息,我不确定 为什么程序依赖于表!
Error report:
ORA-06550: line 1, column 7:
PLS-00905: object XAAL5.EXPORT_PRODUCT is invalid
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
我的程序:
CREATE OR REPLACE PROCEDURE EXPORT_PRODUCT IS
TABLE_NAME VARCHAR2(50) NULL;
TABLE_EXISTS INTEGER:=0;
TRUNC_TABLE VARCHAR2(50) NULL;
CREATE_TABLE VARCHAR2(1000) NULL;
BEGIN
DBMS_OUTPUT.PUT_LINE('Procedure Start Time :' || to_char(systimestamp,'DD-MM-YY HH:MM:SS'));
TABLE_NAME:='TRANSPORT_PRODUCT';
select COUNT(*) INTO TABLE_EXISTS from user_tables where table_name= TABLE_NAME;
DBMS_OUTPUT.PUT_LINE('IF 0 THEN TABLE DOES NOT EXISTS ELSE TABLE EXISTS -'||TO_CHAR(TABLE_EXISTS,99));
IF (TABLE_EXISTS<>0) THEN
BEGIN
DBMS_OUTPUT.PUT_LINE(TABLE_NAME||' TRANSPORT_PRODUCT TABLE EXISTS AND WILL BE TRUNCATED');
TRUNC_TABLE:='truncate table '|| TABLE_NAME;
--DBMS_OUTPUT.PUT_LINE(TRUNC_TABLE);
execute immediate TRUNC_TABLE;
END;
ELSE
BEGIN
DBMS_OUTPUT.PUT_LINE(TABLE_NAME ||' DOES NOT EXISTS AND WILL BE CREATED');
CREATE_TABLE:=
'CREATE TABLE TRANSPORT_PRODUCT (
ROW_NUMBER NUMBER,
PRODUCTID VARCHAR2(20),
PRODUCTNAME VARCHAR2(100),
OWNER VARCHAR2(20),
DIVISIONID VARCHAR2(20),
MERCHLEVEL1 VARCHAR2(20),
MERCHLEVEL2 VARCHAR2(20),
MERCHLEVEL3 VARCHAR2(20),
MERCHLEVEL4 VARCHAR2(20),
STREAMID VARCHAR2(20),
SPECIFICATION VARCHAR2(20),
SSS VARCHAR2(20))';
execute immediate CREATE_TABLE;
END;
END IF;
-- INSERT PRODUCT INTO TRANSPORT_PRODUCT
INSERT INTO TRANSPORT_PRODUCT (ROW_NUMBER,PRODUCTID,PRODUCTNAME,OWNER, DIVISIONID,MERCHLEVEL1, MERCHLEVEL2, MERCHLEVEL3,MERCHLEVEL4,STREAMID,SPECIFICATION,SSS)
SELECT ROWNUM,
PRODUCTID,
PRODUCTNAME,
OWNER,
DIVISIONID,
MERCHLEVEL1,
MERCHLEVEL2,
MERCHLEVEL3,
MERCHLEVEL4,
STREAMID,
SPECIFICATION,
SSS
FROM PRODUCT;
DBMS_OUTPUT.PUT_LINE('Procedure End Time :' || to_char(systimestamp,'DD-MM-YY HH:MM:SS'));
exec buildfile('select * from TRANSPORT_PRODUCT where rownum<=500');
commit;
END;
【问题讨论】:
简单地说,您的过程依赖于表,因为您在 INSERT 语句中静态访问它。如果表不存在,这也必须是动态的。 @Ben 感谢您的解释和链接,我这里还有一个问题,它在查询 USER_TABLES 时。理想情况下,当表不存在时,以下查询应将 0 存储在变量中,但这是存储 48 :( [select COUNT(*) INTO TABLE_EXISTS from user_tables where table_name= TABLE_NAME;] 为什么还要动态创建呢?如果您的架构稳定,您可以避免这种情况。在这种情况下,看起来这个逻辑只需要一次,除非您稍后将表放到其他地方。在过程中进行 DDL 通常不是一个好主意。 不要调用你的变量TABLE_NAME
then...SQL 范围优先于 PL/SQL 范围,因为它发生在 SQL 中。调用你的变量l_table_name
(本地)或其他东西。
@Kfactor21 - AlexisSTDM 已经回答了那部分?
【参考方案1】:
我可以看到方案 2 的问题是您使用的过程参数名称 TABLE_NAME 与 USER_TABLES 的列名称相同。然后查询会为您提供架构中的表总数。 TABLE_NAME = TABLE_NAME 始终匹配。
我认为您的程序也是如此。您在过程中静态使用表。
谢谢 问候。
【讨论】:
这是常识 :(((( ,我怎么错过了,@alexisSTDM 谢谢你叫醒我.. 没关系我总是忘记oracle不区分大小写。谢谢你以上是关于检查架构中的 IF 表 EXISTS 时发生 Oracle PL/SQL 过程错误 [重复]的主要内容,如果未能解决你的问题,请参考以下文章
MySQL 当记录不存在时插入(insert if not exists)
MySQL 当记录不存在时插入(insert if not exists)
IF 语句中的 jQuery OR 运算符检查任一文本字段是不是为空
使用 Pandas 附加 BigQuery 表时如何修复无效架构