ORA-00904 無効な識別子です。の解決方法

  • by
ORA-00904 Invalid Identifier - Oracle Database Object Name Recognition Examples

ORA-00904

ORA-00904は、文の中で一致しない列名または誤った構文を使用したことを意味します。通常、エラーはSELECTまたはINSERTで発生し、その他はUPDATEDELETECREATE TABLEALTER TABLE、またはPL / SQLブロックで発生している可能性があります。

ほとんどのユーザーはそのエラーを信じていませんが、実際にSQLパーサーは間違いを犯したことが一度もないので、この記事でエラーパターンを見てみるのが好きかもしれません。おそらく、エラーパターンの1つがあなたのケースにマッチします。ほとんどのエラーは大文字と小文字を区別する問題なので、最初に緩い形式厳密な形式の違いを説明する必要があります。

通常、Oracleは、パスワード以外の大部分の識別子を大/小文字を区別しないものとして扱います。 ただし、ORA-00904無効な識別子が生成された場合に注意が必要な特別な使用法がいくつかあります。

ORA-00904だけでなく、ORA-00903およびORA-00911も、オブジェクト識別子の無効な使用法に関連しています。 具体的には、ORA-00903は無効なテーブル名をユーザーに警告し、不正な文字を配置するためにORA-00911が発生します。

緩い形式と厳密な形式

Oracle Databaseのオブジェクト名と修飾子によると、データベース・オブジェクトを作成するための有効な命名形式は2種類あります。1つは引用符で囲まれていない識別子、もう1つは引用符で囲まれた識別子です。ORA-00904を回避するには、2つの命名形式の明確な違いを知っておく必要があります。

引用符で囲まれていない識別子(緩い形式)

句読点やその他の特別な扱いに囲まれていません。基本的に同等の文字列である限り、SQLステートメントでは大文字と小文字を区別せずに柔軟に使用できます。だから私は通常この記事でそれを緩い形式と呼びます。

引用符付き識別子(厳密な形式)

それらは二重引用符( "")で始まり、終わります。空白や予約語を含め、ほとんどすべての文字を二重引用符で囲むことができます。この種の識別子は、最初に定義されたとおりに使用する必要があります。だから私は通常、この記事ではそれを厳密な形式と呼びます。私の知る限りでは、これがORA-00904の主な原因です。

後ほど、ORA-00904無効な識別子についても詳しく説明します。

ORA-00904のエラー・パターン

ほとんどの場合、列名の誤用がORA-00904の主な原因であり、残りは構文エラーです。この記事では、次の項でORA-00904のいくつかのエラー・パターンについて説明します。

  1. SELECT, INSERTのORA-00904
  2. WHERE, ORDER BY, GROUP BYのORA-00904
  3. CREATE TABLEのORA-00904
  4. ALTER TABLEのORA-00904
  5. PL/SQLのORA-00904

A. SELECT文またはINSERT文のORA-00904

SELECTまたはINSERTにリストされている列はすべてこのエラーを生成する可能性があります。

この項では、ORA-00904がユーザーに何か問題があることを警告しています。これは、次のいずれかの理由で発生する可能性があります。

  1. 存在しない列
  2. 存在しない関数
  3. スペルミスの柱
  4. 大文字と小文字を区別する列
  5. 列名の中のブランク

1. 存在しない列によるORA-00904

通常、二重引用符を使わずにテーブルを作成します。

SQL> create table all_names_1 (First_Name varchar2(25), Last_Name varchar2(25));

Table created.

それからデータを挿入します。

SQL> insert into all_names_1 select distinct first_name, last_name from employees;

107 rows created.

このテーブルを引用符なしでクエリできます。つまり、小文字または大文字のどちらの列名も有効で受け入れ可能です。これは、SQLパーサーがすべての識別子を大文字のものとして扱うためです。

SQL> select first_name, last_name from all_names_1 where first_name = 'Ed';

FIRST_NAME                LAST_NAME
------------------------- -------------------------
Ed                        Chen

このように通常作成された表を使用すると、もうORA-00904がなくなることが保証されますか?無効な識別子の2つの一般的な種類を見てみましょう。

最初のケースは、テーブルに存在しない列を選択することです。

SQL> select first_name, last_name, num from all_names_1 where first_name = 'Ed';
select first_name, last_name, num from all_names_1 where first_name = 'Ed'
                              *
ERROR at line 1:
ORA-00904: "NUM": invalid identifier
SQL> insert into all_names_1 (first_name, last_name, num) values ('Ed', 'Chen', 100);
insert into all_names_1 (first_name, last_name, num) values ('Ed', 'Chen', 100)
                                                *
ERROR at line 1:
ORA-00904: "NUM": invalid identifier
ORA-00904 Toad for Oracleの識別子が無効です。

ORA-00904 Toad for Oracleの識別子が無効です。

ご存じのとおり、列NUMはテーブルに存在しないため無効な列です。テーブルを記述して定義を確認したほうがよいでしょう。

SQL> desc all_names_1;
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 FIRST_NAME                                         VARCHAR2(25)
 LAST_NAME                                          VARCHAR2(25)

2. 存在しない機能によるORA-00904

このパターンはまれですが、存在しない関数呼び出しについて話すべきです。再現方法を見てみましょう。

SQL> select first_name, month(hire_date) hire_month from employees where last_name = 'Chen';
select first_name, month(hire_date) hire_month from employees where last_name = 'Chen'
                   *
ERROR at line 1:
ORA-00904: "MONTH": invalid identifier

SQLパーサーは最初にMONTHという名前の関数と一致させようとしましたが、何も見つからなかったため、列と一致し、一致しませんでした。MySQLにはMONTH機能がありますが、Oracleにはありません。存在しない関数DATEDIFFが無効なIDであるのと同じ理由。

ORA-00904の解決策は、EXTRACTという名前の正しいOracle関数を呼び出して、列の月の値を取得することです。

SQL> select first_name, extract(month from hire_date) hire_month from employees where last_name = 'Chen';

FIRST_NAME           HIRE_MONTH
-------------------- ----------
Ed                            9

関数DATEDIFFはOracleでは機能しません

それを注意してください、あなたのようなMySQLの中で使用するために使用されるいくつかの日付時刻関数DATEDIFFYEARMONTHは、NOWSUBSTRING、 Oracleで有効な機能や識別子ではありません。あなたは確認することがOracleのSQL言語リファレンス:機能確認のため。

3. 列のスペルミスによるORA-00904

2番目のケースは、スペルミスのある誤った列名を選択することです。これは、ORA-00904の最も一般的なパターンです。

SQL> select first name, last_name from all_names_1 where first_name = 'Ed';
select first name, last_name from all_names_1 where first_name = 'Ed'
       *
ERROR at line 1:
ORA-00904: "FIRST": invalid identifier

このステートメントでは、FIRSTNAMEの間にアンダースコアを付けずに、意図的に列名を無効にしました。その結果、SQLパーサーは次のようにステートメントを翻訳しました。

NAMEとしてエイリアスされたFIRST列と、残りの条件を持つテーブルALL_NAMES_1からの列LAST_NAMEをクエリするには。
もちろん、FIRSTという名前の有効な列はなく、First Nameもありません。有効で真の識別子はFIRST_NAMEです。スペルをもう一度確認してから、識別子を修正してください。

列名の入力ミスを避けるために、列名の自動補完を容易にするために、SQL Developer、Toad for Oracle、PL / SQL DeveloperなどのGUIツールを使用できます。SQL Developerの例を次に示します。

ORA-00904無効な識別子を回避するためのSQL Developer Editorでの列名の自動補完

ORA-00904無効な識別子を回避するためのSQL Developer Editorでの列名の自動補完

お分かりのように、私たちはいくつかの手紙を提供しました、そしてSQL開発者のエディタは残りを大事にします。

4. 大文字と小文字を区別する列

場合によっては、SQLパーサーは欠落している列について不満を言っていますが、列はテーブルに存在します。これはどのように起こりますか?知っておく必要があるのは、厳密な形式を使用してSQLステートメントで列を表現する方法だけです。

厳密な形式の識別子を使用するには、列名を折り返すために二重引用符を使用する必要があります。これにより、指定したとおりに厳密な名前を作成するようデータベースに通知されます。厳密には?少なくとも、大文字と小文字を区別する識別子として扱うべきです。

SQL> create table all_names_2 ("First_Name" varchar2(25), "Last_Name" varchar2(25));

Table created.

それからデータを挿入します。

SQL> insert into all_names_2 select distinct first_name, last_name from employees;

107 rows created.

これからは、テーブルを昔のように大まかに使用することはできなくなります。そうでなければ、文に無効な識別子を使用し、その後ORA-00904を受け取る可能性が非常に高いです。

列に二重引用符を追加しないと、ORA-00904になります。

SQL> select First_Name, Last_Name from all_names_2 where First_Name = 'Ed';
select First_Name, Last_Name from all_names_2 where First_Name = 'Ed'
                                                    *
ERROR at line 1:
ORA-00904: "FIRST_NAME": invalid identifier
SQL> insert into all_names_2 (First_Name, Last_Name) values ('Ed', 'Chen');
insert into all_names_2 (First_Name, Last_Name) values ('Ed', 'Chen')
                                     *
ERROR at line 1:
ORA-00904: "LAST_NAME": invalid identifier

列名は文字通りその定義と同じですが、列に二重引用符がないため、ORA-00904が発生しました。これは、引用符で囲まれていない識別子First_Nameが、大文字のFIRST_NAMEとしておおまかに認識されているためです。したがって、SQLパーサーはテーブル内で一致するIDを見つけることができません。結局、false列を警告するためにORA-00904が発生しました。

解決方法

解決方法は簡単で、引用符で囲まれていない形式ではなく、テーブルの作成時に指定したとおりに引用符を付ける必要があります。

SQL> select "First_Name", "Last_Name" from all_names_2 where "First_Name" = 'Ed';

First_Name                Last_Name
------------------------- -------------------------
Ed                        Chen
SQL> insert into all_names_2 ("First_Name", "Last_Name") values ('Ed', 'Chen');

1 row created.

文を有効にするために厳密な形式を使用しました。ご覧のとおり、厳密な形式を使用することは非常に不便です。識別子が無効にされないようにするために、識別子に関する細かい点すべてに注意する必要があります。

5. 列名の空白

厳密な形式により、空白で埋められた列を作成できます。これは、ORA-00904無効化の問題がなくても有効です。まず普通の表を見てみましょう。

SQL> create table all_names_3 (First_Name varchar2(25), Last_Name varchar2(25), Num int, Create_Date date default sysdate);

Table created.

SQL> insert into all_names_3 (first_name, last_name, num) select first_name, last_name, count(*) from employees group by first_name, last_name;

107 rows created.

SQL> select first_name, last_name, num, create_date from all_names_3 where first_name = 'Ed';

FIRST_NAME                LAST_NAME                        NUM CREATE_DA
------------------------- ------------------------- ---------- ---------
Ed                        Chen                               1 12-MAR-19

次に、列名に空白が含まれている奇妙だが有効なケースを見てみましょう。

SQL> create table all_names_4 ("First_Name" varchar2(25), "Last_Name" varchar2(25), " " int, "  " date default sysdate);

Table created.

SQL> insert into all_names_4 ("First_Name", "Last_Name", " ") select first_name, last_name, count(*) from employees group by first_name, last_name;

107 rows created.

SQL> select "First_Name", "Last_Name", " ", "  " from all_names_4 where "First_Name" = 'Ed';

First_Name                Last_Name
------------------------- ------------------------- ---------- ---------
Ed                        Chen                               1 12-MAR-19

ご覧のとおり、3番目の列に1つの空白スペース、4番目の列に2つの空白スペースを使用しました。規則に従って表を問い合せる限り、ORA-00904がなくてもうまく機能します。

名前の衝突または無効化 いいえ、これは同じテーブルのネームスペース内の1つの空白が2つの空白とは異なるためです。特に列を定義するために厳密な形式を使用している場合はそうです。

テーブルを慎重かつ適切に使用しているため、ORA-00904および無効化の問題は発生しませんでしたが、厳密なスタイルの命名は混乱を招きます。奇妙だが有効な表について説明してください。

SQL> desc all_names_4;
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 First_Name                                         VARCHAR2(25)
 Last_Name                                          VARCHAR2(25)
                                                    NUMBER(38)
                                                    DATE

したがって、3列目と4列目にはほとんど情報が表示されません。ここで何が起こっているのか全くわからない、新しいメンバーのために。さらに、このような奇数表を問い合せるときにORA-00904がスローされると、誰もそれをトラブルシューティングできません。

これは私がUnix OSで空または空白の名前のファイルを削除しようとしたことがあることを私に思い出させます。直すのに長い時間がかかりました。

B. WHERE句、ORDER BY句、またはGROUP BY句のORA-00904

上記で説明した、存在しない列存在しない関数スペルミスのある列大文字と小文字を区別する列などの列の不一致の問題は、WHERE句、ORDER BY句、またはGROUP BY句でも発生する可能性があります。

このセクションでは、WHERE句またはGROUP BY句で列の別名を使用する方法について具体的に説明します。

  1. 列の別名が誤って使用

1. 列の別名が誤って使用のORA-00904

このように、ORDER BY句で列の別名を使用できます。

SQL> column did format 9999;
SQL> column eid format 9999;
SQL> select department_id as did, employee_id as eid from employees order by did;

  DID   EID
----- -----
   10   200
   20   201
...

しかし、WHERE句で列の別名を直接使用することはできません。

SQL> select department_id as did, employee_id as eid from employees where did > 50;
select department_id as did, employee_id as eid from employees where did > 50
                                                                     *
ERROR at line 1:
ORA-00904: "DID": invalid identifier

GROUP BY句にもありません。

SQL> select department_id as did, count(employee_id) as cnt from employees group by did;
select department_id as did, count(employee_id) as cnt from employees group by did
                                                                               *
ERROR at line 1:
ORA-00904: "DID": invalid identifier

私たちはみんな、列のDIDが何であるかを知っていますが、SQLパーサーは知りません。問題を警告するためにORA-00904をスローしました。

ソリューション

もちろん、実際の列名を使用していつでもORA-00904を抑制できます。このようにすれば、ステートメントはより安定したものになります。

WHERE句で列の別名を使用できるようにするには、外側のSELECTでクエリをラップする必要があります。

SQL> select * from (select department_id as did, employee_id as eid from employees) where did > 50;

  DID   EID
----- -----
   90   100
   90   101
...

以下のために、GROUP BY列の別名を使用したいの句、それは少しトリッキーです。

SQL> select did, count(eid) cnt from (select department_id as did, employee_id eid from employees) group by did;

  DID        CNT
----- ----------
  100          6
   30          6
...

つまり、列の別名を使用すると主張した場合、このエラーパターンでは外側のSELECTがORA-00904の解決策になります。これにより、すべての列の別名を実際の列名と見なすことができます。

そこにいる列の別名の上のより微妙な使用法c_aliasでいくつかの中にSELECT副次句など、search_clausecycle_clauseorder_by_clauseには。

C. CREATE TABLE文のORA-00904

CREATE TABLE文には、いくつかのORA-00904のパターンがあります。

  1. 予約語の誤用
  2. 誤って追加のコンマを追加
  3. 数字で始まる

1. 予約語の誤用によるORA-00904

ORA-00904のようなエラーは、あらゆる種類のオブジェクト作成で発生する可能性があります。命名規則を明確にするために、誤った種類の識別子を見てみましょう。

予約語を使用することはワイルドです、それらを含むすべては最終的に予測不可能で厄介になるかもしれません。データベースオブジェクトの名前を付けるためにそれらを使用しないでください。

SQL> create table t1 (audit int);
create table t1 (audit int)
                 *
ERROR at line 1:
ORA-00904: : invalid identifier

再度ORA-00904を見ましたが、今回はSQLパーサーは列名を認識できず、無効なストリングを空のままにしました。

それらを使用することを主張する場合は、二重引用符、厳密な形式を使用してください。

SQL> create table t1 ("audit" int);

Table created.

たぶん、あなたのユーザは、全く無意識の状況下でそのようなデータベースオブジェクトを作成するかもしれません。これらのツールが残りの面倒を見るからです。

2. 誤って追加のカンマを追加したためにORA-00904

ステートメントに誤って追加のコンマが追加されていると、SQLパーサーは何をすべきかわからなくなります。いくつかの例を見てみましょう。

SQL> create table t1 (c1 number, c2 date,);
create table t1 (c1 number, c2 date,)
                                    *
ERROR at line 1:
ORA-00904: : invalid identifier
SQL> create table t1 (c1 number,, c2 date);
create table t1 (c1 number,, c2 date)
                           *
ERROR at line 1:
ORA-00904: : invalid identifier

ご覧のとおり、列リストに追加のコンマがあります。SQLパーサーは、追加のカンマの後に何もないであることを認識していましたが、無効な使用法を修正するために結局ORA-00904を残しました。

すでに説明したように、純粋な空白を使用して列を定義することは、テーブルを作成するために厳密な形式を使用している限り、許容でき、意味があります。しかし、何もないのコラムは別の考えで、まったく無意味です。ORA-00904がスローされたのも当然です。

問題を解決するには、ステートメントを機能させるために余分なコンマを削除する必要があります。

SQL> create table t1 (c1 number, c2 date);

Table created.

3. 数値で始まるためORA-00904

数字で始まるテーブル名は?

SQL> create table t1 (12345678 int);
create table t1 (12345678 int)
                 *
ERROR at line 1:
ORA-00904: : invalid identifier

ORA-00904では、ここでは違法であると警告されています。そのため、ORA-00904を修正するために識別子の前に文字「c」を追加しました。

SQL> create table t1 (c12345678 int);

Table created.

使用されている無効な文字については、次のようにこの問題を警告するためにORA-00911が発生します。

SQL> create table $t1 (c12345678 int);
create table $t1 (c12345678 int)
             *
ERROR at line 1:
ORA-00911: invalid character

実際、ドル記号「$」は識別子に有効です。オブジェクト名の先頭に付けないでください。特殊文字の制限について詳しくは、次の規則に進んでください。

ORA-00911はオブジェクト命名の不正な使用方法ですが、ORA-00904ほど明確ではありません。それでは、オブジェクトの命名に特殊文字を使用する方法を見てみましょう。

特殊キャラクター

"$"、 "_"、および "#"のみが許可されています。 列名の場合、不適切な特殊文字 "?"を使用した無効な文字に対してORA-00911が発生します。

SQL> create table t1 (c12345678?production int);
create table t1 (c12345678?production int)
                          *
ERROR at line 1:
ORA-00911: invalid character

ORA-00904ではなく、疑問符が無効な文字であることを知らせるORA-00911を見ました。そこで、問題を解決するために"?"を"$"、"#"、または"_"に変更しました。

ドル記号

SQL> create table t1 (c12345678$production int);

Table created.

番号記号

SQL> create table t2 (c12345678#production int);

Table created.

下線

SQL> create table t3 (c12345678_production int);

Table created.

実際には、識別子に文字列を使用するのはかなり普通のことです。スペースの代わりに、文字列内の意味のある単語を区切るためにアンダースコアがよく使用され推奨されます。

D. ALTER TABLEステートメントのORA-00904

同様の問題は存在しない列存在しない関数スペルミスの列大文字と小文字を区別列は また、ここで適用されます。したがって、このセクションでは、まれにいくつかの稀なケースについて説明します。

ALTER TABLEステートメントには、いくつかのORA-00904のパターンがあります。

  1. ALTER TABLE ADD Column
  2. ALTER TABLE MODIFY Column
  3. ALTER TABLE ADD CONSTRAINT NOT NULL

1. ALTER TABLE ADD ColumnのORA-00904

ALTER DATABASE ADD列ステートメントの一般的なORA-00904 は、次のとおりです。

SQL> alter table t1 add column c2 date;
alter table t1 add column c2 date
                   *
ERROR at line 1:
ORA-00904: : invalid identifier

予約語COLUMNに明示的に配置されているORA-00904 は有効な識別子ではありません。実際、これは構文エラーです。予約語のCOLUMNを追加する必要はありません。

SQL> alter table t1 add c2 date;

Table altered.

さらに、ADDの直後にその位置に予約語を使用することはできません。

2. ALTER TABLE MODIFY ColumnのORA-00904

ALTER DATABASE MODIFY列ステートメントにORA-00904の場合を見てみましょう。

SQL> alter table all_names_1 modify (column fname varchar2(30));
alter table all_names_1 modify (column fname varchar2(30))
                                *
ERROR at line 1:
ORA-00904: : invalid identifier

ここでも同じ理由で、ステートメントに予約語のCOLUMNを追加する必要はありません。削除してください。

予約語を削除した後も、無効な列名を意図的に使用したため、依然としてORA-00904が返されました。

SQL> alter table all_names_1 modify (fname varchar2(30));
alter table all_names_1 modify (fname varchar2(30))
                                *
ERROR at line 1:
ORA-00904: "FNAME": invalid identifier

FNAMEがテーブルに見つかりません。有効な列名はFIRST_NAMEです。

SQL> alter table all_names_1 modify (first_name varchar2(30));

Table altered.

3. ALTER TABLE ADD CONSTRAINT NOT NULLのORA-00904

SQL> create table t1 (c1 number);

Table created.

次のようにALTER TABLE ADD CONSTRAINTステートメントの列にUNIQUE制約を追加できます。

SQL> alter table t1 add constraint c1_unique UNIQUE (c1);

Table altered.

しかし、同じ方法でNOT NULL制約を列に追加することはできません。

SQL> alter table t1 add constraint c1_nn NOT NULL (c1);
alter table t1 add constraint c1_nn NOT NULL (c1)
                                    *
ERROR at line 1:
ORA-00904: : invalid identifier

ご覧のとおり、SQLパーサーがORA-00904をスローして、ステートメントで使用されている識別子名が不正であることを警告しています。実際、これは構文エラーです。

どうして?NOT NULLは制約ですね。もちろん、NOT NULLLはある種の制約ですが、それはむしろ列属性であり、間違った方法で使用されています。最初にそれを制約として扱いましょう。

解決策1:それを制約と見なす

基本的に、Oracleのconstraint句には4種類の副次句があります。

  • inline_constraint
  • out_of_line_constraint
  • inline_ref_constraint
  • out_of_line_ref_constraint

ORA-00904を生成した上記の文では、NOT NULLを使用できないout_of_line_constraint句です。代わりに、NOT NULLに対してinline_constraintを使用する必要があります。そのため、制約NOT NULLを追加するときにORA-00904が表示されました。

SQL> alter table t1 modify (c1 constraint c1_nn NOT NULL);

Table altered.

制約名を確認しましょう。

SQL> select constraint_name from user_constraints where table_name = 'T1';

CONSTRAINT_NAME
------------------------------
C1_UNIQUE
C1_NN

SQL> alter table t1 drop constraint C1_NN;

Table altered.

他の制約とは異なり、NOT NULLを複合(複数列)制約にすることはできません。列に対してのみ機能します。

解決策2:列属性と見なす

厳密に言えば、NOT NULLは列属性なので、制約になる可能性があるとしても、制約として扱う必要はありません。

たとえば、次のように列をNOT NULLとして変更できます。

SQL> alter table t1 modify (c1 NOT NULL);

Table altered.

ご覧のとおり、私はこれを列属性として扱いました。制約句は含まれていません。制約名を確認しましょう。

SQL> select constraint_name from user_constraints where table_name = 'T1';

CONSTRAINT_NAME
------------------------------
C1_UNIQUE
SYS_C0011427
SQL> alter table t1 modify (c1 NULL);

Table altered.

SQL> select constraint_name from user_constraints where table_name = 'T1';

CONSTRAINT_NAME
------------------------------
C1_UNIQUE

つまり、制約名を削除するために制約名を知る必要はなく、単に属性を元に戻すだけです。

E. PL/SQLストアドプロシージャのORA-00904

これまでのところ、PL/SQLにはORA-00904の2つのエラー・パターンがあります。

  1. PL/SQLでの変数宣言の順序が正しくない
  2. 引用符で囲まれていない文字列

1. PL/SQLでの変数宣言の順序が正しくないためORA-00904

次のような変数を含むカーソルを使用したいとします。

SQL> declare
  2    cursor c1 is select employee_id from hr.employees where department_id = v_num;
  3    v_num number;
  4  begin
  5    v_num := 110;
  6    open c1;
  7  end;
  8  /
  cursor c1 is select employee_id from hr.employees where department_id = v_num;
                                                                          *
ERROR at line 2:
ORA-06550: line 2, column 75:
PLS-00320: the declaration of the type of this expression is incomplete or malformed
ORA-06550: line 2, column 75:
PL/SQL: ORA-00904: "V_NUM": invalid identifier

ORA-06550: line 2, column 16:
PL/SQL: SQL Statement ignored

PL/SQLエンジンからORA-00904がスローされました。 この場合、ORA-06550では、2行75列の識別子が無名PL/SQLブロックで不正に使用されていました。

このエラーは明らかです。宣言する前に変数を使用することはできません。つまり、最初に変数を宣言する必要があります。2行目と3行目を次のように切り替えました。

SQL> declare
  2    v_num number;
  3    cursor c1 is select employee_id from hr.employees where department_id = v_num;
  4  begin
  5    v_num := 110;
  6    open c1;
  7  end;
  8  /

PL/SQL procedure successfully completed.

2. 引用符で囲まれていない文字列が原因でORA-00904

PL/SQLでEXECUTE IMMEDIATEを使用するときは、文中の文字列を引用符で囲む方法を知りたいと思うかもしれません。

SQL> begin
  2    execute immediate 'select nvl(first_name, NO_VALUE) from employees';
  3  end;
  4  /
begin
*
ERROR at line 1:
ORA-00904: "NO_VALUE": invalid identifier
ORA-06512: at line 2

上記のステートメントでは、関数NVLによってすべてのNULL値をNO_VALUE文字列で置き換えますが、ステートメント内の文字列を引用符で囲むことをためらっています。その結果、ORA-00904になりました。さて、問題は、正しくするために外側の文字列で文字列を引用符で囲む方法です。

解決方法

答えは、すべての単一引用符を2つの単一引用符として複製して、特にEXECUTE IMMEDIATEの中で別のストリングにストリングを提示したい場合は、そのストリング内の単一引用符をエスケープすることです。

SQL> begin
  2    execute immediate 'select nvl(first_name, ''NO_VALUE'') from employees';
  3  end;
  4  /

PL/SQL procedure successfully completed.

今すぐコードブロックは良いです。

Leave a Reply

Your email address will not be published. Required fields are marked *