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

Postgres関数は作成されますが、実行されません

    私も同様の状況にありました-幅広いパラメータリストを持つ関数。いわゆる名前付きパラメータ 、パラメータの順序を尊重する必要はありません。コードは長くなりますが、(私は)より読みやすく、より堅牢になることを願っています。

    CREATE TABLE tab(name text, surname text, address text, city text, zip text);
    
    CREATE OR REPLACE FUNCTION public.fx(name text, surname text,
                                         address text, city text, zip text)
    RETURNS void
    LANGUAGE plpgsql
    AS $function$
    BEGIN
      INSERT INTO tab(name, surname, address, city, zip)
        VALUES(fx.name, fx.surname, fx.address, fx.city, fx.zip);
      -- ... some other logic
    END;
    $function$
    

    この関数は、名前付きパラメータを使用して呼び出すことができます。 表記:

    SELECT fx(name := 'Pavel', surname := 'Stehule',
              address := 'Skalice 12', city := 'Benesov', zip := '12');
    

    重要:間違ったタイプを使用すると-Postgresはメッセージを報告します:

    postgres=#   SELECT fx(name := 'Pavel', surname := 'Stehule',
                  address := 'Skalice 12', city := 'Benesov', zip := 12);
    ERROR:  function fx(name := unknown, surname := unknown, address := unknown, city := unknown, zip := integer) does not exist
    LINE 1: SELECT fx(name := 'Pavel', surname := 'Stehule',
                   ^
    HINT:  No function matches the given name and argument types. You might need to add explicit type casts.
    

    メッセージは有効ですが、クリーンではありません。これは、関数のオーバーロードサポートのコストです。他にも、長いパラメータリストを分割する方法、およびこれらの問題をより快適に見つける方法などのトリックがあります。

    Postgresはカスタムタイプをサポートしています。あなたはそれを使うことができます:

    CREATE TYPE person_type AS (name text, surname text);
    CREATE TYPE address_type AS (address text, city text, zip text);
    

    コンストラクター関数を書くことができます:

    CREATE OR REPLACE FUNCTION public._person_type(name text, surname text)
    RETURNS person_type
    LANGUAGE plpgsql
    AS $function$
    DECLARE r person_type;
    BEGIN
      r.name = name;
      r.surname = surname;
      RETURN r;
    END;
    $function$
    
    CREATE OR REPLACE FUNCTION public._address_type(address text, city text, zip text)
    RETURNS address_type
    LANGUAGE plpgsql
    AS $function$ DECLARE r address_type;
    BEGIN
      r.address = address;
      r.city = city;
      r.zip = zip;
      RETURN r;
    END;
    $function$
    

    このシステムの作成にはいくつかの作業が必要であり、長寿命のシステムでのみ実用的です。一方で、将来のメンテナンス作業のコストを削減します。

    CREATE OR REPLACE FUNCTION public.fx(p person_type, a address_type)
    RETURNS void
    LANGUAGE plpgsql
    AS $function$
    BEGIN
      INSERT INTO tab(name, surname, address, city, zip)
        VALUES(p.name, p.surname, a.address, a.city, a.zip);
       -- ... some other logic
    END;
    $function$
    

    現在、より多くの表記法(表記法の組み合わせ)が可能です:

    postgres=# SELECT fx(_person_type('Pavel','Stehule'),
    postgres(#           _address_type('Skalice 12','Benesov', '25601'));
     fx 
    ----
    
    (1 row)
    

    コンストラクターはエラーのローカリゼーションに役立ちます:

    postgres=# SELECT fx(_person_type('Pavel','Stehule'),
              _address_type('Skalice 12','Benesov', 25601));
    ERROR:  function _address_type(unknown, unknown, integer) does not exist
    LINE 2:           _address_type('Skalice 12','Benesov', 25601));
                      ^
    HINT:  No function matches the given name and argument types. You might need to add explicit type casts.
    


    1. MariaDB CONNECTION_ID()の説明

    2. 1つのクエリで別のテーブルから取得したテーブルのリストをUNIONするにはどうすればよいですか?

    3. PHP彗星usleepがapachempmをブロックしていますか?

    4. カンマ区切りの文字列を分割->FUNCTIONdb.CHARINDEXが存在しません