12

次の表の説明を前提とします。

emp : 

ename varchar2(25)


dept:

loc varchar2(25)

次の3つのケースがあります。

select ename,to_number(null) from emp
union
select to_char(null),loc from dept;

  select ename,to_number(null) from emp
    union
    select to_number(null),loc from dept;

  select ename,null from emp
    union
    select null,loc from dept;

ケース 1 は完全に実行されます。

ケース 2 は実行に失敗します。

ケース 3 も完全に実行されます。

私の理解では、ユニオンに対応する列がない場合は、同等のデータ型のダミーを作成する必要があることを確認する必要があります。したがって、他のテーブルの対応する列リストのnumberようなものを持つタイプ。to_number(null)

ケース 3 では、すべて null を指定しているため、シナリオはある程度理解できます。locただし、ケース 1 では、との間にデータ型の互換性はありませんto_numberが、実行されます。一方、ケース 2 は失敗します。どうか明らかにしてください。

4

1 に答える 1

8

この答えは少しとりとめのないかもしれません...

オラクルは、セット操作に非常にうるさいです。すべての列は、2 番目、3 番目などのクエリの対応する列と同じデータ型である必要があります。

Oracleはを実行するに数値として評価しますが、実行に「null-ness」を評価するため、2番目のクエリは失敗すると思います。最初の値が「null-ness」について評価され、次に が発生するため、最初のクエリは成功します。これは、評価の順序が次のとおりであることを意味します。to_number()unionunion

  1. 第1選択機能
  2. 最初に選択するデータ型
  3. セカンドセレクト機能
  4. 連合
  5. 2 番目に選択するデータ型

これを段階的に証明しようとしますが、絶対的な証明になるかどうかはわかりません.

次の両方のクエリ

select 1 from dual union select '1' from dual;
select '1' from dual union select 1 from dual;

暗黙的な変換が行われないため、次のエラーで失敗します。

ORA-01790: 式は、対応する式と同じデータ型である必要があります

ただし、次の両方が成功します

select null from dual union select '1' from dual;
select null from dual union select 1 from dual;

これら 2 つのクエリのいずれかを選択するdumpと、次のものが返されます。

SQL> select dump(a)
  2    from ( select null a from dual union select '1' from dual );

DUMP(A)
-------------------------------------------------------------------

Typ=96 Len=1: 49
NULL

SQL> select dump(a)
  2    from ( select null a from dual union select 1 from dual );

DUMP(A)
-------------------------------------------------------------------

Typ=2 Len=2: 193,2
NULL

ご覧のとおり、列には異なるデータ型があります。文字を使用した最初のクエリは acharを返し、2 番目のクエリは数値を返しますが、順序が逆になり、2 番目selectが最初になります。

最後に、dump最初のクエリを見ると

SQL> select substr(dump(ename),1,35) a, substr(dump(loc),1,35) b
  2    from ( select ename,to_number(null) as loc from emp
  3            union
  4           select to_char(null),loc from dept
  5                  );

A                                   B
----------------------------------- -----------------------------------
Typ=1 Len=6: 104,97,104,97,104,97   NULL
NULL                                Typ=1 Len=6: 104,97,104,97,104,97

SQL>

dump(to_number(null))nullであることがわかります。ただし、これは列のデータ型であるため、 avarchar2ではなく aが返されます。char返されるステートメントの順序が逆になっておらず、このクエリをテーブルとして作成すると、両方の列がvarchar2.

選択クエリで列のデータ型を決定するとき、Oracle は最初の既知のデータ型を取得し、それを使用して全体のデータ型を計算します。selectこれが、最初のクエリが null だったクエリの行が逆になった理由です。

最初の select はselect ename,to_number(null) from emp、結果セットがどのようになるかを「説明」するため、最初のクエリは成功します。|varchar2|null|. 次に、2 番目のクエリで が追加されますが|varchar2|varchar2|、これにより問題は発生しません。

select ename,to_number(null) from emp最初の選択で結果セットが として「説明」されるため、2 番目のクエリは失敗しますvarchar2, null。ただし、null 番号と varchar2 を に追加しようとしますunion

ここで信じられないのは、オラクルはそれがto_number(null)の数値であると判断し、後まで「null-ness」を評価しないということです。列を使用してオブジェクトを作成することはできず、それを選択することもできないため、これが実際に発生しているかどうかをテストする方法がよくわかりません。unionnull

オラクルが許可していないことを証明することはできないので、経験的な証拠を探します。次のクエリの結果 (またはエラー) を検討してください。

SQL> select 1 as a from dual union select to_number(null) from dual;

         A
----------
         1


SQL> select '1' as a from dual union select to_number(null) from dual;
select '1' as a from dual union select to_number(null) from dual
       *
ERROR at line 1:
ORA-01790: expression must have same datatype as corresponding expression


SQL> select 1 as a from dual union select to_char(null) from dual;
select 1 as a from dual union select to_char(null) from dual
       *
ERROR at line 1:
ORA-01790: expression must have same datatype as corresponding expression


SQL> select '1' as a from dual union select to_char(null) from dual;

A
-
1

それらは、 null で実行されるかどうかに関係なく、「null-ness」の評価の前に、データ型を暗黙的に定義し、それが a で適切かどうかを評価することを実証しているように見えto_charます。to_numberunion

この説明は、null であるに数値であるため、coalesce問題もカバーします。to_number(null)

于 2012-08-21T17:03:31.457 に答える