VALIDANDO UM INSERTE COM EXISTS

AMELINHACODE 03/06/2022 11:55:43
#500025
Boa tarde pessoal,

Tenho um script aqui que insere numa tabela vários registros (tabela de configurações)
A medida que o sistema vai tendo novos recursos, deixo ativo (ou nao) aquele recurso em algum cliente
enfim...

Normalmente insiro assim no MSSMS
INSERT INTO configuracao (config_nome, config_valor) VALUES ("CONFIMPNFCE", "SIM")

Até ai normal, porem já me deparei varias vezes com a situação de inserir valores duplicados... isso vai dar bug na hora que a abrir a parte do recurso que vai verificar se tá ativo para aquele cliente...

Então pensei em verificar a existencia do na tabela antes de inserir... pensei em algo assim:
IF EXISTS  (SELECT config_nome FROM configuracao WHERE (config_nome = "CONFIMPNFCE"))
"FAZ NADA
ELSE
INSERT INTO configuracao (config_nome, config_valor) VALUES ("CONFIMPNFCE", "SIM")
END IF


porem alem de não funcionar, ficou 5 linhas... e precisava algo mais "clean" numa linha

tipo
Se NÃO tem o valor XXX entao inserir XXX
KERPLUNK 03/06/2022 14:01:26
#500027
Resposta escolhida
Dependendo do banco de dados, essa funcionalidade já existe. Qual o banco de dados está usando?
AMELINHACODE 03/06/2022 15:52:58
#500028
Citação:

:
Dependendo do banco de dados, essa funcionalidade já existe. Qual o banco de dados está usando?



Sql Server Express 2008
JABA 03/06/2022 16:23:52
#500029
Não precisa fazer pesquisa alguma. Voce tem que tratar isso com chave primária nos campos que não podem haver repetição. Daí, quando for inserir e os dados forem repetidos, vai gerar uma exceção na aplicação.
KERPLUNK 03/06/2022 16:43:09
#500030
Citação:

:
Não precisa fazer pesquisa alguma. Voce tem que tratar isso com chave primária nos campos que não podem haver repetição. Daí, quando for inserir e os dados forem repetidos, vai gerar uma exceção na aplicação.


Seria realmente o mais indicado.
AMELINHACODE 03/06/2022 17:07:09
#500031
Mais caso eu quisesse fazer o EXISTS e depois o INSERT
JABA 03/06/2022 19:10:12
#500032
Citação:

:
Mais caso eu quisesse fazer o EXISTS e depois o INSERT



Voce não pode fazer assim porque pode gerar problema de concorrencia. Ou seja, duas pesquisas poderão ser feitas quase que ao mesmo tempo e ambas passarem na verificação, daí na hora de inserirem, vai gerar duplicação.
KERPLUNK 03/06/2022 20:59:25
#500035
O que voce se refere, é um anti-pattern, chamado UPSERT e é na prática uma má idéia, mas se voce quer mesmo fazer, sugiro usar algo assim:

CREATE PROCEDURE s_ConfigNome_Upsert ( @Nome nvarchar(4000), @Config nvarchar(max) )
AS
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;

MERGE dbo.configuracao AS myTarget
USING (SELECT config_nome FROM configuracao WHERE (config_nome = @Nome)) AS mySource
ON mySource.config_nome = myTarget.config_nome
WHEN MATCHED THEN UPDATE
SET config_valor = mySource.config_valor
WHEN NOT MATCHED THEN
INSERT INTO configuracao (config_nome, config_valor) VALUES (@Nome, @Config)


É um dos modos mais seguros de fazer o que voce quer porque amarra uma transação.
AMELINHACODE 13/06/2022 20:30:09
#500057
Citação:

:
O que voce se refere, é um anti-pattern, chamado UPSERT e é na prática uma má idéia, mas se voce quer mesmo fazer, sugiro usar algo assim:


CREATE PROCEDURE s_ConfigNome_Upsert ( @Nome nvarchar(4000), @Config nvarchar(max) )
AS
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;

MERGE dbo.configuracao AS myTarget
USING (SELECT config_nome FROM configuracao WHERE (config_nome = @Nome)) AS mySource
ON mySource.config_nome = myTarget.config_nome
WHEN MATCHED THEN UPDATE
SET config_valor = mySource.config_valor
WHEN NOT MATCHED THEN
INSERT INTO configuracao (config_nome, config_valor) VALUES (@Nome, @Config)


É um dos modos mais seguros de fazer o que voce quer porque amarra uma transação.



Desculpe a demora, tive q fazer um estagio e nao tive mais tempo... retornei hoje
Executei e deu o seguinte erro:
[txt-color=#e80000]Mensagem 156, Nível 15, Estado 1, Procedimento s_ConfigNome_Upsert, Linha 12
Sintaxe incorreta próxima à palavra-chave "INTO".[/txt-color]
Tópico encerrado , respostas não são mais permitidas