Tại sao?
PL / pgSQL thực thi các truy vấn SQL như câu lệnh chuẩn bị . Hướng dẫn về thay thế tham số:
Lưu ý thuật ngữ giá trị . Chỉ các giá trị thực tế mới có thể được tham số hóa, nhưng không được tham số hóa các từ khóa, số nhận dạng hoặc tên kiểu. 32
trong bit(32)
ngoại hình giống như một giá trị, nhưng công cụ sửa đổi của một kiểu dữ liệu chỉ là một "giá trị" bên trong và không thể được tham số hóa. SQL yêu cầu biết các kiểu dữ liệu ở giai đoạn lập kế hoạch, nó không thể đợi giai đoạn thực thi.
Bạn có thể đạt được mục tiêu của bạn với SQL động và EXECUTE
. Như bằng chứng về khái niệm :
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;
Gọi:
SELECT lpad_bits(b'1001100111000', 32);
Lưu ý sự khác biệt giữa sz
được sử dụng dưới dạng chữ để xây dựng câu lệnh và lần xuất hiện thứ hai nơi nó được sử dụng làm giá trị , có thể được chuyển dưới dạng tham số.
Các lựa chọn thay thế nhanh hơn
Giải pháp ưu việt cho tác vụ cụ thể này là chỉ sử dụng lpad()
như @Abelisto đề xuất
:
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;
(Đơn giản hơn như hàm SQL thuần túy, cũng cho phép hàm nội tuyến trong ngữ cảnh của các truy vấn bên ngoài.)
Nhanh hơn vài lần so với chức năng trên. Một lỗ hổng nhỏ:chúng tôi phải truyền sang text
và quay lại varbit
. Rất tiếc, lpad()
hiện không được triển khai cho varbit
. Hướng dẫn:
overlay()
có sẵn, chúng tôi có thể có một chức năng rẻ hơn:
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;
Nhanh hơn nếu bạn có thể làm việc với varbit
giá trị bắt đầu. (Ưu điểm là (một phần) bị vô hiệu, nếu bạn phải truyền text
tới varbit
dù sao.)
Gọi:
SELECT lpad_bits3(b'1001100111000', '00000000000000000000000000000000');
SELECT lpad_bits3(b'1001100111000', repeat('0', 32)::varbit);
Chúng tôi có thể chồng lên nhau hàm có một biến thể lấy một số nguyên để tạo base
chính nó:
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;
Gọi:
SELECT lpad_bits3(b'1001100111000', 32;
Có liên quan:
- Postgresql Chuyển đổi bit thay đổi thành số nguyên
- Chuyển đổi hex trong biểu diễn văn bản thành số thập phân