UPDATE de vários registros

Forum sobre SQL.

Moderador: Moderadores

gilbertosilverio
Usuário Nível 3
Usuário Nível 3
Mensagens: 339
Registrado em: 18 Jan 2009 10:39
Localização: Ribeirao Pires - SP

UPDATE de vários registros

Mensagem por gilbertosilverio »

Olá amigos,

Tenho uma duvida, se e possível fazer o UPDATE de vários registros de uma única vez?

Tenho uma base de 23000 registros, hoje faço a alteração item a item, so que demora um pouco, tem como executar o update de vários registros ao mesmo tempo...

Hoje faço desta maneira, item a item, queria fazer um único arquivo e atualizar tudo de uma só fez, e possível?

Código: Selecionar todos


              cQuery2   := [UPDATE agille54_api.tray_produtos ]
              cQuery2   += [SET estoque = ] + ALLTRIM(STR(nQTDE,11))+[, ]
              cQuery2   += [preco = ]       + ALLTRIM(nPRECO)       +[, ]
              IF xCod_Spec <> [nao]
                 cQuery2+= [894687_processamentoPendente = 'Atualizar', ]
              ENDIF
              cQuery2   += [845890_processamentoPendente = 'Atualizar' ]
              cQuery2   += [WHERE  sku = ]  + ALLTRIM(STR(MATA_GERAL[G,1],11))
              oQuery2   := oServer:Execute(cQuery2)

Grato.
GilbertoSilverio
gilbertosilverio@gmail.com
gilbertosilverio2003@yahoo.com.br
alxsts
Colaborador
Colaborador
Mensagens: 3092
Registrado em: 12 Ago 2008 15:50
Localização: São Paulo-SP-Brasil

UPDATE de vários registros

Mensagem por alxsts »

Olá!
gilbertosilverio escreveu:Tenho uma duvida, se e possível fazer o UPDATE de vários registros de uma única vez?
Claro!

SQL foi pensado para trabalhar com conjuntos de registros. Fazer com que ele trabalhe linha a linha geralmente causa queda na performance.

No teu código, você atualiza colunas de uma tabela com o conteúdo de variáveis. Para conseguir o que quer, provavelmente os valores a atualizar precisarão estar em outra tabela. As duas tabelas precisarão ter uma coluna em comum que permita associar as duas tabelas, através da cláusula JOIN.

Veja alguns exemplos do comando UPDATE: =How to Update a Column Based on a Filter of Another Column (em inglês).
[]´s
Alexandre Santos (AlxSts)
gilbertosilverio
Usuário Nível 3
Usuário Nível 3
Mensagens: 339
Registrado em: 18 Jan 2009 10:39
Localização: Ribeirao Pires - SP

UPDATE de vários registros

Mensagem por gilbertosilverio »

Alexandre,

Obrigado pela resposta.

Ate entendi a logica, só que não consegui executa-la no Heid, você poderia 'DESENHAR' pra mim, por que não vai mesmo... kkkk

Ja pesquisei, li muito, mais sem UM DESENHO(exemplo simples), não consigo fazer


Grato.
GilbertoSilverio
gilbertosilverio@gmail.com
gilbertosilverio2003@yahoo.com.br
alxsts
Colaborador
Colaborador
Mensagens: 3092
Registrado em: 12 Ago 2008 15:50
Localização: São Paulo-SP-Brasil

UPDATE de vários registros

Mensagem por alxsts »

Olá!
STR(nQTDE,11)
ALLTRIM(nPRECO)
ALLTRIM(STR(MATA_GERAL[G,1],11))
Fica difícil "desenhar". Não sei de onde vem estes valores. Parece que você está percorrendo o array MATA_GERAL e atualizando a tabela.
Neste caso, teria que ser um a um mesmo. O UPDATE em massa se aplica a duas ou mais tabelas (vai pegar valores de uma e atualizar a segunda). No teu caso, só vejo uma tabela e os valores vem de variáveis de memória...
gilbertosilverio escreveu:so que demora um pouco,... [WHERE sku = ] + ALLTRIM(STR(MATA_GERAL[G,1],11)
Verifique na tua tabela se a coluna SKU tem índice. Se não tiver, crie um. 23000 registros é pouca coisa mas se não tiver índice, a cada UPDATE o SGBD vai ter que ler a tabela sequencialmente até encontrar o SKU desejado.

Para criar o índice, use o HaidiSQL.

Código: Selecionar todos

CREATE INDEX idx_sku ON agille54_api.tray_produtos (sku);
[]´s
Alexandre Santos (AlxSts)
gilbertosilverio
Usuário Nível 3
Usuário Nível 3
Mensagens: 339
Registrado em: 18 Jan 2009 10:39
Localização: Ribeirao Pires - SP

UPDATE de vários registros

Mensagem por gilbertosilverio »

Alexandre,

E isso mesmo, uso uma matriz por que pego valores de 5 filiais em DBF, e tenho que subir para o site estes valores.

Estava pensando em criar uma tabela no sql, INSERIR esses valores e ai mesclar com a que preciso subir.

Mais ai e minha duvida, como ficaria esse update?

tabela.temp = sku, qtde, preco

agille54.tray = sku, qtde, preco

Como ALTERAR os valores? eis a questão... kkkk

Por favor pode me dar um ideia de como seria.

Grato.
GilbertoSilverio
gilbertosilverio@gmail.com
gilbertosilverio2003@yahoo.com.br
alxsts
Colaborador
Colaborador
Mensagens: 3092
Registrado em: 12 Ago 2008 15:50
Localização: São Paulo-SP-Brasil

UPDATE de vários registros

Mensagem por alxsts »

Olá!

Supondo que as duas tabela tenham o mesmo layout:
sku
qtde
preco
atualizar ( 'SIM' ou 'NAO' )

tente assim:

Código: Selecionar todos

UPDATE agille54.tray t1 
INNER JOIN temp t2 
        ON (t1.sku = t2.sku)  
SET t1.qtde = t2.qtde, 
    t1.preco = t2.preco,
    t1.ATUALIZAR = CASE WHEN t2.atualizar = 'SIM' THEN 'ATUALIZAR' ELSE 'NAO ATUALIZAR' END;
Outra forma:

Código: Selecionar todos

UPDATE agille54.tray t1, temp t2
SET t1.qtde = t2.qtde, 
    t1.preco = t2.preco,
    t1.ATUALIZAR = CASE WHEN t2.atualizar = 'SIM' THEN 'ATUALIZAR' ELSE 'NAO ATUALIZAR' END;
WHERE t1.sku = t2.sku;
[]´s
Alexandre Santos (AlxSts)
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

UPDATE de vários registros

Mensagem por JoséQuintas »

gilbertosilverio escreveu:Estava pensando em criar uma tabela no sql, INSERIR esses valores e ai mesclar com a que preciso subir.
Mais ai e minha duvida, como ficaria esse update?
Sem complicar, eu faria assim:

Código: Selecionar todos

UPDATE .... AS A
INNER JOIN ( montagem da lista ) AS B ON A.CODIGO = B.CODIGO
SET A.SALDO = B.SALDO
Já tem exemplos aqui de como criar a lista.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
gilbertosilverio
Usuário Nível 3
Usuário Nível 3
Mensagens: 339
Registrado em: 18 Jan 2009 10:39
Localização: Ribeirao Pires - SP

UPDATE de vários registros

Mensagem por gilbertosilverio »

Alexandre, Quintas,

Muito obrigado, agora consegui enxergar...

Valeu...
GilbertoSilverio
gilbertosilverio@gmail.com
gilbertosilverio2003@yahoo.com.br
gilbertosilverio
Usuário Nível 3
Usuário Nível 3
Mensagens: 339
Registrado em: 18 Jan 2009 10:39
Localização: Ribeirao Pires - SP

UPDATE de vários registros

Mensagem por gilbertosilverio »

Olá Amigos,

Funcionou perfeitamente, um semana batendo cabeça, resolvido em segundos...

Criei um DBF temporário e subi os valores com uma rotina postada aqui do Quintas, onde ele INSERE dados de um DBF para o SQL, levou em media 16 segundos para subir os valores.

Código: Selecionar todos

...
   SELECT 0
   USE ( cTable ) ALIAS DbfDb

   cComplete :=DbfDb->(LASTREC())

   cSqlFix := "INSERT INTO " + cNewTable + " ( "
   FOR nCont = 1 TO FCount()
      cSqlFix += FieldName( nCont )
      IF nCont != FCount()
         cSqlFix += ", "
      ENDIF
   NEXT
   cSqlFix += " ) VALUES "
   cTxt := ""
Usei a rotina postada pelo Alexandre.

Código: Selecionar todos

UPDATE tray_produtos t1, tray_produtos_dbf t2
	SET t1.estoque = t2.estoque,
        t1.preco = t2.preco,
        t1.845890_processamentoPendente = t2.845890_processamentoPendente
	WHERE t1.sku = t2.sku AND t2.845890_processamentoPendente = 'ATUALIZAR' 
Pronto, tudo atualizado...

Novamente, Alexandre, Quintas, muito obrigado pela ajuda.

ps: Como dizia Chacrinha, neste mundo nada se cria tudo se copia... kkkkkk
GilbertoSilverio
gilbertosilverio@gmail.com
gilbertosilverio2003@yahoo.com.br
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

UPDATE de vários registros

Mensagem por JoséQuintas »

Ao invés disso, faz do jeito que comentei, não precisa arquivo temporário.

Código: Selecionar todos

USE (arquivoDBF) ALIAS temp
cLista := "SELECT " + Ltrim(Str(temp->Codigo)) + " AS CODIGO, " + Ltrim(Str( temp->Valor,16,2)) + " AS VALOR "
SKIP
DO WHILE ! Eof()
   cLista += " UNION ALL SELECT " + Ltrim(Str(temp->Codigo)) + ", " + Ltrim(Str( temp->Valor,16,2))
   SKIP
ENDDO
cSQL := "UPDATE tabela AS A" + ;
   " INNER JOIN (  "  + cLista + " ) AS B"
   " SET A.VALOR = B.VALOR"
cn:Execute( cSQL )
Assim a tabela é criada no próprio comando.

Mas esqueci de um detalhe: tem limite no comando, acho que é 4MB pra funcionar pelo terminal.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
alxsts
Colaborador
Colaborador
Mensagens: 3092
Registrado em: 12 Ago 2008 15:50
Localização: São Paulo-SP-Brasil

UPDATE de vários registros

Mensagem por alxsts »

Olá!

Independentemente da solução que adotar, penso que o índice que mencionei acima é importante.
[]´s
Alexandre Santos (AlxSts)
Responder