PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Zrozumienie różnicy między literałem int a parametrem int w funkcji PL/pgSQL

Dlaczego?

PL/pgSQL wykonuje zapytania SQL, takie jak przygotowane instrukcje . Instrukcja zastępowania parametrów:

Zwróć uwagę na termin wartości . Sparametryzować można tylko wartości rzeczywiste, ale nie słowa kluczowe, identyfikatory lub nazwy typów. 32 w bit(32) wygląda jak wartość, ale modyfikator typu danych jest tylko „wartością” wewnętrznie i nie można go sparametryzować. SQL wymaga znajomości typów danych na etapie planowania, nie może czekać na etap wykonania.

możesz osiągnij swój cel dzięki dynamicznemu SQL i EXECUTE . Jako weryfikacja koncepcji :

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;

Zadzwoń:

SELECT lpad_bits(b'1001100111000', 32);  

Zwróć uwagę na różnicę między sz używane jako dosłowne do zbudowania instrukcji i jej drugiego wystąpienia, gdy jest używana jako wartość , który można przekazać jako parametr.

Szybsze alternatywy

Doskonałym rozwiązaniem dla tego konkretnego zadania jest po prostu użycie lpad() jak Zasugerowano @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;

(Prostsza jak zwykła funkcja SQL, która umożliwia także wbudowanie funkcji w kontekście zapytań zewnętrznych).

Kilka razy szybciej niż powyższa funkcja. Mała wada:musimy rzutować do text i wróć do varbit . Niestety, lpad() nie jest obecnie zaimplementowany dla varbit . Podręcznik:

overlay() jest dostępna, możemy mieć tańszą funkcję:

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;

Szybciej, jeśli możesz pracować z varbit wartości na początek. (Zaleta jest (częściowo) unieważniona, jeśli musisz rzucić text do varbit w każdym razie.)

Zadzwoń:

SELECT lpad_bits3(b'1001100111000', '00000000000000000000000000000000');
SELECT lpad_bits3(b'1001100111000',  repeat('0', 32)::varbit);

Możemy nałożyć funkcja z wariantem pobierającym liczbę całkowitą do wygenerowania base sam:

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;

Zadzwoń:

SELECT lpad_bits3(b'1001100111000', 32;

Powiązane:



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Przegląd buforowania dla PostgreSQL

  2. Spowodowane przez:org.postgresql.util.PSQLException:FATAL:uwierzytelnianie hasła nie powiodło się dla użytkownika admin

  3. Instalowanie gem PG; BŁĄD:nie udało się zbudować rozszerzenia natywnego klejnot

  4. jak używać poprawnie, jeśli instrukcja postgresql

  5. Zmiana z SQLite na PostgreSQL w nowym projekcie Rails