PostgreSQL
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> PostgreSQL

Hiểu sự khác biệt giữa tham số int và tham số int trong hàm PL / pgSQL

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:



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Làm cách nào để sao chép dữ liệu từ bảng này sang bảng khác trong postgres bằng lệnh copy

  2. Làm thế nào để cung cấp một mật khẩu cho không tương tác được tạo của PostgreSQL?

  3. Perl - DBI và .pgpass

  4. connect.select_value chỉ trả về các chuỗi trong postgres với pg gem

  5. Coalesces jsonArrayAgg thành mảng trống trong jOOQ