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

PL/pgSQL関数のintリテラルとintパラメータの違いを理解する

    なぜですか?

    PL / pgSQLは、プリペアドステートメントのようなSQLクエリを実行します。 パラメーター置換に関するマニュアル:

    という用語に注意してください 。パラメータ化できるのは実際の値のみであり、キーワード、識別子、またはタイプ名はパラメータ化できません。 32 bit(32)見た目 値と同様ですが、データ型の修飾子は内部的には「値」にすぎず、パラメーター化することはできません。 SQLは、計画段階でデータ型を知る必要があり、実行段階を待つことはできません。

    あなたはできた 動的SQLとEXECUTEで目標を達成する 。 概念実証として :

    CREATE OR REPLACE FUNCTION lpad_bits(val varbit, sz int = 32, OUT outval varbit) AS
    $func$
    BEGIN
       EXECUTE format('SELECT $1::bit(%s) >> $2', sz)  -- literal
       USING val, sz - length(val)                     -- values
       INTO outval;
    END
    $func$  LANGUAGE plpgsql IMMUTABLE;
    

    電話:

    SELECT lpad_bits(b'1001100111000', 32);  
    

    szの違いに注意してください 文字として使用されている ステートメントと、それがとして使用される2番目のオカレンスを作成します 、パラメータとして渡すことができます。

    より高速な代替案

    この特定のタスクの優れた解決策は、 lpad()を使用することです。 @Abelistoが提案しました

    CREATE OR REPLACE FUNCTION lpad_bits2(val varbit, sz int = 32)
      RETURNS varbit AS
    $func$
    SELECT lpad(val::text, sz, '0')::varbit;
    $func$  LANGUAGE sql IMMUTABLE;
    

    (単純なSQL関数としてより単純で、関数のインライン化も可能です。 外部クエリのコンテキストで。)

    上記の関数の数倍高速です。マイナーな欠陥:textにキャストする必要があります varbitに戻ります 。残念ながら、lpad() 現在、varbitには実装されていません 。 マニュアル:

    overlay() が利用可能である場合、より安価な機能を使用できます:

    CREATE OR REPLACE FUNCTION lpad_bits3(val varbit, base varbit = '00000000000000000000000000000000')
      RETURNS varbit AS
    $func$
    SELECT overlay(base PLACING val FROM bit_length(base) - bit_length(val))
    $func$  LANGUAGE sql IMMUTABLE;
    

    varbitを使用できる場合は、より高速になります そもそも値。 (textをキャストする必要がある場合、利点は(部分的に)無効になります varbitへ とにかく。)

    電話:

    SELECT lpad_bits3(b'1001100111000', '00000000000000000000000000000000');
    SELECT lpad_bits3(b'1001100111000',  repeat('0', 32)::varbit);
    

    上書きする可能性があります baseを生成するために整数をとるバリアントを持つ関数 それ自体:

    CREATE OR REPLACE FUNCTION lpad_bits3(val varbit, sz int = 32)
      RETURNS varbit AS
    $func$
    SELECT overlay(repeat('0', sz)::varbit PLACING val FROM sz - bit_length(val))
    $func$  LANGUAGE sql IMMUTABLE;
    

    電話:

    SELECT lpad_bits3(b'1001100111000', 32;
    

    関連:



    1. PostgresSQL集計クエリのパフォーマンスを向上させる

    2. テーブルの名前付けのジレンマ:単数形と複数形

    3. SQLのNull、Zero、Blankの違いは何ですか?

    4. MySQLは、いくつあるかに関係なく、すべての子をカウントします