Защо?
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
се използва като буквал за изграждане на израза и второто му срещане, когато се използва като стойност , който може да бъде предаден като параметър.
По-бързи алтернативи
Превъзходно решение за тази конкретна задача е просто да използвате 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;
Свързани:
- Postgresql Преобразуване на бит, вариращ в цяло число
- Преобразуване на шестнадесетичен в текстово представяне до десетично число