web-dev-qa-db-ja.com

Oracleで数値として文字列を選択

私はこの奇妙な行動を発見し、私はこれで私の頭を壊しています...誰かが何かアイデアを持っていますか?

Oracle 10g:2つの異なるテーブルがあり、どちらにも「[〜#〜] testcol [〜#〜]という名前のこの列がありますVarchar2(10)として、nullにできません。

このクエリをtable1で実行すると、適切な結果が得られます。

select * from table1 where TESTCOL = 1234;

特に「1234」を配置していないこと...それはタイプミスではなく、動的に生成されたクエリであり、変更しないようにします(少なくとも近い将来は変更しません)。

しかし、同じクエリをtable2で実行すると、次のエラーメッセージが表示されます。

ORA-01722: Invalid number

両方のクエリは、同じセッション、同じデータベースで実行されます。

私はその2つのテーブルをその列で結合しており、結合は問題なく動作します。唯一の問題は、その条件を使用しようとするたびに発生します。

あるテーブルと他のテーブルで何が違うのかについてのアイデアはありますか?

前もって感謝します。

9
frenetix

TESTCOLに非数値が含まれている場合、TESTCOLエントリを数値に変換するときにOracleで問題が発生する可能性があります。それは内部で何をしているので、これは:

select * from table1 where TO_NUMBER(TESTCOL) = 1234;

あなたがそう確信しているなら1234VARCHARリテラルとして表すことはできません。代わりに、数値ではなくvarchar値を比較するためにこれを試してください。

select * from table1 where TESTCOL = TO_CHAR(1234);
25
Lukas Eder

明らかなTABLE2.TESTCOLには数値ではないの値が含まれています。文字列を数値リテラルと比較すると、暗黙的な変換が生成されます。したがって、TESTCOL hichの値を数値にキャストできない場合は、ORA-1722が表示されます。

文字列を比較しているので、2つのテーブルを比較する場所には影響しません。

したがって、いくつかのオプションがあります。最も明白な答えは、TABLE2に非数値が含まれないようにデータをクリーンアップすることです。理想的には、これを列を数値データ型に変更することと組み合わせる必要があります。それ以外の場合は、ジェネレーターを変更して、不安定なデータモデルに対して実行できるコードを生成できます。この場合、マップされた列が文字データ型の場合、リテラルを引用符で囲むことを意味します。

5
APC

ここで暗黙の型キャストの危険に直面しています。

testcol = 1234は、testcolを数値列として扱いたいと述べているため、Oracleはその列のすべての値を数値に変換しようとします。

ORA-01722は、その列の少なくとも1つの値がnot数値であるために発生します。

これが「タイプミスではない」であると主張したとしても、それは確かに1つです。これは構文エラーです。

単一引用符を使用して、パラメータを文字列リテラルとして宣言する必要があります:where testcol = '1234'

正しい条件を作成することが問題の唯一の解決策です。

以下はうまくいくはずです。 「あなたの場所」を置き換えるだけです。

select * 
from table1 
where (select TO_NUMBER(TESTCOL) 
       from table2 
       where "your where") = 1234;
0