Do czego służy '$$' w PL / pgSQL

98

Będąc zupełnie nowym w PL / pgSQL, jakie jest znaczenie podwójnych znaków dolara w tej funkcji :

CREATE OR REPLACE FUNCTION check_phone_number(text)
RETURNS boolean AS $$
BEGIN
  IF NOT $1 ~  e'^\\+\\d{3}\\ \\d{3} \\d{3} \\d{3}$' THEN
    RAISE EXCEPTION 'Wrong formated string "%". Expected format is +999 999';
  END IF;
  RETURN true; 
END;
$$ LANGUAGE plpgsql STRICT IMMUTABLE;

Zgaduję, że RETURNS boolean AS $$, $$jest symbolem zastępczym.

Ostatnia linijka jest trochę tajemnicza: $$ LANGUAGE plpgsql STRICT IMMUTABLE;

A propos, co oznacza ostatnia linijka?

wektor
źródło
4
Proszę rozważyć oznaczenie odpowiedzi Erwina jako odpowiedź na to pytanie, jego opis wyjaśnia, czym właściwie są $$i możesz dowiedzieć się czegoś nowego czytając go np. Jest też$foo$
csharpfolk

Odpowiedzi:

143

Znaki dolara są używane do kwotowań dolara i nie są w żaden sposób specyficzne dla definicji funkcji . Można go używać do zastępowania pojedynczych cudzysłowów praktycznie w każdym miejscu skryptów SQL.

Ciało funkcji jest literałem ciągu, który musi być ujęty w pojedyncze cudzysłowy. Cytowanie dolara jest specyficznym dla PostgreSQL substytutem pojedynczych cudzysłowów, aby uniknąć problemów z cytowaniem w treści funkcji. Możesz również napisać definicję funkcji w apostrofach. Ale wtedy musiałbyś uciec przed wszystkimi pojedynczymi cudzysłowami w treści:

CREATE OR REPLACE FUNCTION check_phone_number(text)
RETURNS boolean AS
'
BEGIN
  IF NOT $1 ~  e''^\\+\\d{3}\\ \\d{3} \\d{3} \\d{3}$'' THEN
    RAISE EXCEPTION ''Malformed string "%". Expected format is +999 999'';
  END IF;
  RETURN true; 
END
' LANGUAGE plpgsql STRICT IMMUTABLE;

To nie jest dobry pomysł. Zamiast tego $$użyj cudzysłowów , a dokładniej umieść token między znakami, aby uczynić go unikalnym - możesz również chcieć użyć $ -quotes w treści funkcji. Właściwie to często to robię.

CREATE OR REPLACE FUNCTION check_phone_number(text)
  RETURNS boolean  
AS
$func$
BEGIN
 ...
END
$func$  LANGUAGE plpgsql STRICT IMMUTABLE;

Detale:

A co do drugiego pytania:
Przeczytaj najdoskonalszy podręcznik,CREATE FUNCTION aby zrozumieć ostatnią linijkę swojego przykładu.

Erwin Brandstetter
źródło
1
Powinieneś powiedzieć dobra instrukcja , RTEM po prostu nie ma odpowiedniego pierścienia :)
mu jest za krótkie
@muistooshort: Mój błąd, próbowanie wariacji na temat wydaje się zepsuć harmonię. Jak ci się podoba RTMEM? :)
Erwin Brandstetter
1
Próbowałem to wykrzyczeć i to po prostu nie było to samo. Chociaż są sytuacje, w których liczy się grzeczność.
mu jest za krótkie
@ErwinBrandstetter Dobrze, ale co to jest $body$? Od CREATE OR REPLACE FUNCTION update_ts() RETURNS TRIGGER AS $BODY$ BEGIN NEW.updated_at = NOW(); RETURN NEW; END; $BODY$ LANGUAGE plpgsql- bodynigdzie nie widzę definicji. Naprawdę nie mam pojęcia, co się tutaj dzieje
Growler
2
@Growler: $body$to po prostu „cytowanie dolara”, jak wyjaśniłem. Więcej szczegółów: stackoverflow.com/a/12320729/939860
Erwin Brandstetter
21

$$ jest separatorem używanym do wskazania początku i końca definicji funkcji. Rozważ następujące,

CREATE TABLE <name> <definition goes here> <options go here, eg: WITH OIDS>

Składnia funkcji create jest podobna, ale ponieważ zamierzasz używać wszelkiego rodzaju SQL w swojej funkcji (szczególnie koniec instrukcji; znak), parser wyłączyłby się, gdybyś go nie ograniczył. Dlatego powinieneś przeczytać swoje oświadczenie jako:

CREATE OR REPLACE FUNCTION check_phone_number(text)
RETURNS boolean AS <code delimited by $$> LANGUAGE plpgsql STRICT IMMUTABLE;

Rzeczy po rzeczywistej definicji to opcje, które dają bazie danych więcej informacji o twojej funkcji, aby mogła zoptymalizować jej użycie.

W rzeczywistości, jeśli zajrzysz do sekcji „4.1.2.2. Stałe łańcuchowe w cudzysłowach w dolarach” w podręczniku, zobaczysz, że możesz nawet używać znaków między symbolami dolara i będzie to traktowane jako jeden separator.

Kapitanie Coder
źródło