none
Chamar SPROC com Insert e verificação se o registro já existe 2x rapidamente faz com que o registro seja criado 2x RRS feed

  • Pergunta

  • Bom dia a todos!

    Tenho um software que dispara uma informação para todos as instancias conectadas e ele envia essa informação para uma SPROC que salva mas antes de fazer isso ela verifica se o registro já existe, afim de não ter registros duplicados no banco. Sei que o grande problema é essa informação ser enviada a todas as instancias ao invés de ser enviada a apenas uma e esta responsável por salvar mas alterar isso não esta no escopo agora.

     

    Essa verificação é feita através do seguinte código: 

    IF NOT EXISTS
    (
    	SELECT
    		*
    	FROM
    		Tabela
    	WHERE
    		campo1	= @campo1
    	AND	campo2	= @campo2
    	AND	campo3	= @campo3
    )

    Mas mesmo assim os registro continuam a ser inseridos repetidos. Criei uma coluna pra ver a diferença de tempo que esses dois registros são inseridos através de um GetDate() durante o insert e noto que as diferenças de tempo são minimas como por exemplo '2012-11-19 10:43:50.580' e '2012-11-19 10:43:50.570', 1 centésimos de segundos (?).

    Para tentar solucionar isso, tentei criar uma transação na SPROC mas sem sucesso. Tentei também alterar o Isolation Level para Read Uncommited, achando que talvez ele não estava achando no exists por ainda não ter sido Commitado, mas ainda sem sem sucesso.

    Enfim, estou começando a ficar sem idéias e gostaria da colaboração de vocês para me ajudar a solucionar esse problema.

    Toda idéia ou sugestão é bem vinda!

    Obrigado a todos pela atenção

    segunda-feira, 19 de novembro de 2012 13:06

Respostas

  • O Not Exists não tem como falhar. Pode estar acontecendo de um dos campos não ser igual e por isso a validação está falhando.

    Ex.: Se um desses 3 campos estiver com valor nulo, a comparação com igual poderá falhar.

    Quais são os campos que estão sendo validados no Exists? Qual o tipo de dados deles? Por acaso eles estão nulos na base?


    Roberson Ferreira - Database Developer
    Acesse: www.robersonferreira.com.br
    Email: contato@robersonferreira.com.br

    Se esta sugestão for útil, por favor, classifique-a como útil.
    Se ela lhe ajudar a resolver o problema, por favor, marque-a como Resposta.

    segunda-feira, 19 de novembro de 2012 18:27
    Moderador
  • Thiago, se a versão do SQL Server for superior ou igual ao 2k8 você pode utilizar o Merge, http://technet.microsoft.com/pt-br/library/bb510625(v=sql.100).aspx

    Ele faz uma validação, via select, de existência e decide se faz um insert ou update, caso precise ele pode fazer um delete também.

    Outra opção que vejo é usar um insert select com uma clausula NOT EXISTS, seria algo como:

    insert...
    select "valores a inserir" NOT EXISTS(select "valores a inserir")

    Essa segunda não é tão performática quanto a primeira com o Merge, mas funciona bem, no seu caso vai depender do tamanho da tabela, além de funcionar no SQL 2k e 2k5.

    O ideal é que a sua proc tente resolver com uma só instrução no banco.

    quarta-feira, 21 de novembro de 2012 16:56

Todas as Respostas

  • Thiago,

    Tenta checar com o valor do campo até os segundos somente, sem levar em cosideração as frações de segundo.


    Se esta sugestão for útil, por favor, classifique-a como útil. Se ela lhe ajudar a resolver o problema, por favor, marque-a como Resposta.

    segunda-feira, 19 de novembro de 2012 13:11
  • Que comando exatamente é disparado para as instâncias?

    Roberson Ferreira - Database Developer
    Acesse: www.robersonferreira.com.br
    Email: contato@robersonferreira.com.br

    Se esta sugestão for útil, por favor, classifique-a como útil.
    Se ela lhe ajudar a resolver o problema, por favor, marque-a como Resposta.

    segunda-feira, 19 de novembro de 2012 13:13
    Moderador
  • Marcos Rocha,

    Nenhum dos campos que eu testo no exists varia entre os dois registros.

    Roberson Ferreira,

    É disparado via socket um comando que informa os dados que devem ser logados de um exame. Os dados que devem ser logados são disparados para todas as instancias e faz com que todas elas chamem a SPROC para salvar com os mesmos parametros.

    Agradeço pela atenção

    segunda-feira, 19 de novembro de 2012 13:18
  • Sim, mas esta questão de cadastrar em duplicidade não é normal.

    Parece que o código está sendo chamado duas vezes para a mesma instância. Você já verificou isso?

    Qualquer coisa ative o Profiler para tentar verificar o que realmente está acontecendo.


    Roberson Ferreira - Database Developer
    Acesse: www.robersonferreira.com.br
    Email: contato@robersonferreira.com.br

    Se esta sugestão for útil, por favor, classifique-a como útil.
    Se ela lhe ajudar a resolver o problema, por favor, marque-a como Resposta.

    segunda-feira, 19 de novembro de 2012 16:16
    Moderador
  • Roberson Ferreira,

    Isso de fato está acontecendo, como eu disse no primeiro post. O problema é que isso é um problema da arquitetura da solução que não temos no escopo solucionar isso agora.

    O que eu busco é uma solução para não permitir que a stored procedure consiga gravar o registro com as informações que já existe. 

    A stored procedure realmente é chamada mais de uma vez, e pelo campo que criei usando GetDate(), num intervalo de tempo muito pequeno. O qeu eu não consigo entender é porque o EXISTS não está se comportando como devia.

    segunda-feira, 19 de novembro de 2012 18:02
  • O Not Exists não tem como falhar. Pode estar acontecendo de um dos campos não ser igual e por isso a validação está falhando.

    Ex.: Se um desses 3 campos estiver com valor nulo, a comparação com igual poderá falhar.

    Quais são os campos que estão sendo validados no Exists? Qual o tipo de dados deles? Por acaso eles estão nulos na base?


    Roberson Ferreira - Database Developer
    Acesse: www.robersonferreira.com.br
    Email: contato@robersonferreira.com.br

    Se esta sugestão for útil, por favor, classifique-a como útil.
    Se ela lhe ajudar a resolver o problema, por favor, marque-a como Resposta.

    segunda-feira, 19 de novembro de 2012 18:27
    Moderador
  • Roberson Ferreira,

    Os campos são um inteiro, um DateTime e um NVARCHAR. Como as chamadas são originadas da mesma fonte de dados, apenas de locais diferentes, e não há nenhum pós-processamento nos registros o NOT EXISTS não deveria falhar. Eu entendo que isso deve ocorrer devido as chamadas serem praticamente ao mesmo tempo e a inserção ser feita entre o teste do NOT EXISTS e o INSERT, mas acho tudo isso muita conspiração pra fazer com que o software não funcione como esperado, rs.

    segunda-feira, 19 de novembro de 2012 18:59
  • Thiago, se a versão do SQL Server for superior ou igual ao 2k8 você pode utilizar o Merge, http://technet.microsoft.com/pt-br/library/bb510625(v=sql.100).aspx

    Ele faz uma validação, via select, de existência e decide se faz um insert ou update, caso precise ele pode fazer um delete também.

    Outra opção que vejo é usar um insert select com uma clausula NOT EXISTS, seria algo como:

    insert...
    select "valores a inserir" NOT EXISTS(select "valores a inserir")

    Essa segunda não é tão performática quanto a primeira com o Merge, mas funciona bem, no seu caso vai depender do tamanho da tabela, além de funcionar no SQL 2k e 2k5.

    O ideal é que a sua proc tente resolver com uma só instrução no banco.

    quarta-feira, 21 de novembro de 2012 16:56