Carregando ...
Desculpe, ocorreu um erro ao carregar o conteúdo.

33214RES: [mssql-l] Melhores práticas - melhorando o script

Expandir mensagens
  • Wolney Marconi Maia
    6 de dez de 2016

      Olá Vitor, bom dia.

       

      Pelo que percebi, as colunas CodProduto e CodLocal são de uma tipo que não é varchar. Por isso o CONVERT na clausula WHERE.

      Mas do jeito que foi colocado, você poderá ter problemas.

      Falta definir o tamanho do varchar no CONVERTE. Boa pratica.

       

      Outro ponto é colocando o CONVERT na clausula WHERE do jeito que você fez, a consulta vai fazer SCAN TABLE/INDEX. Mesmo que você tenha um índice com essas colunas, o fato de incluir uma função com as colunas de pesquisa, faz com que o SQL Server faça um SCAN para pesquisar. Solução : Tire o CONVERT.

       

      Uma solução :

       

      use TempDB

      go

      drop table TPropostaDT 

      go

      create table TPropostaDT  (CodProposta int , CodProduto int , CodLocal int  )

      go

      /*

      Proposta 1 terá os produtos 1,2 e 3

      Proposta 2 terá os produtos 3,4 e 5

      Ambas para o mesmo local (1)

       

      Quando executar a procedure, a proposta 2 terá os produtos 1,2,3 e mais os produtos 4 e 5

       

      */

       

      insert into TPropostaDT (CodProposta , CodProduto , CodLocal )

      values (1,1,),(1,2,1),(1,3,1)

       

      insert into TPropostaDT (CodProposta , CodProduto , CodLocal )

      values (2,3,1),(2,4,1),(2,5,1)

       

      insert into TPropostaDT (CodProposta , CodProduto , CodLocal  )

      values (3,3,1),(3,4,1),(3,5,1)

       

      select * from TPropostaDT

      where CodProposta = 1

       

       

       

      Declare @CodPropostaOrigem int = 2

      Declare @CodPropostaDestino int = 1

       

      ;

      with

         cteOrigem as (

            select * from TPropostaDT

            where CodProposta = @CodPropostaOrigem

         ),

         cteDestino as (

            select * from TPropostaDT

            where CodProposta = @CodPropostaDestino

      )     

      INSERT INTO TPropostaDT (

             CodProposta ,

             CodProduto  ,

             CodLocal

             )

      SELECT

             @CodPropostaDestino ,

             Origem.CodProduto  ,

             Origem.CodLocal 

             FROM cteOrigem as Origem

             left JOIN cteDestino  Destino

               on Origem.CodProduto = Destino.CodProduto

              and Origem.CodLocal   = Origem.CodLocal

             where Destino.CodProposta is null

       

       

       

       

       

      Wolney Marconi Maia
      http://imagem.imprensaoficial.com.br/mailing/email_spacer.pngRede e Infraestrutura - TI
      http://imagem.imprensaoficial.com.br/mailing/email_spacer.png11-2799-9892

      Só imprima se realmente for necessário, pense em sua responsabilidade com o meio ambiente.
O conteúdo desse e-mail ou de seus anexos é confidencial e restrito ao destinatário da mensagem.
Se, por engano, você recebeu esse e-mail, por favor, notifique o remetente, não faça cópias nem distribua seu conteúdo.

       

       

      De: mssql-l@... [mailto:mssql-l@...]
      Enviada em: segunda-feira, 5 de dezembro de 2016 17:58
      Para: mssql-l@...
      Assunto: [mssql-l] Melhores práticas - melhorando o script

       

       

      Olá Pessoal, 

       

      gostaria da opinião de vocês sobre uma maneira mais elegante de se fazer duas operações no SQL Server, sempre visando a questão do desempenho e também de manutenção futura:  

       

       

       

      1. validação de INSERT em tabela com chave composta :

       

      o seguinte insert em uma tabela de detalhe na qual a chave é composta de 3 colunas:

       

       

      TProposta (CodProposta, Cliente, ...)

      TPropostaDT (CodProposta, CodProduto, CodLocal, ...)

       

      A operação em questão é para a movimentação de itens de dentro de uma proposta para outra  (usada para criar cenários de vendas), de maneira a permitir alterações posteriores na confecção de orçamento, porém, ao inserir itens dentro da proposta destino, este não pode existir dentro da mesma. A solução abaixo está em operação, mas me parece uma enorme engenharia alternativa. 

       

       

      Estive analisando algo referente a trocar esta validação para o uso do WHERE NOT EXISTS mas não cheguei num consenso.

       

       

       

       

       

      2. Registro de Log:

       

      Esta operação foi concebida desta forma devido a alguns problemas com triggers no passado e foi ficando, ficando e está assim até hoje (é do tempo do SQL 6.5). Que opção mais interessante pode ser usada para registros de logs destas operações? Como vocês fazem isto atualmente?

       

       

       

       

      Segue abaixo a rotina em questão, negritado as partes referenciadas nos itens acima.

       

      Versão atual do banco: Microsoft SQL Server 2012 - 11.0.2100.60 (X64)

       

      Grato pela atenção.

       

       

      Att

       

       

       

       

       

       

       

       

       

       

       

      CREATE PROCEDURE spPropostaCenario 

                  @CodPropostaOrigem int,

                  @CodPropostaDestino int,

                  @ID int,

                  @Retorno varchar(500) output

      AS

      BEGIN

       

              DECLARE @QtdeColunas int

              SET QtdeColunas = 0

       

                  INSERT INTO TPropostaDT (

                              CodProposta, 

                              CodProduto, 

                              CodLocal, 

                              QtdeIncluso, 

                              Renovar, 

                              VrBase, 

                              VrIncluso, 

                              VrExtra, 

                              QtdeParcelas, 

                              DescricaoProduto, 

                              Precificador, 

                              ID, 

                              GrupoConsumo, 

                              VrPrecificador, 

                              InstrucaoOperacional

                             

                  SELECT 

                              @CodPropostaDestino, 

                              CodProduto, 

                              CodLocal, 

                              QtdeIncluso, 

                              Renovar, 

                              VrBase, 

                              VrIncluso, 

                              VrExtra, 

                              QtdeParcelas, 

                              DescricaoProduto, 

                              Precificador, 

                              @ID, 

                              GrupoConsumo, 

                              VrPrecificador, 

                              InstrucaoOperacional

                  FROM TPropostaDT 

                  WHERE 

                              CodProposta = @CodPropostaOrigem

                              AND CONVERT(varchar, CodProduto) + '|' + convert(varchar, CodLocal) NOT IN (

                                         SELECT 

                                                     CONVERT(varchar, CodProduto) + '|' + convert(varchar, CodLocal)

                                         FROM TPropostaDT

                                         WHERE 

                                                     CodProposta = @CodPropostaDestino

                                         )

       

              SET QtdeColunas = @@ROWCOUNT

       

       

                  -- Registro de Log

                  INSRT INTO TLog (ID, Modulo, Obs)

                  VALUES (

                              @ID,

                              'PropostaCenario',

                              convert(varchar, ISNULL(@CodPropostaOrigem,0) )         

                              +'|'+ convert(varchar, ISNULL(@CodPropostaDestino,0) )

                              +'|'+ convert(varchar, ISNULL(@QtdeColunas,0) )

                         �

      (Message over 64 KB, truncated)

    • Mostrar todas as 6 mensagens neste tópico