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

複数の列のSELECTとINSERT間の競合状態

    作品のレンチはSELECT f_insert_tag(tag_p_id, _tag)です。

    の代わりに

    SELECT * FROM f_insert_tag(tag_p_id, _tag)

    Postgres9.4の場合

    CREATE FUNCTION f_insert_tag(_tag_id int, _tag text, OUT _tag_id_ int, OUT _tag_ text) 
    AS
    $func$
     BEGIN
       INSERT INTO t(tag_id, tag)
       VALUES (_tag_id, _tag)
       RETURNING t.tag_id, t.tag
       INTO  _tag_id_, _tag_;
    
       EXCEPTION WHEN UNIQUE_VIOLATION THEN
          -- catch exception, return NULL
     END
    $func$  LANGUAGE plpgsql;
    
    
    CREATE FUNCTION f_tag_id(_tag_id int, _tag text, OUT _tag_id_ int, OUT _tag_ text) AS
    $func$
    BEGIN
    LOOP
       SELECT t.tag_id, t.tag
       FROM   t
       WHERE  t.tag = _tag
    
       UNION ALL
       SELECT *                                              -- !!!
       FROM   f_insert_tag(_tag_id, _tag)
       LIMIT  1
    
       INTO _tag_id_, _tag_;
    
       EXIT WHEN _tag_id_ IS NOT NULL;  -- else keep looping
    END LOOP;
    END
    $func$ LANGUAGE plpgsql;
    

    db <> fiddle こちら

    Postgres 9.5以降の場合:

    CREATE FUNCTION f_tag_id(_tag_id int, _tag text, OUT _tag_id_ int, OUT _tag_ text) AS
    $func$
    BEGIN
    LOOP
       SELECT t.tag_id, t.tag
       FROM   t
       WHERE  t.tag = _tag
       INTO   _tag_id_, _tag_;
    
       EXIT WHEN FOUND;
    
       INSERT INTO t (tag_id, tag)
       VALUES (_tag_id, _tag)
       ON     CONFLICT (tag) DO NOTHING
       RETURNING t.tag_id, t.tag
       INTO   _tag_id_, _tag_;
    
       EXIT WHEN FOUND;
    END LOOP;
    END
    $func$  LANGUAGE plpgsql;
    

    db <> fiddle こちら

    ここでの基本:




    1. クエリを使用して、指定された2つの日付の間の月のリストを取得するにはどうすればよいですか?

    2. 実数vs.浮動小数点vs.お金

    3. Postgresクエリウィンドウのパラメータを使用してアドホックSQLをテストする方法

    4. ダンプファイルでpg_restoreを使用する