简体   繁体   English

如何使用EXECUTE IMMEDIATE语句更正PL / SQL脚本中的ORA-00904错误?

[英]How do I correct the ORA-00904 error in PL/SQL script using EXECUTE IMMEDIATE statement?

Below is the PL/SQL script to determine if the table exists then drop/create the table. 下面是PL / SQL脚本,用于确定表是否存在,然后删除/创建表。 If it does not exist, create the table, anyway. 如果不存在,则仍然创建表。 So, when I ran the script, I received the following: 因此,当我运行脚本时,收到以下消息:

ORA-00904: "E": invalid identifier ORA-00904:“ E”:无效的标识符

I thought that the syntax was accurate and the double quoted 'E' was correct, but apparently, not. 我认为语法是正确的,双引号'E'是正确的,但显然不是。 Please advise. 请指教。

Thanks. 谢谢。

DECLARE 

  l_cnt NUMBER;

BEGIN
  SELECT COUNT(*)
    INTO l_cnt
    FROM dba_tables
   WHERE owner = 'ABCD'
     AND table_name = 'SEC_REC_TEMP';

  IF( l_cnt > 0 )
  THEN
     EXECUTE IMMEDIATE 'DROP TABLE sec_rec_temp';
     EXECUTE IMMEDIATE 'CREATE TABLE sec_rec_temp 
                        AS
                        SELECT is.inv_num
                          FROM abcd.inv_summ is
                              ,abcd.bill_fee bf
                         WHERE is.inv_num = bf.inv_num
                           AND trim(bf.fee_type) = "E"
                         GROUP BY is.inv_num';
  ELSE
     EXECUTE IMMEDIATE 'CREATE TABLE sec_rec_temp 
                        AS
                        SELECT is.inv_num
                          FROM abcd.inv_summ is
                              ,abcd.bill_fee bf
                         WHERE is.inv_num = bf.inv_num
                           AND trim(bf.fee_type) = "E"
                         GROUP BY is.inv_num';
  END IF;
END;
/ 

First off, a PL/SQL script that drops and recreates a table is highly suspect. 首先,高度可疑的是会删除并重新创建表的PL / SQL脚本。 Are you really sure that you don't want to create a materialized view that you simply refresh periodically, for example? 您是否真的确定不想创建只需要定期刷新的实例化视图? Doing DDL in PL/SQL is almost always a poor approach. 在PL / SQL中执行DDL几乎总是一种糟糕的方法。 If you can explain the business problem you're trying to solve, we can probably point you at a better technical solution. 如果您可以解释要解决的业务问题,我们可能会为您提供更好的技术解决方案。

Second, if you want to escape a single quote in a string in PL/SQL, you need to use two consecutive single quotes. 其次,如果要在PL / SQL中的字符串中转义单引号,则需要使用两个连续的单引号。 Not a single double-quote character. 没有一个双引号字符。

DECLARE 
  l_cnt NUMBER;
BEGIN
  SELECT COUNT(*)
    INTO l_cnt
    FROM dba_tables
   WHERE owner = 'ABCD'
     AND table_name = 'SEC_REC_TEMP';

  IF( l_cnt > 0 )
  THEN
     EXECUTE IMMEDIATE 'DROP TABLE sec_rec_temp';
     EXECUTE IMMEDIATE 'CREATE TABLE sec_rec_temp 
                        AS
                        SELECT is.inv_num
                          FROM abcd.inv_summ is
                              ,abcd.bill_fee bf
                         WHERE is.inv_num = bf.inv_num
                           AND trim(bf.fee_type) = ''E''
                         GROUP BY is.inv_num';
  ELSE
     EXECUTE IMMEDIATE 'CREATE TABLE sec_rec_temp 
                        AS
                        SELECT is.inv_num
                          FROM abcd.inv_summ is
                              ,abcd.bill_fee bf
                         WHERE is.inv_num = bf.inv_num
                           AND trim(bf.fee_type) = ''E''
                         GROUP BY is.inv_num';
  END IF;
END;

Alternately, you can use the q quoting syntax 或者,您可以使用q引用语法

DECLARE 
  l_cnt NUMBER;
BEGIN
  SELECT COUNT(*)
    INTO l_cnt
    FROM dba_tables
   WHERE owner = 'ABCD'
     AND table_name = 'SEC_REC_TEMP';

  IF( l_cnt > 0 )
  THEN
     EXECUTE IMMEDIATE 'DROP TABLE sec_rec_temp';
     EXECUTE IMMEDIATE q'[CREATE TABLE sec_rec_temp 
                        AS
                        SELECT is.inv_num
                          FROM abcd.inv_summ is
                              ,abcd.bill_fee bf
                         WHERE is.inv_num = bf.inv_num
                           AND trim(bf.fee_type) = 'E'
                         GROUP BY is.inv_num]';
  ELSE
     EXECUTE IMMEDIATE q'[CREATE TABLE sec_rec_temp 
                        AS
                        SELECT is.inv_num
                          FROM abcd.inv_summ is
                              ,abcd.bill_fee bf
                         WHERE is.inv_num = bf.inv_num
                           AND trim(bf.fee_type) = 'E'
                         GROUP BY is.inv_num]';
  END IF;
END;

您需要用另一个单引号将单引号转义

  AND trim(bf.fee_type) = ''E''

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM