Para que serve '$$' em PL / pgSQL

93

Por ser completamente novo no PL / pgSQL, qual é o significado dos cifrões duplos nesta função :

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;

Estou supondo que, em RETURNS boolean AS $$, $$é um espaço reservado.

A última linha é um pouco misteriosa: $$ LANGUAGE plpgsql STRICT IMMUTABLE;

A propósito, o que significa a última linha?

vetor
fonte
4
Por favor, considere marcar a resposta de Erwin como resposta a esta pergunta, sua descrição explica o que realmente são $$e você pode aprender algo novo lendo-o, por exemplo, também há$foo$
csharpfolk

Respostas:

135

Os cifrões são usados ​​para cotação de dólares e não são de forma alguma específicos para definições de funções . Ele pode ser usado para substituir aspas simples em praticamente qualquer lugar em scripts SQL.

O corpo de uma função é um literal de string que deve ser colocado entre aspas simples. A cotação de dólar é um substituto específico do PostgreSQL para aspas simples para evitar problemas de cotação dentro do corpo da função. Você também pode escrever sua definição de função com aspas simples. Mas então você teria que escapar de todas as aspas simples no corpo:

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;

Esta não é uma boa ideia. Em vez disso, use a cotação do dólar, mais especificamente também coloque um token entre $$para torná-la única - você pode querer usar $ -quotes dentro do corpo da função também. Eu faço muito isso, na verdade.

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

Detalhes:

Quanto à sua segunda pergunta:
Leia o manualCREATE FUNCTION mais excelente para entender a última linha do seu exemplo.

Erwin Brandstetter
fonte
1
Você deve dizer um bom manual , RTEM simplesmente não tem o tom certo :)
mu é muito curto
@muistooshort: Que pena, tentar uma variação do tema parece ter quebrado a harmonia. Como você gosta do RTMEM? :)
Erwin Brandstetter
1
Tentei gritar e não era a mesma coisa. Embora, existam algumas situações em que a polidez conta.
mu é muito curto
@ErwinBrandstetter Ok, mas o que é $body$? De CREATE OR REPLACE FUNCTION update_ts() RETURNS TRIGGER AS $BODY$ BEGIN NEW.updated_at = NOW(); RETURN NEW; END; $BODY$ LANGUAGE plpgsql- não vejo bodydefinido em nenhum lugar. Eu realmente não tenho ideia do que está acontecendo aqui
Growler
2
@Growler: $body$é apenas uma "cotação do dólar", como expliquei. Mais detalhes: stackoverflow.com/a/12320729/939860
Erwin Brandstetter
21

O $$ é um delimitador que você usa para indicar onde a definição da função começa e termina. Considere o seguinte,

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

A sintaxe da função de criação é semelhante, mas como você vai usar todos os tipos de SQL em sua função (especialmente o fim da instrução; caractere), o analisador dispararia se você não o delimitasse. Portanto, você deve ler sua declaração como:

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

As coisas após a definição real são opções que fornecem ao banco de dados mais informações sobre sua função, para que ele possa otimizar seu uso.

Na verdade, se você olhar em "4.1.2.2. Constantes de string citadas em dólar" no manual, verá que pode até usar caracteres entre os símbolos de dólar e tudo contará como um delimitador.

Capitão Coder
fonte