41.2. Estrutura do PL/pgSQL #

As funções escritas em PL/pgSQL são definidas para o servidor executando o comando CREATE FUNCTION. Este comando normalmente se parece com, digamos,

CREATE FUNCTION algumafunc(integer, text) RETURNS integer
AS 'texto do corpo da função'
LANGUAGE plpgsql;

O corpo da função é apenas um literal cadeia de caracteres no que diz respeito a CREATE FUNCTION. Geralmente, é útil usar delimitação por cifrão (veja Constantes do tipo cadeia de caracteres delimitadas por cifrão) para escrever o corpo da função, em vez de usar a sintaxe normal de apóstrofos. Sem a delimitação por cifrão, quaisquer apóstrofos ou contrabarras no corpo da função devem receber escape dobrando-os. Quase todos os exemplos neste capítulo usam delimitação por cifrão para seus corpos de função.

PL/pgSQL é uma linguagem estruturada em blocos. O texto completo do corpo de uma função deve ser um bloco. Um bloco é definido como:

[ <<rótulo>> ]
[ DECLARE
    declarações ]
BEGIN
    instruções
END [ rótulo ];

Cada declaração e cada instrução no interior de um bloco é encerrada por ponto e vírgula. Um bloco que aparece dentro de outro bloco deve ter um ponto e vírgula após o END, conforme mostrado acima; entretanto, o END final que conclui o corpo da função não requer ponto e vírgula.

Dica

Um erro comum é escrever ponto e vírgula logo após o BEGIN. Isto está errado, resultando em erro de sintaxe.

O rótulo só é necessário se for desejado identificar o bloco para uso em uma instrução EXIT, ou para qualificar os nomes das variáveis declaradas no bloco. Se for fornecido um rótulo após o END, este rótulo deverá corresponder ao rótulo no início do bloco.

Não faz diferença usar letras maiúsculas ou minúsculas nas palavras-chave. Os identificadores são implicitamente convertidos em letras minúsculas, a menos que sejam colocados entre aspas, assim como nos comandos SQL comuns.

Os comentários funcionam da mesma forma no código PL/pgSQL que no SQL comum. Dois hifens (--) iniciam um comentário, que se estende até o final da linha. O /* inicia um bloco de comentários, que se estende até a ocorrência correspondente de */. Os blocos de comentários podem ser aninhados.

Toda instrução na seção de instrução de um bloco pode ser um sub-bloco. Os sub-blocos podem ser usados para agrupamento lógico, ou para criar variáveis locais em um pequeno grupo de instruções. As variáveis declaradas em um sub-bloco escondem quaisquer variáveis com nomes idênticos de blocos externos durante a execução do sub-bloco; mas é possível acessar as variáveis externas assim mesmo, qualificando seus nomes com o rótulo do bloco externo. Por exemplo:

CREATE FUNCTION algumafunc() RETURNS integer AS $$
<< blocoexterno >>
DECLARE
    quantidade integer := 30;
BEGIN
    RAISE NOTICE 'A quantidade aqui é %', quantidade;  -- Mostra 30
    quantidade := 50;
    --
    -- Criar um sub-bloco
    --
    DECLARE
        quantidade integer := 80;
    BEGIN
        RAISE NOTICE 'A quantidade aqui é %', quantidade;  -- Mostra 80
        RAISE NOTICE 'A quantidade lá fora é %', blocoexterno.quantidade;  -- Mostra 50
    END;

    RAISE NOTICE 'A quantidade aqui é %', quantidade;  -- Mostra 50

    RETURN quantidade;
END;
$$ LANGUAGE plpgsql;

Nota

Na verdade, existe um bloco externo oculto envolvendo o corpo de qualquer função PL/pgSQL. Este bloco fornece as declarações dos parâmetros da função (se houver), bem como algumas variáveis especiais como FOUND (veja Obtenção do status do resultado). O bloco externo é rotulado com o nome da função, significando que parâmetros e variáveis especiais podem ser qualificados com o nome da função.

É importante não confundir o uso de BEGIN/END para agrupar instruções no PL/pgSQL com os comandos SQL de mesmo nome usados para controlar transação. Os BEGIN/END do PL/pgSQL são apenas para agrupamento; não iniciam ou terminam uma transação. Veja Gerenciamento de transação para obter informações sobre como gerenciar transações no PL/pgSQL. Além disso, um bloco contendo a cláusula EXCEPTION forma de fato uma subtransação que pode ser desfeita sem afetar a transação externa. Para obter mais informações veja Captura de erros.