On 2014-06-13 12:02, Matheus de Oliveira wrote:
2014-06-13 6:39 GMT-03:00 Eloi Ribeiro <[email protected]>:
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.
Obrigado, isso era o que me faltava saber.
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):
Muito melhor a solução que apresentas, poupo um passo.
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)?
Tem um UNIQUE, não existem valores repetidos.
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).
Não deveria passar porque nesta tabela só podem inserir valores muito
pouca gente. Mas terei cuidado com isso.
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).
Eu também não gosto nada e da-me muitas dores de cabeça quando tenho de
escrever código em Python. Pois todo o banco de dados, todos os objetos
estão em "PascalCase", uma loucura. Cada vez que tenho de por uma aspa
(") tenho de pressionar 3 teclas! E não imaginas o que me custou de
convencer-lhes de que isto não é o mais ótimo. Mas se fosse só isso...
A função ficou assim:
CREATE OR REPLACE FUNCTION "Attribute".fun_insert_attribute(name text,
description text, type text)
RETURNS text AS
$BODY$
DECLARE
attribute_id integer;
BEGIN
-- verifica se ja existe e devolve o id
SELECT "AttributeId" INTO attribute_id FROM "Attribute"."Attribute"
WHERE lower(trim("Name")) LIKE lower(trim(name));
-- se nao existe, inserir e conhecer o id
IF NOT FOUND THEN
INSERT INTO
"Attribute"."Attribute"("Name","Description",version_type)
VALUES(trim(name),trim(description),trim(type)) RETURNING "AttributeId"
INTO attribute_id;
END IF;
RETURN attribute_id;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
--
Eloi
_______________________________________________
pgbr-geral mailing list
[email protected]
https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral