Eu tenho uma tabela tag
com 2 colunas: id
(uuid) e name
(texto). Agora, quero inserir uma nova tag na tabela, mas se a tag já existir, quero simplesmente obter o id
registro existente.
Eu assumi que eu poderia apenas usar ON CONFLICT DO NOTHING
em combinação com RETURNING "id"
:
INSERT INTO
"tag" ("name")
VALUES( 'foo' )
ON CONFLICT DO NOTHING
RETURNING "id";
Mas isso retorna um conjunto de resultados vazio, se a tag com o nome "foo" já existir.
Alterei a consulta para usar uma DO UPDATE
cláusula noop :
INSERT INTO
"tag" ("name")
VALUES( 'foo' )
ON CONFLICT ("name") DO UPDATE SET "name" = 'foo'
RETURNING "id";
Isso funciona como pretendido, mas é um pouco confuso, porque estou apenas definindo o nome para o valor já existente.
É este o caminho a seguir sobre esse problema ou há uma abordagem mais simples que estou perdendo?
postgresql
upsert
postgresql-9.5
Der Hochstapler
fonte
fonte
returning excluded.id
?ERROR: missing FROM-clause entry for table "excluded"
ao usarDO NOTHING
.Respostas:
Isso funcionará (até onde eu testei) nos 3 casos, se os valores a serem inseridos forem todos novos ou já estiverem na tabela ou em uma mistura:
Provavelmente, existem outras maneiras de fazer isso, talvez sem usar a nova
ON CONFLICT
sintaxe.fonte
Não faço ideia se como isso vai funcionar, mas apenas como outra opção para tentar, aqui está fazendo o mesmo da maneira antiga (sem
ON CONFLICT
):Ou seja, insira apenas os nomes [únicos] não encontrados na
tag
tabela e retorne os IDs; combine isso com os IDs dos nomes que existem emtag
, para a saída final. Você também podename
enviar para a saída, conforme sugerido pelo ypercubeᵀᴹ , para saber qual ID corresponde a qual nome.fonte
SELECT .. FROM ins UNION ALL SELECT ... FROM val JOIN tag ... ;