sql >> データベース >  >> RDS >> Oracle

Oracle VARCHAR列の数値比較はどのように機能しますか?

    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リファレンスを探していました。最初に見たもの 便利なことに、「述語の順序の変更」の効果と、「varchar2に数値を格納しない」という意味があります。



    1. as3、MySQLPHP接続

    2. 2回以上注文したすべての顧客IDと姓を一覧表示します

    3. 異なる列のタイム スタンプの違いに基づいて Oracle DB ビューを作成する

    4. not条件に基づいて2つのテーブルの結果を結合する方法