Clipper On Line • Ver Tópico - UPDATE de vários registros

UPDATE de vários registros

Discussão sobre SQL

Moderador: Moderadores

 

UPDATE de vários registros

Mensagempor gilbertosilverio » 14 Jul 2021 07:11

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?


              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
Usuário Nível 3

Usuário Nível 3
 
Mensagens: 332
Data de registro: 18 Jan 2009 09:39
Cidade/Estado: Ribeirao Pires - SP
Curtiu: 1 vez
Mens.Curtidas: 23 vezes

UPDATE de vários registros

Mensagempor alxsts » 14 Jul 2021 09:42

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)
alxsts
Colaborador

Colaborador
 
Mensagens: 2945
Data de registro: 12 Ago 2008 15:50
Cidade/Estado: São Paulo-SP-Brasil
Curtiu: 21 vezes
Mens.Curtidas: 248 vezes

UPDATE de vários registros

Mensagempor gilbertosilverio » 14 Jul 2021 10:22

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
Usuário Nível 3

Usuário Nível 3
 
Mensagens: 332
Data de registro: 18 Jan 2009 09:39
Cidade/Estado: Ribeirao Pires - SP
Curtiu: 1 vez
Mens.Curtidas: 23 vezes

UPDATE de vários registros

Mensagempor alxsts » 14 Jul 2021 10:49

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.
CREATE INDEX idx_sku ON agille54_api.tray_produtos (sku);
[]´s
Alexandre Santos (AlxSts)
alxsts
Colaborador

Colaborador
 
Mensagens: 2945
Data de registro: 12 Ago 2008 15:50
Cidade/Estado: São Paulo-SP-Brasil
Curtiu: 21 vezes
Mens.Curtidas: 248 vezes

UPDATE de vários registros

Mensagempor gilbertosilverio » 14 Jul 2021 11:16

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
Usuário Nível 3

Usuário Nível 3
 
Mensagens: 332
Data de registro: 18 Jan 2009 09:39
Cidade/Estado: Ribeirao Pires - SP
Curtiu: 1 vez
Mens.Curtidas: 23 vezes

UPDATE de vários registros

Mensagempor alxsts » 14 Jul 2021 11:59

Olá!

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

tente assim:
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:
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)
alxsts
Colaborador

Colaborador
 
Mensagens: 2945
Data de registro: 12 Ago 2008 15:50
Cidade/Estado: São Paulo-SP-Brasil
Curtiu: 21 vezes
Mens.Curtidas: 248 vezes

UPDATE de vários registros

Mensagempor JoséQuintas » 14 Jul 2021 12:05

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:

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, multithread, dbfcdx, ADO+MySql, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18150
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1215 vezes

UPDATE de vários registros

Mensagempor gilbertosilverio » 14 Jul 2021 12:31

Alexandre, Quintas,

Muito obrigado, agora consegui enxergar...

Valeu...
gilbertosilverio
Usuário Nível 3

Usuário Nível 3
 
Mensagens: 332
Data de registro: 18 Jan 2009 09:39
Cidade/Estado: Ribeirao Pires - SP
Curtiu: 1 vez
Mens.Curtidas: 23 vezes

UPDATE de vários registros

Mensagempor gilbertosilverio » 14 Jul 2021 13:07

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.

...
   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.

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
Usuário Nível 3

Usuário Nível 3
 
Mensagens: 332
Data de registro: 18 Jan 2009 09:39
Cidade/Estado: Ribeirao Pires - SP
Curtiu: 1 vez
Mens.Curtidas: 23 vezes

UPDATE de vários registros

Mensagempor JoséQuintas » 14 Jul 2021 15:12

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

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, multithread, dbfcdx, ADO+MySql, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18150
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1215 vezes

UPDATE de vários registros

Mensagempor alxsts » 14 Jul 2021 16:52

Olá!

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

Colaborador
 
Mensagens: 2945
Data de registro: 12 Ago 2008 15:50
Cidade/Estado: São Paulo-SP-Brasil
Curtiu: 21 vezes
Mens.Curtidas: 248 vezes




Retornar para SQL

Quem está online

Usuários vendo este fórum: Nenhum usuário registrado online e 8 visitantes


Ola Amigo, espero que meu site e forum tem lhe beneficiado, com exemplos e dicas de programacao.
Entao divulgue o link da Doacao abaixo para seus amigos e redes sociais ou faça uma doacao para o site forum...
MUITO OBRIGADO PELA SUA DOACAO!
Faça uma doação para o forum
cron
v
Olá visitante, seja bem-vindo ao Fórum Clipper On Line!
Efetue o seu login ou faça o seu Registro