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

OracleからPostgreSQLへ:PostgreSQLのANSI外部結合構文

    Oracle移行シリーズの3番目の記事をご覧ください。今回は、Oracle(+)のWHERE句の基準を変更する奇妙な演算子を見ていきます。他のすべてと同様に、PostgreSQLにはそのためのソリューションがあります。

    右結合

    Oracleは、修飾句の演算子を使用したANSI外部JOIN構文をサポートしており、多くの開発者が使用しています。

    通常、これは次のようになります。

    SELECT *
    FROM person, places
    WHERE person.id = places.person_id(+)

    この構文の目的は、右外部結合です。集合論の用語では、これは人に関係なく、すべての場所を含むサブセットです。

    小さなサンプルの結果は次のようになります:

    id last_name first_name id 場所 person_id
    1 (NULL) (NULL) 1 ダラス (NULL)
    2 ロイヤル カーク 2 ロンドン 2
    3 リグ サイモン 3 パリ 3

    この構文はPostgreSQLではサポートされていません。

    同じ結果を得るには、外部結合に標準のSQL構文を使用します。

    SELECT *
    FROM persons
    RIGHT JOIN places
    ON persons.id = places.person_id;

    SQLは、明確な副詞OUTERも提供します 。 RIGHT JOINと同様に、このクラリファイアは完全にオプションです。 定義上、OUTER 参加します。

    フルジョイン

    同様に、完全結合にOracle構文を使用しても、PostgreSQLでは機能しません。

    SELECT *
    FROM persons, places
    WHERE persons.id(+) = places(+);

    この構文の目的は、人が場所に関連付けられているかどうかに関係なく、人と場所の完全なリストです。

    結果は次のようになります:

    id last_name first_name ** id 場所 person_id
    1 (NULL) (NULL) 1 ダラス (NULL)
    2 ロイヤル カーク 2 ロンドン 2
    3 リグ サイモン 3 パリ 3
    4 アンドリュー ダンスタン (NULL) (NULL) (NULL)

    PostgreSQL構文を使用すると、クエリは次のように記述されます。

    SELECT *
    FROM persons
    FULL JOIN places
    ON persons.id = places.person_id;

    繰り返しますが、OUTER キーワードは完全にオプションです。

    CROSS JOIN

    暗黙の関係ではなくキーワードを使用するアプローチの明確な利点の1つは、誤って外積を作成できないことです。

    構文:

    SELECT *
    FROM persons
    LEFT JOIN places;

    エラーが発生します:

    ERROR:  syntax error at or near ";"

    行末マーカー「;」でステートメントが完了していないことを示します。

    PostgreSQLは、ANSI構文を使用して相互結合製品を作成します。

    SELECT *
    FROM persons, places;
    id last_name first_name id 場所 person_id
    1 ダンスタン アンドリュー 1 ダラス (null)
    1 ダンスタン アンドリュー 2 ロンドン 2
    1 ダンスタン アンドリュー 3 パリ 3
    1 ダンスタン アンドリュー 4 マドリード (null)
    2 ロイヤル カーク 1 ダラス (null)
    2 ロイヤル カーク 2 ロンドン 2
    2 ロイヤル カーク 3 パリ 3
    2 ロイヤル カーク 4 マドリード (null)
    3 リグ サイモン 1 ダラス (null)
    3 リグ サイモン 2 ロンドン 2
    3 リグ サイモン 3 パリ 3
    3 リグ サイモン 4 マドリード (null)
    6 ウォン マーク 1 ダラス (null)
    6 ウォン マーク 2 ロンドン 2
    6 ウォン マーク 3 パリ 3
    6 ウォン マーク 4 マドリード (null)

    これは、意図的な結果よりもコーディングエラーである可能性が高いです。

    この機能を意図的に取得するには、CROSS JOINを使用することをお勧めします。 ステートメント。

    SELECT *
    FROM persons
    CROSS JOIN places;

    したがって、ステートメントの意味が明確になります。

    NATURAL JOIN

    PostgreSQLはNATURAL JOINをサポートしています 構文ですが、少し抗議しています。

    SELECT *
    FROM persons
    NATURAL JOIN places;

    これにより、次の結果が生成されます。

    id last_name first_name parent_id 場所 person_id
    1 ダンスタン アンドリュー (null) ダラス (null)
    2 ロイヤル カーク 1 ロンドン 2
    3 リグ サイモン 1 パリ 3

    ただし、この構文には問題があります。この例では、両方のテーブルの「id」列は互いに関係がありません 。この結合は結果を生み出しましたが、完全に無関係なコンテンツを含んでいます。

    さらに、最初は正しい結果を表示するクエリがあるかもしれませんが、後続のDDLステートメントはサイレントに影響します。

    検討してください:

    ALTER TABLE person ADD COLUMN places_id bigint;
    ALTER TABLE places ADD COLUMN places_id bigint;
    ALTER TABLE person ADD COLUMN person_id bigint;

    ここで、NATURAL JOINはどの列ですか 使用していますか?選択肢は、id、places_id、person_id、および上記のすべてです。答えは読者の練習問題として残しておきます。

    この構文は、コードにとって時限爆弾です。使用しないでください。

    わかりました、それであなたは確信していません。それなら、少なくともいくつかの正しいコーディング規則があります。親テーブルの場合、ID列に「myparenttable_id」という名前を付けます。子関係から参照する場合は、同じ名前「myparenttable_id」を使用してください。 「id」という名前を付けたり、別の名前の列を参照したりしないでください。ああ、忘れて。これはしないでください。

    USINGを使用して、前のパズルの曖昧さを解消したくなるかもしれません。 キーワード。これは次のようになります:

    SELECT *
    FROM persons
    JOIN places
    USING (id);

    しかし、USING キーワードは、テーブル間での完全な名前の一致のみを利用できます。繰り返しになりますが、この例ではまったく間違っています。

    PostgreSQLのベストプラクティスの選択は、規約標準をコーディングしてテーブルを設計することを単に避けることです。

    概要

    これらのキーワード手法(対演算子)は、Oracleでも利用できます。それらはよりクロスプラットフォームであり、曖昧さが少なくなっています。それだけでベストプラクティスになります。

    それに加えて、不適切に使用すると論理エラーが発生します。 PostgreSQLでの開発では、一方的に明示的なキーワードを使用することをお勧めします。


    1. IDに基づいて値を連結します

    2. OracleからPostgreSQLへ:移行する理由

    3. varbinaryを文字列に変換するSQLServer

    4. PostgreSQLがタイムゾーンのないタイムスタンプからタイムゾーンのあるタイムスタンプに誤って変換する