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

时间:2013-02-08 23:16:11

标签: sql oracle

下面是确定表是否存在的PL / SQL脚本然后删除/创建表。如果它不存在,无论如何都要创建表。所以,当我运行脚本时,我收到了以下内容:

  

ORA-00904:“E”:标识符无效

我认为语法准确,双引号'E'是正确的,但显然不是。请指教。

感谢。

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;
/ 

2 个答案:

答案 0 :(得分:3)

首先,丢弃并重新创建表的PL / SQL脚本非常可疑。例如,你真的确定你不想创建一个只是定期刷新的物化视图吗?在PL / SQL中执行DDL几乎总是一种糟糕的方法。如果您可以解释您尝试解决的业务问题,我们可能会为您提供更好的技术解决方案。

其次,如果要在PL / SQL中转义字符串中的单引号,则需要使用两个连续的单引号。不是一个双引号字符。

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;

或者,您可以使用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;

答案 1 :(得分:2)

您需要使用另一个单引号来逃避单引号

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