1

以下は、テーブルが存在するかどうかを判断し、テーブルを削除/作成する 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;
/ 
4

2 に答える 2

3

まず、テーブルを削除して再作成する PL/SQL スクリプトは非常に疑わしいものです。たとえば、単に定期的に更新するだけの具体化されたビューを作成したくないと本当に確信していますか? PL/SQL で DDL を実行することは、ほとんどの場合、不適切なアプローチです。解決しようとしているビジネス上の問題を説明していただければ、より適切な技術的解決策を提示できる可能性があります。

第 2 に、PL/SQL で文字列内の一重引用符をエスケープする場合は、2 つの連続した一重引用符を使用する必要があります。単一の二重引用符ではありません。

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;
于 2013-02-08T23:21:10.317 に答える
2

一重引用符を別の一重引用符でエスケープする必要があります

  AND trim(bf.fee_type) = ''E''
于 2013-02-08T23:22:33.307 に答える