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

行が存在する場合はIDを返し、存在しない場合はINSERTを返します

    単一のSQLステートメントのソリューション。 PostgreSQLが必要8.4 またはそれ以降。
    次のデモを検討してください:

    テストセットアップ:

    CREATE TEMP TABLE tbl (
      id  serial PRIMARY KEY
     ,txt text   UNIQUE   -- obviously there is unique column (or set of columns)
    );
    
    INSERT INTO tbl(txt) VALUES ('one'), ('two');
    

    INSERT / SELECTコマンド:

    WITH v AS (SELECT 'three'::text AS txt)
        ,s AS (SELECT id FROM tbl JOIN v USING (txt))
        ,i AS (
           INSERT INTO tbl (txt)
           SELECT txt
           FROM   v
           WHERE  NOT EXISTS (SELECT * FROM s)
           RETURNING id
           )
    SELECT id, 'i'::text AS src FROM i
    UNION  ALL
    SELECT id, 's' FROM s;
    
    • 最初のCTEv 厳密には必要ではありませんが、を入力する必要があります 一度だけ。

    • 2番目のCTEが選択 id tblから 「行」が存在する場合。

    • 3番目のCTEi挿入 tblへの「行」 存在しない場合(そして存在する場合のみ)、idを返します 。

    • 最後のSELECT idを返します 。 src列を追加しました 「ソース」を示します-「行」が既存であり、idであるかどうか SELECTからのものであるか、「行」が新しく、idも新しい 。

    • このバージョンは、tblからの追加のSELECTを必要としないため、可能な限り高速である必要があります。 代わりにCTEを使用します。

    マルチユーザー環境で発生する可能性のある競合状態に対してこれを安全にするには:
    また、Postgresの新しいUPSERTを使用した最新の技術 9.5 以降:

    • 関数内のSELECTまたはINSERTは競合状態になりやすいですか?


    1. Oracleで文字列から日付を取得する方法

    2. データベースの行数が多すぎますか?

    3. SQL Serverインデックスの後方スキャン:理解、調整

    4. SQL Server(T-SQL)で数値をパーセンテージに変換する4つの方法