なぜですか?
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;
関連: