SQL言語リファレンス に記載されているとおり :
タイプが一致しない場合、テーブル列に対して暗黙的な変換が実行されます。これは、いくつかのダミーデータを使用してSQL*Plusでトレースすることで確認できます。
create table t42 (foo varchar2(3 byte));
insert into t42 (foo) values ('10');
insert into t42 (foo) values ('2A');
set autotrace on explain
これは機能します:
select * from t42 where foo = '10';
FOO
---
10
Execution Plan
----------------------------------------------------------
Plan hash value: 3843907281
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 3 | 3 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| T42 | 1 | 3 | 3 (0)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("FOO"='10')
Note
-----
- dynamic sampling used for this statement (level=2)
しかし、このエラー:
select * from t42 where foo = 10;
ERROR:
ORA-01722: invalid number
Execution Plan
----------------------------------------------------------
Plan hash value: 3843907281
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 3 | 3 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| T42 | 1 | 3 | 3 (0)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(TO_NUMBER("FOO")=10)
フィルタの違いに注意してください。 filter("FOO"='10')
対filter(TO_NUMBER("FOO")=10)
。後者の場合、数値と比較して、to_number()
テーブル内のすべての行に対して実行され、その変換の結果が固定値と比較されます。したがって、いずれかの文字値を変換できない場合は、ORA-01722を取得します。適用されている関数は、インデックスがその列に存在する場合、そのインデックスの使用も停止します。
興味深いのは、複数のフィルターがある場合です。 Oracleは、異なる時間に異なる順序でそれらを評価する場合があるため、ORA-01722が常に表示されるとは限らず、ポップアップする場合があります。 where foo = 10 and bar = 'X'
があるとします。 。 OracleがX
以外を除外できると考えた場合 最初に値を指定すると、to_number()
のみが適用されます。 残っているものに、そしてその小さなサンプルはfoo
に数値以外の値を持たないかもしれません 。ただし、and bar = 'Y'
がある場合 、非Y
値には、数値以外、またはが含まれる場合があります Oracleはfoo
でフィルタリングする場合があります 最初 、値がどの程度選択的であるかによって異なります。
道徳は、数値情報を文字タイプとして決して保存しないことです。
私は道徳をバックアップするためのAskTomリファレンスを探していました。