2014-06-13 6:39 GMT-03:00 Eloi Ribeiro <[email protected]>:

> Gostaria de fazer uma função que:
>  1. verifica-se se um determinado valor já existe numa tabela
>  2. se sim, que me devolva o id desse registo
>  3. se não, que faca o insert e em seguida devolva o id resultante
>
> Escrevi a seguinte código mas falta-me saber como recuperar o resultado do
> EXECUTE. Alguém me pode ajudar? Obrigado.
>

Em primeiro lugar, você não precisaria do EXECUTE, basta executar os
comandos SQL diretamente. No seu caso o EXECUTE não é só ruim, está
**errado**, pois não trata corretamente escape e está suscetível à
SQL-injection.

Agora, se quer recuperar o valor, mas caso não tenha inserir, basta usar a
variável FOUND (ainda não está bom, veja as considerações abaixo):

    SELECT "AttributeId" INTO n
    FROM "Attribute"."Attribute"
    WHERE lower("Name") LIKE lower(name);
    -- se não existe, inserir e conhecer o id
    IF NOT FOUND THEN
        INSERT INTO "Attribute"."Attribute"("Name", "Description",
version_type)
        VALUES(name, description, type)
        RETURNING "AttributeId" INTO n;
    END IF;
    RETURN n;

Agora, essa função apesar de **aparentemente** fazer o que você quer, ainda
tem diversos "possíveis" problemas:

1. Você busca usando ILIKE (até troquei por lower+LIKE, por ser mais
eficiente), mas o que acontece se retornar mais de um registro? Poderia
acontecer? No caso acima o PG irá pegar um deles arbitrariamente (na sorte
mesmo). Será que você não queria ter usando igualdade? O campo "Name" é
único (tem chave UNIQUE)?
2. A função não está tratando concorrência. Imagine o que acontece se você
fizer o SELECT, não retornar nada, mas quando for fazer um INSERT alguém
acabou de um "Name" que casaria. Se "Name" for UNIQUE vai dar um problemão;
se não, só vai ser estranho e acho que você deveria repensar seriamente no
seu modelo de dados e suas operações (me cheira mal, mas tenho pouca
informação para afirmar).
3. Por que está usando nomes de tabelas e atributos com aspas duplas? Não
acha que fica horrível de usar assim depois? (esse não é um problema de
fato, só uma prática ruim na minha opinião).

Atenciosamente,
-- 
Matheus de Oliveira
Analista de Banco de Dados
Dextra Sistemas - MPS.Br nível F!
www.dextra.com.br/postgres
_______________________________________________
pgbr-geral mailing list
[email protected]
https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral

Responder a