PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

Memahami perbedaan antara parameter int literal vs int dalam fungsi PL/pgSQL

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:



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Nilai Default dalam kolom saat menyisipkan baris baru

  2. SQLAlchemy mengatur keanggotaan untuk set yang sangat besar

  3. Operator Bitwise PostgreSQL dengan variasi bit tidak dapat DAN string bit dengan ukuran berbeda

  4. Bagaimana mengembalikan jumlah kolom dinamis dalam fungsi?

  5. Permintaan Postgres yang kompleks