tenho uma tabela:
CREATE TABLE mytable (id SERIAL, name VARCHAR(10) PRIMARY KEY)
Agora quero adicionar nomes a esta tabela, mas apenas se eles ainda não existirem na tabela e, em ambos os casos, retornar o id
. Como posso fazer isso com o PostgreSQL?
Eu vi alguns scripts para isso, mas não há uma única instrução SQL para fazer isso?
Por exemplo, posso INSERT e retornar id
com:
INSERT INTO mytable (name) VALUES ('Jonas') RETURNING id
funciona na primeira vez e retorna id
. Mas falha se Jonas
já existir na tabela, mas quero retornar id
mesmo que o Insert falhe. Isso é possível fazer com o PostgreSQL?
As instruções Upsert costumavam ser planejadas para 9.1, mas foram adiadas para 9.2, portanto, até lá, sua única opção é testar se o valor já existe antes de inserir.
Como alternativa, se sua intenção é apenas ter um identificador exclusivo, você pode simplesmente usar uma sequência + nextval.
Se você deseja criar uma função para fazer isso, isso deve começar:
Se você estiver no 9.1, há uma espécie de solução alternativa para isso usando CTEs graváveis
http://xzilla.net/blog/2011/Mar/Upserting-via-Writeable-CTE.html
Eu acho que é muito difícil fazer isso em uma única instrução SQL. Talvez você deva escrever uma função para fazer isso. Essa é a minha opinião pessoal. Porque você deseja retornar o id mesmo que o sql gere um "ERRO: valor de chave duplicado".
Eu gosto de simplesmente capturar a exceção unique_violation conforme proposto aqui:
Maneira ideal de ignorar inserções duplicadas?
A beleza desta solução é que ela não sofre as condições de corrida. Você teria que adicionar código ao manipulador de exceção para procurar o id.