Jump to content
Fivewin Brasil

SQLRDD: UPDATE em vários registros, única query (Resolvido)


Ariston Santos

Recommended Posts

Olá, pessoal.

Tenho duas tabelas de estoque, uma local em DBF e outra em um servidor remoto em MySQL. Preciso periodicamente atualizar o campo ESTOQUEATUAL na tabela remota a partir do DBF local.

Ja tentei assim mas não funcinou:

UPDATE ITENS_DB SET ESTOQUEATUAL = 0.000 WHERE CODIGO = '0001',
                SET ESTOQUEATUAL = 7.000 WHERE CODIGO = '0002',
                SET ESTOQUEATUAL = 2.000 WHERE CODIGO = '0003',
                SET ESTOQUEATUAL = 5.000 WHERE CODIGO = '0004'

Assim também não vai:

UPDATE ITENS_DB SET ESTOQUEATUAL = 0.000 WHERE CODIGO = '0001';
UPDATE ITENS_DB SET ESTOQUEATUAL = 7.000 WHERE CODIGO = '0002';
UPDATE ITENS_DB SET ESTOQUEATUAL = 2.000 WHERE CODIGO = '0003';
UPDATE ITENS_DB SET ESTOQUEATUAL = 5.000 WHERE CODIGO = '0004'

Só funciona quando eu atualizo apenas um registro por vez, mas fica muito demorado. Preciso de um exemplo que faça a atualização de vários registros via query única. Tem como?

Agradeço desde já.

Link to comment
Share on other sites

Airston, o segundo exemplo era pra funcionar. Como voce está executando e que erro esta retornando? Eu não conheço MYSQL mas primeiro faça funcionar o seu comando no equivalente ao QUERY ANALIZER do SQL SERVER.

Fazendo funcionar o comando lá ai é só adaptar o codigo abaixo.

Tente assim:

cComando := "UPDATE ITENS_DB SET ESTOQUEATUAL = 0.000 WHERE CODIGO = '0001' "+Chr(13)+Chr(10)
cComando += "UPDATE ITENS_DB SET ESTOQUEATUAL = 7.000 WHERE CODIGO = '0002' "+Chr(13)+Chr(10)
cComando += "UPDATE ITENS_DB SET ESTOQUEATUAL = 2.000 WHERE CODIGO = '0003' "+Chr(13)+Chr(10)
cComando += "UPDATE ITENS_DB SET ESTOQUEATUAL = 5.000 WHERE CODIGO = '0004' "+Chr(13)+Chr(10)

SR_GetConnection():exec(cComando)

SR_GetConnection():Commit()

Olá, pessoal.

Tenho duas tabelas de estoque, uma local em DBF e outra em um servidor remoto em MySQL. Preciso periodicamente atualizar o campo ESTOQUEATUAL na tabela remota a partir do DBF local.

Ja tentei assim mas não funcinou:

UPDATE ITENS_DB SET ESTOQUEATUAL = 0.000 WHERE CODIGO = '0001',
                SET ESTOQUEATUAL = 7.000 WHERE CODIGO = '0002',
                SET ESTOQUEATUAL = 2.000 WHERE CODIGO = '0003',
                SET ESTOQUEATUAL = 5.000 WHERE CODIGO = '0004'

Assim também não vai:

UPDATE ITENS_DB SET ESTOQUEATUAL = 0.000 WHERE CODIGO = '0001';
UPDATE ITENS_DB SET ESTOQUEATUAL = 7.000 WHERE CODIGO = '0002';
UPDATE ITENS_DB SET ESTOQUEATUAL = 2.000 WHERE CODIGO = '0003';
UPDATE ITENS_DB SET ESTOQUEATUAL = 5.000 WHERE CODIGO = '0004'

Só funciona quando eu atualizo apenas um registro por vez, mas fica muito demorado. Preciso de um exemplo que faça a atualização de vários registros via query única. Tem como?

Agradeço desde já.

Link to comment
Share on other sites

Ariston,

Segue a idéia

// Aqui você começa o loop no teu dbf. No meu caso foi em um arquivo texto.

      if cSituaope="Crédito Enviado"
         cSitContrato:="AGUARDANDO LIBERAÇÃO PARA PAGAMENTO"
      elseif cSituaope="Cancelada"
         cSitContrato:="CANCELADA"
      else
         cSitContrato:="EM ANÁLISE"
      endif
      cCpf:=strtran(aReg[10],".","")
      cCpf:=strtran(cCpf,"-")
      
      aAdd(aDadosTXT,"("+Any2Sql( cCodLoja )+","+;
                         Any2Sql( upper(alltrim(aReg[8])) )+","+;
                         Any2Sql( alltrim(aReg[3]) )+","+;
                         Any2Sql( aReg[37] )+","+;
                         Any2Sql( alltrim(aReg[31]) )+","+;
                         Any2Sql( alltrim(cNumope))+","+;
                         Any2Sql( cMatFunc )+","+;
                         Any2Sql( cFisico )+","+;
                         if(empty(cNumope),"1","0")+","+;
                         Any2Sql( aReg[7] )+","+;
                         Any2Sql( date() )+","+;
                         Any2Sql( cTipopag )+","+;
                         Any2Sql( alltrim(cCpf) )+","+;
                         Any2Sql( cTipoCorretor )+","+;
                         Any2Sql( cSitContrato )+")")
...
...
Depois do loop faço assim:

   if !empty(aDadosTXT)
      cSql:="INSERT INTO tab_prot (cod_loja,nome_cliente,cod_convenio,valor,ade,contrato,"+;
		      "mat_func,fisico,cod_produto,usuario,dtcada,tipoconta,cpf,tipocorretor,statusconsig) VALUES "
      for nI:=1 to len(aDadosTXT)
          cSql+=aDadosTXT[nI]+","
      next
// Apagar última virgula
      cSql:=substr(cSql,1,len(cSql)-1)
      
      Begin Transaction
      SQL Execute cSql
      IF SQL_ErrorNO() > 0
         SQLRollBack()
         End Transaction
         MsgInfo( "Informe esta mensagem ao suporte : "+CRLF+;
                  SQLErrorMsg(),"ATENÇÃO" )
      ENDIF
      End Transaction
   
      SQL EXECUTE "COMMIT" // Para gravar as atualzações no banco
   endif   

Lembrando que faço isto usando SQLLIB, mas a idéia é a mesma, ou seja, neste caso executo um único INSERT ou poderia ser um UPDATE com todas as linhas que preciso.

Espero que sirva.

Link to comment
Share on other sites

kleyber

Obrigado, mas não serve. Para INSERT eu ja tenho uma rotina que está funcinando corretamente. Já consigo inserir quantos registros novos que quiser enviando apenas uma query para o BD.

O que preciso para o momento é de um exemplo para UPDATE. O motivo é que são vários registros no banco de dados. Alterar um a um via internet fica muito lento. Por isso surgiu a idéia de enviar os itens por blocos de 100. Assim, em uma tabela com mil itens, eu enviaria dez queries com 100 itens cada uma.

Até um momento não consegui isso usando a SQLRDD, comandos em sql puro. Optei por enviar um a um até que surja uma dica funcional.

Por enquanto, obrigado a todos pelo esforço em ajudar.

Link to comment
Share on other sites

Ariston, pelo que sei, não dá para atualizar registros diferentes, aplicando informações diferentes em um mesmo campo, com condições diferentes

ou seja, tem que atualizar "1 a 1" mesmo.

O que torna esse tipo de atualização mais rápida, é abrir um TRANSACTION, para não ficar comitando a cada UPDATE realizado, isso dá uma GRAAANDE diferença dependendo a quantia de UPDATES enviados.

Link to comment
Share on other sites

Ariston, de onde vem estes "CODIGO = '0001'", isto é um sequencial, de onde voce pega este '0001'.

Vem da tabela ITENS_DB, campo CODIGO. Antes de fazer o update, eu pego os itens cadastrados na tabela online em um vetor (via SELECT). Atualizo o estoque no vetor com base no DBF local, e quero dar um UPDATE na tabela online de todos os itens do vetor.

Acho que você não entendeu. Basta mudar o INSERT por UPDATE que iria funcionar. Mas blz, de qualquer forma tentei algo.

Vou testar isso. Se funcionar, aviso.

Ariston, pelo que sei, não dá para atualizar registros diferentes, aplicando informações diferentes em um mesmo campo, com condições diferentes, ou seja, tem que atualizar "1 a 1" mesmo. O que torna esse tipo de atualização mais rápida, é abrir um TRANSACTION, para não ficar comitando a cada UPDATE realizado, isso dá uma GRAAANDE diferença dependendo a quantia de UPDATES enviados.

O Kleyber afima asima que apenas trocando o INSERT por UPDATE dá sim.

De qualquer forma, já estou usando BEGIN e END TRANSCTION - SR_BeginTransaction() e SR_CommitTransaction(). Realmente fica bem mais rápido, mas ainda poderia melhorar.

Obrigado a todos.

Link to comment
Share on other sites

Ariston, a única forma que enxergo para fazer isso com apenas um comando, seria como o exemplo abaixo.

UPDATE ITENS_DB SET ESTOQUEATUAL = CASE CODIGO
                                      WHEN '0001' THEN 0.000
                                      WHEN '0002' THEN 7.000
                                      WHEN '0003' THEN 2.000
                                      WHEN '0004' THEN 5.000
                                   END
WHERE CODIGO IN ('0001','0002','0003','0004');

Fazer isso em um LOOP é fácil, mas dependendo o número de dados, pode haver problemas no fivewin, com o tamanho da string

ou pode haver problema no banco de dados, com o tamanho do pacote enviado, então seria bom que você tivesse um limite de códigos a atualizar de uma única vez, para não haver nenhum dos 2 problemas citados.

Link to comment
Share on other sites

Ariston, sugiro vc faça uma pesquisa sobre como criar um "function no banco de dados", assim vc passa os dados como parâmetros para banco de dados em uma única chamada e internamente o banco faz a atualização (vários update), fica rápido e não consome banda.

delimiter $$
create function upd_variosReg(p1 varchar,p2 varchar) returns bool
BEGIN
UPDATE ITENS_DB SET ESTOQUEATUAL = 0.000 WHERE CODIGO = p1;

UPDATE ITENS_DB SET ESTOQUEATUAL = 7.000 WHERE CODIGO = p2;
UPDATE ITENS_DB SET ESTOQUEATUAL = 2.000 WHERE CODIGO = p3;
UPDATE ITENS_DB SET ESTOQUEATUAL = 5.000 WHERE CODIGO = p4;

return true;
END $$
delimiter ;
no seu prg
func main
cmdSql := "Call upd_variosReg("0001","002",....);"
Link to comment
Share on other sites

UPDATE ITENS_DB SET ESTOQUEATUAL = CASE CODIGO

WHEN '0001' THEN 0.000

WHEN '0002' THEN 7.000

WHEN '0003' THEN 2.000

WHEN '0004' THEN 5.000

END

WHERE CODIGO IN ('0001','0002','0003','0004');

Perfeito. Funcionou. Era exatamente isso que eu queria.

ISSO É QUE FORUM!!

Obrigado a todos.

Link to comment
Share on other sites

Oi Emotta, na verdade o WHEN é uma instrução do comando CASE.

Daria pra fazer com IF´s, mas o código ficaria meio poluído ........ e funciona em SQL Server sim. ^^

Uma dica pra quem está em casa e não tem sql server, mysql, oracle instalado, é usar o sqlfiddle

é um site que você pode simular uma base de dados em qualquer uma dessas linguagens, entre outras...... tem até um botãozinho Donate pra quem animar, hehehe

http://sqlfiddle.com/

Link to comment
Share on other sites

Fantastico... obrigado !

Oi Emotta, na verdade o WHEN é uma instrução do comando CASE.

Daria pra fazer com IF´s, mas o código ficaria meio poluído ........ e funciona em SQL Server sim. ^^

Uma dica pra quem está em casa e não tem sql server, mysql, oracle instalado, é usar o sqlfiddle

é um site que você pode simular uma base de dados em qualquer uma dessas linguagens, entre outras...... tem até um botãozinho Donate pra quem animar, hehehe

http://sqlfiddle.com/

Link to comment
Share on other sites

  • 3 years later...

Boa tarde Ariston Santos,

estava com o mesmo problema e tentei utilizar o WHEN, porem não meu caso não funcionou, pois estava usando 15 digitos e estourou o limite do INT.
Resolvi o caso da seguinte forma.

UPDATE ITENS_DB SET ESTOQUEATUAL = 0.000 WHERE CODIGO = '0001';
UPDATE ITENS_DB SET ESTOQUEATUAL = 7.000 WHERE CODIGO = '0002';
UPDATE ITENS_DB SET ESTOQUEATUAL = 2.000 WHERE CODIGO = '0003';
UPDATE ITENS_DB SET ESTOQUEATUAL = 5.000 WHERE CODIGO = '0004';

Utilizando todos os pontos e virgulas no final (;) é exibido a mensagem de apenas 1 Update (apenas 1 comando), porem ao realizar o select, todos os registros foram atualizados.
Testei no POSTGRE e funcionou, faça o teste por gentileza.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
×
×
  • Create New...