PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Разбиране на разликата между int литерал и int параметър във функцията PL/pgSQL

Защо?

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;

Свързани:



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Защо psycopg2 INSERT отнема толкова време, за да работи в цикъл и как да го ускоря?

  2. Как да филтрирам json масив за всеки върнат ред?

  3. Инсталиране на PL/Ruby на PostgreSQL 9.3

  4. Използване на колона псевдоним в клаузата where в Postgresql

  5. Postgres:изчистете цялата база данни преди повторно създаване/попълване от bash скрипт