valmont74
valmont74

Reputation: 1237

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. If it does not exist, create the table, anyway. So, when I ran the script, I received the following:

ORA-00904: "E": invalid identifier

I thought that the syntax was accurate and the double quoted 'E' was correct, but apparently, not. 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;
/ 

Upvotes: 1

Views: 3001

Answers (2)

codingbiz
codingbiz

Reputation: 26396

You need to Escape the single quote with another single quote

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

Upvotes: 2

Justin Cave
Justin Cave

Reputation: 231791

First off, a PL/SQL script that drops and recreates a table is highly suspect. 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. 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. 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

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;

Upvotes: 3

Related Questions