Mengapa?
PL/pgSQL mengeksekusi kueri SQL seperti pernyataan yang disiapkan . Panduan tentang penggantian parameter:
Perhatikan istilah nilai . Hanya nilai aktual yang dapat diparameterisasi, tetapi bukan kata kunci, pengidentifikasi, atau nama jenis. 32
dalam bit(32)
penampilan seperti nilai, tetapi pengubah tipe data hanya "nilai" secara internal dan tidak dapat diparameterisasi. SQL menuntut untuk mengetahui tipe data pada tahap perencanaan, tidak bisa menunggu tahap eksekusi.
Anda bisa mencapai tujuan Anda dengan SQL dinamis dan EXECUTE
. Sebagai bukti konsep :
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;
Telepon:
SELECT lpad_bits(b'1001100111000', 32);
Perhatikan perbedaan antara sz
digunakan sebagai harfiah untuk membuat pernyataan dan kemunculan keduanya yang digunakan sebagai nilai , yang dapat diteruskan sebagai parameter.
Alternatif yang lebih cepat
Solusi terbaik untuk tugas khusus ini adalah dengan menggunakan lpad()
seperti @Abelisto menyarankan
:
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;
(Lebih sederhana seperti fungsi SQL biasa, yang juga memungkinkan fungsi inlining dalam konteks kueri luar.)
Beberapa kali lebih cepat dari fungsi di atas. Cacat kecil:kita harus menggunakan text
dan kembali ke varbit
. Sayangnya, lpad()
saat ini tidak diimplementasikan untuk varbit
. Manual:
overlay()
tersedia, kami dapat memiliki fungsi yang lebih murah:
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;
Lebih cepat jika Anda dapat bekerja dengan varbit
nilai-nilai untuk memulai. (Keuntungannya adalah (sebagian) batal, jika Anda harus melemparkan text
ke varbit
pokoknya.)
Telepon:
SELECT lpad_bits3(b'1001100111000', '00000000000000000000000000000000');
SELECT lpad_bits3(b'1001100111000', repeat('0', 32)::varbit);
Kami mungkin overlaod fungsi dengan varian yang mengambil bilangan bulat untuk menghasilkan base
sendiri:
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;
Telepon:
SELECT lpad_bits3(b'1001100111000', 32;
Terkait:
- Postgresql Mengonversi bit yang bervariasi ke integer
- Konversikan hex dalam representasi teks ke angka desimal