ORACLE外部接続

10182 ワード

今日の開発過程で面倒な外部接続の問題に遭遇し、最後まで良い解決方法が見つからず、最後にunion allで実現するしかなく、性能は外部接続に及ばないが、少なくとも外部接続の限界を広げた.
まず、私のテスト用の3つのテーブルとデータを提供します(左右の外部接続の道理は同じで、私は左接続だけをまとめました):
KC21 :
create table KC21
(
  AKB020 VARCHAR2(14) not null,
  AKC190 VARCHAR2(18) not null,
  AAC001 VARCHAR2(20) not null
);
INSERT INTO KC21  (AKB020, AKC190, AAC001) VALUES('110', '266', '1302012062942');
INSERT INTO KC21  (AKB020, AKC190, AAC001) VALUES('456', '369', '1302012063210');
INSERT INTO KC21  (AKB020, AKC190, AAC001) VALUES('1000', '472', '1302012045811');
INSERT INTO KC21  (AKB020, AKC190, AAC001) VALUES('123', '335', '1302012063275');
KC24 :
create table KC24
(
  AKB020 VARCHAR2(14) not null,
  AKC190 VARCHAR2(18) not null,
  AAE072 VARCHAR2(20) not null
);
insert into KC24 (AKB020, AKC190, AAE072)values ('110', '335', '2188038055');
insert into KC24 (AKB020, AKC190, AAE072)values ('11', '369', '2188038092');
insert into KC24 (AKB020, AKC190, AAE072)values ('1000', '472', '2188038197');
insert into KC24 (AKB020, AKC190, AAE072)values ('110', '339', '2188038058');
KB01 :
create table KB01
(
  AKB020 VARCHAR2(14) not null,
  AKB021 VARCHAR2(50)
);
insert into KB01 (AKB020, AKB021)values ('1000', '        ');
insert into KB01 (AKB020, AKB021)values ('110', '     A');
insert into KB01 (AKB020, AKB021)values ('123', '     B');
insert into KB01 (AKB020, AKB021)values ('456', '     C');
insert into KB01 (AKB020, AKB021)values ('11', '     D');
oracle公式では、from句でleft outer join/right outer join/full outer joinを使用し、もう1つはwhere句でよく知られている記号「(+)」を使用する2つの方法の理解を書きたいと考えています.
一、一つの接続条件を使用する外部接続:
SQL> select * from kc21 left outer join kc24 on kc21.akb020=kc24.akb020;
 
AKB020         AKC190             AAC001               AKB020         AKC190             AAE072
-------------- ------------------ -------------------- -------------- ------------------ --------------------
110            266                1302012062942        110            335                2188038055
1000           472                1302012045811        1000           472                2188038197
110            266                1302012062942        110            339                2188038058
123            335                1302012063275                                          
456            369                1302012063210                                          
 
SQL> select * from kc21 ,kc24 where kc21.akb020=kc24.akb020(+);
 
AKB020         AKC190             AAC001               AKB020         AKC190             AAE072
-------------- ------------------ -------------------- -------------- ------------------ --------------------
110            266                1302012062942        110            335                2188038055
1000           472                1302012045811        1000           472                2188038197
110            266                1302012062942        110            339                2188038058
123            335                1302012063275                                          
456            369                1302012063210 

この2つの文のクエリの結果が同じであることは容易にわかります.そのため、この2つの文法は変換できると言えますが、最初の書き方が理解しやすいのは明らかです.これもoracleの公式提案です.公式文書は、Oracle recommends that you use the FROM clause OUTER JOIN syntax rather than the Oracle join operatorと述べています.
KC 21中のakb 020はKC 24中と等しいものが110と1000であり、KC 24中には2つのakb 020が110の記録があるため、結果として3つの接続上のものが生成され、残りの2つに一致していないものが表示され、KC 24の項目に対応してNULLで充填されることも左外接続が実現される目的である.
二、二つの接続条件を使用する場合:
SQL> select * from kc21 left outer join kc24 on (KC21.akb020=kc24.akb020 and KC21.akc190=KC24.akc190);
 
AKB020         AKC190             AAC001               AKB020         AKC190             AAE072
-------------- ------------------ -------------------- -------------- ------------------ --------------------
1000           472                1302012045811        1000           472                2188038197
110            266                1302012062942                                          
123            335                1302012063275                                          
456            369                1302012063210                                          
 
SQL> select * from kc21,kc24 where kc21.akb020=kc24.akb020(+) and kc21.akc190=KC24.akc190(+);
 
AKB020         AKC190             AAC001               AKB020         AKC190             AAE072
-------------- ------------------ -------------------- -------------- ------------------ --------------------
1000           472                1302012045811        1000           472                2188038197
110            266                1302012062942                                          
456            369                1302012063210                                          
123            335                1302012063275

この2つの文のクエリの結果も同じであり、この2つの文は等価であることがわかります.AKB 020とakc 190が同時に等しい場合にのみ一致するという意味です.同じように明らかに最初の文が理解しやすい.2番目の文を直接与える場合、最終的にどのような結果になるか想像しにくいことがあります.ここではOracle政府がなぜこのように書くのか理由を示しています.If A and B are joined by multiple join conditions,then you must use the(+)operator in all of these conditions.
3、3つのテーブルのうち、2つのテーブルには外部接続関係があり、もう1つのテーブルには外部接続関係がありません.oracleでは、SQL文の1つのテーブルに2つのテーブルを外部接続できません.
SQL> SELECT A.akb020, A.AKC190, B.akb020, B.akc190, C.akb021
  2    FROM kc21 A, kc24 B, kb01 C
  3   WHERE A.akb020 = B.akb020(+)
  4     AND A.akc190 = B.akc190(+)
  5     AND A.akb020 = C.akb020;
 
AKB020         AKC190             AKB020         AKC190             AKB021
-------------- ------------------ -------------- ------------------ --------------------------------------------------
1000           472                1000           472                        
110            266                                                       A
123            335                                                       B
456            369                                                       C
これは、第2のステップに基づいて第3のテーブルに関連して病院のコードを病院名に変換したようなものであることがわかり、このような結果が得られたのは理解できる.
4、2つの接続テーブルのうち、接続条件は2つあり、1つは外部接続、1つは内部接続です.そうすると、どのような結果になりますか.
SQL> select * from kc21,kc24 where kc21.akb020=kc24.akb020(+);
 
AKB020         AKC190             AAC001               AKB020         AKC190             AAE072
-------------- ------------------ -------------------- -------------- ------------------ --------------------
110            266                1302012062942        110            335                2188038055
1000           472                1302012045811        1000           472                2188038197
110            266                1302012062942        110            339                2188038058
123            335                1302012063275                                          
456            369                1302012063210                                          
 
SQL> select * from kc21,kc24 where kc21.akc190=kc24.akc190;
 
AKB020         AKC190             AAC001               AKB020         AKC190             AAE072
-------------- ------------------ -------------------- -------------- ------------------ --------------------
123            335                1302012063275        110            335                2188038055
456            369                1302012063210        11             369                2188038092
1000           472                1302012045811        1000           472                2188038197
 
SQL> select * from kc21,kc24 where kc21.akb020=kc24.akb020(+) and  kc21.akc190=kc24.akc190;
 
AKB020         AKC190             AAC001               AKB020         AKC190             AAE072
-------------- ------------------ -------------------- -------------- ------------------ --------------------
1000           472                1302012045811        1000           472                2188038197
 
SQL> select * from kc21,kc24 where kc21.akb020=kc24.akb020 and  kc21.akc190=kc24.akc190;
 
AKB020         AKC190             AAC001               AKB020         AKC190             AAE072
-------------- ------------------ -------------------- -------------- ------------------ --------------------
1000           472                1302012045811        1000           472                2188038197
上のいくつかのSQL文は1つと2つ目を使って、私たちは自然に3つ目を得ることができて、これも常識に合っていて、3つ目の結果セットはちょうど1つ目と2つ目の交差です.3番目と4番目のSQL文の効果は同じです.複数の接続条件を持つ2つのテーブルが接続時に「(+)」と書かれていない場合、oracleは単純な等値内で接続されているとみなされます.これもoracleの公式声明です.If Aand B are joined by multiple join conditions,then you must use the(+)operator in all of these conditions.If you do not, then Oracle Database will return only the rows resulting from a simple join, but without a warning or error to advise you that you do not have the results of an outer join.
五、全外接続oracleは全接続に対して接続条件の左右に「(+)」をつけることをサポートしていない.from句にfull outer joinを使用し、on句に接続条件を加える方法は一つしかない.
SQL> select * from kc21 full outer join kc24 on (kc21.akb020=KC24.akb020);
 
AKB020         AKC190             AAC001               AKB020         AKC190             AAE072
-------------- ------------------ -------------------- -------------- ------------------ --------------------
110            266                1302012062942        110            335                2188038055
1000           472                1302012045811        1000           472                2188038197
110            266                1302012062942        110            339                2188038058
123            335                1302012063275                                          
456            369                1302012063210                                          
                                                       11             369                2188038092
 
6 rows selected
この結果はよく理解され、一致条件を満たすものは成功記録として返され、他のテーブルに対応するフィールドを満たさないものはNULLで満たされる.
六、終わり!