Carga do DBF para MySql/Postgres e LetoDbf juntos!

Forum sobre SQL.

Moderador: Moderadores

Avatar do usuário
Itamar M. Lins Jr.
Administrador
Administrador
Mensagens: 7928
Registrado em: 30 Mai 2007 11:31
Localização: Ilheus Bahia
Curtiu: 1 vez

Carga do DBF para MySql/Postgres e LetoDbf juntos!

Mensagem por Itamar M. Lins Jr. »

Olá!
Fiz aqui, uns testes... pegando o macete VALUES (), (), () tava colocando VALUES (), VALUES ()...
Pego de 10 em 10 registros, por vez.
Ai tem o campo id autoincrement, talvez desligue pq não usei assim no DBF.
O campo data que criei NOT NULL, aceita criar mas em compensação não grava nada kkkkk, Não aceita NULL quando a data é 0000-00-00.

Código: Selecionar todos

   AbreDb('colaboradores.dbf','co',.t.)
   co->(dbGoTop())
   nCampos := co->(FCount())
   cFields := ''
   aValues := {}
   
   FOR nCount := 1 TO nCampos
      IF Lower(Field(nCount)) = 'idcolabora'
      ELSE
         cFields += co->(Field(nCount)) + iif(nCount==nCampos,'',",")      
      ENDIF
   NEXT
   
   cDados := "" ; cSql := "" ; nReg := 0 ; lUma := .T.
   DO WHILE co->(!Eof())            
      
      FOR nCount:=1 TO nCampos
         xField := co->(FieldGet(nCount))

         DO CASE 
            CASE ValType(xField) = 'C'                  
                  xValue := "'"+AllTrim(xField)+"'"
            CASE ValType(xField) = 'N'
               IF Lower(Field(nCount)) = 'idcolabora'
                  loop
               ELSE
                  xValue := "'"+hb_ntoc(xField)+"'"
               ENDIF
            CASE ValType(xField) = 'D'
               IF Empty(xField)
                  xValue := 'NULL'
               ELSE
                  xValue := "'"+hb_DToC(xField,'YYYY-MM-DD')+"'"
               ENDIF
         ENDCASE
         cDados += xValue + iif(nCount==nCampos,'',",")      
      NEXT
      
      co->(dbSkip())
      
      IF ++nReg <= 10
         cSQL += iif(lUma,"values ",", ") + "(" + cDados + ")" + iif(co->(Eof()),";","")
         cDados := "" ; lUma := .F.
      ENDIF
      
      IF co->(Eof()) .OR. nReg == 10
         cSQLFinal := "INSERT INTO colaboradores (" + cFields + ") " + cSQL  
         IF rddInfo( RDDI_EXECUTE, cSQLFinal )  
            Hwg_MsgInfo("Dados adicionados.")
         ELSE
            Hwg_MsgInfo("Falha adicionando dados.")
         ENDIF       
         nReg := 0
      ENDIF
   ENDDO
Rodando leve os dois.
Quem tem seus DBFs e quer colocar na NUVEM e migrar/ usar junto com SQL.
Colocando aqui no forum como marcação de aprendizado pra mim mesmo.

Saudações,
Itamar M. Lins Jr.
Saudações,
Itamar M. Lins Jr.
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Carga do DBF para MySql/Postgres e LetoDbf juntos!

Mensagem por JoséQuintas »

Não entendi nada.

Opção 1: gerar arquivo texto pra ser usado por outro programa
Opção 2: fazer direto

É só pra dar idéia

Código: Selecionar todos

/*
ZE_SQLFROMDBF - Transfere de DBF pra SQL incluindo ou não
José Quintas
*/

#include "inkey.ch"
#include "dbstruct.ch"
#include "josequintas.ch"
#include "ze_adoclass.ch"

FUNCTION SQLFromDbf()

   LOCAL oFiles, nCont, acAchoice := {}, cFileDbf, nOpc := 1, cConfirma := "NAO", GetList := {}

   @ 2, 1 SAY "ATENÇÃO"
   @ Row() + 1, 1 SAY "Os dados dos DBFs são salvos no SQL."
   @ Row() + 1, 1 SAY "Se quiser eliminar dados anteriores do SQL, precisa fazer manualmente"
   @ Row() + 1, 1 SAY "Se quiser eliminar dados finais do DBF, precisa fazer manualmente"

   oFiles := CnfDbfInd()
   FOR nCont = 1 TO Len( oFiles )
      AAdd( acAchoice, oFiles[ nCont, 1 ] )
   NEXT
   DO WHILE .T.
      wAchoice( Row() + 1, 5, acAchoice, @nOpc, "Arquivos a transferir" )
      IF LastKey() == K_ESC
         EXIT
      ENDIF
      cFileDbf := Upper( oFiles[ nOpc, 1 ] )
      Mensagem( "Confirme criar estrutura para " + cFileDbf )
      @ Row(), Col() + 2 GET cConfirma PICTURE "@!"
      READ
      Mensagem()
      IF LastKey() == K_ESC .OR. cConfirma != "SIM"
         LOOP
      ENDIF
      CopyDbfToSQL( cFileDbf, .F., .T., .F., cFileDbf )
   ENDDO

   RETURN Nil

FUNCTION CopyDbfToSQL( cTable, lTransfere, lCria, lZera, cNewTable )

   LOCAL oStru
   LOCAL cSQL, xValue, nCont, cSQLFix
   LOCAL lBegin := .T., cTxt, cKeyName
   LOCAL cnGERAL := ADOLocal()
   LOCAL nSelect := Select()

   IF ! File( cTable + iif( ".DBF" $ Upper( cTable ), "", ".DBF" ) )
      RETURN Nil
   ENDIF
   hb_Default( @lCria, .F. )
   hb_Default( @lZera, .F. )
   hb_Default( @cNewTable, cTable )
   cTable      := Upper( cTable )
   SELECT 0
   USE ( cTable ) ALIAS thisdbf
   oStru    := dbStruct()
   cKeyName := "ID" + iif( Left( cTable, 2 ) $ "JP,HL", Substr( cTable, 3 ), cTable )
   USE
   cSQL := "CREATE TABLE IF NOT EXISTS " + cNewTable + " ( " + cKeyName + " INT(9) NOT NULL AUTO_INCREMENT, "
   FOR nCont = 1 TO Len( oStru )
      IF oStru[ nCont, DBS_NAME ] != cKeyName
         cSQL += oStru[ nCont, DBS_NAME ] + " "
         DO CASE
         CASE oStru[ nCont, DBS_TYPE ] == "N"
            IF oStru[ nCont, DBS_DEC ] == 0
               cSQL += " INT( " + Ltrim( Str( oStru[ nCont, DBS_LEN ] ) ) + " ) DEFAULT 0"
            ELSE
               cSQL += " DECIMAL( " + Ltrim( Str( oStru[ nCont, DBS_LEN ] ) ) + " , " + Ltrim( Str( oStru[ nCont, DBS_DEC ] ) ) + " ) DEFAULT 0"
            ENDIF
         CASE oStru[ nCont, DBS_TYPE ] == "C"
            IF oStru[ nCont, DBS_LEN ] < 250
               cSQL += " VARCHAR( " + Ltrim( Str( oStru[ nCont, DBS_LEN ] ) ) + " ) DEFAULT '' "
            ELSE
               cSQL += " TEXT"
            ENDIF
         CASE oStru[ nCont, DBS_TYPE ] == "D"
            cSQL += " DATE " // DEFAULT '0000-00-00'"
         CASE oStru[ nCont, DBS_TYPE ] == "M"
            cSQL += " TEXT "
         ENDCASE
         cSQL += " , "
      ENDIF
   NEXT
   cSQL += " PRIMARY KEY ( " + cKeyName + " )"
   cSQL += " )"
   cSQL += ";"
   SayScroll( "Salvando no SQL." + cTable )
   IF lCria
      cnGERAL:ExecuteNoReturn( cSQL )
   ENDIF
   IF lZera
      cnGERAL:ExecuteNoReturn( "TRUNCATE TABLE " + cNewTable )
   ENDIF
   IF ! lTransfere
      SELECT ( nSelect )
      RETURN Nil
   ENDIF
   SELECT 0
   USE ( cTable ) ALIAS thisdbf
   GrafTempo( "Processando " + cTable )
   cSQLFix := "INSERT INTO " + cNewTable + " ( "
   FOR nCont = 1 TO FCount()
      cSQLFix += FieldName( nCont )
      IF nCont != FCount()
         cSQLFix += ", "
      ENDIF
   NEXT
   cSQLFix += " ) VALUES "
   cTxt := ""
   DO WHILE ! Eof()
      GrafTempo( RecNo(), LastRec() )
      Inkey()
      cSQL := "( "
      FOR nCont = 1 TO FCount()
         xValue := FieldGet( nCont )
         DO CASE
         CASE ValType( xValue ) == "N"
            cSQL += NumberSQL( xValue )
         CASE ValType( xValue ) == "D"
            cSQL += DateSQL( xValue )
         CASE ValType( xValue ) == "C"
            xValue := SQLValidString( xValue )
            cSQL += StringSQL( xValue )
         OTHERWISE
            cSQL += "NULL"
         ENDCASE
         IF nCont != FCount()
            cSQL += ","
         ENDIF
      NEXT
      cSQL += " )"
      IF Len( cTxt ) == 0
         cTxt += cSQLFix
         lBegin := .T.
      ENDIF
      IF ! lBegin
         cTxt += ", "
      ENDIF
      lBegin := .F.
      cTxt += cSQL
      IF Len( cTxt ) > SQL_CMD_MAXSIZE
         cnGERAL:ExecuteNoReturn( cTxt )
         cTxt := ""
      ENDIF
      SKIP
   ENDDO
   IF Len( cTxt ) != 0
      cnGERAL:ExecuteNoReturn( cTxt )
   ENDIF
   USE
   SELECT ( nSelect )

   RETURN Nil

FUNCTION CopyRecordToSQL( cDatabase, cChaveAcesso )

   LOCAL nCont, lInsert := .T., cnSQL := ADOLocal()

   IF cChaveAcesso != Nil
      lInsert := ( ADORecCount( cDatabase, cChaveAcesso ) == 0 )
   ENDIF
   WITH OBJECT cnSQL
      :QueryCreate()
      FOR nCont = 1 TO FCount()
         :QueryAdd( FieldName( nCont ), FieldGet( nCont ) )
      NEXT
      IF lInsert
         :QueryExecuteInsert( cDatabase )
      ELSE
         :QueryExecuteUpdate( cDatabase, cChaveAcesso )
      ENDIF
   ENDWITH

   RETURN Nil

STATIC FUNCTION SQLValidString( xValue )

   xValue := StrTran( xValue, Chr(91),  " " )
   xValue := StrTran( xValue, Chr(93),  " " )
   xValue := StrTran( xValue, Chr(167), " " )
   xValue := StrTran( xValue, Chr(128), "C" )
   xValue := StrTran( xValue, Chr(135), "C" )
   xValue := StrTran( xValue, Chr(166), "A" )
   xValue := StrTran( xValue, Chr(198), "A" )
   xValue := StrTran( xValue, Chr(0),   "" )
   //xValue := StrTran( xValue, Chr(95),  "-" ) // usada em email barra inferior
   xValue := StrTran( xValue, Chr(229), "O" )
   xValue := StrTran( xValue, Chr(124), " " )
   xValue := StrTran( xValue, Chr(141), " " )
   xValue := StrTran( xValue, Chr(181), " " )
   xValue := StrTran( xValue, Chr(162), " " )
   xValue := StrTran( xValue, Chr(224), " " )
   xValue := StrTran( xValue, Chr(133), " " )
   xValue := StrTran( xValue, Chr(144), "E" )
   xValue := StrTran( xValue, Chr(160), " " )

   RETURN xValue
Crio tabela com campo autoincrement usando as iniciais da tabela.
Gravo tudo do dbf como está.
Tem otimização, porque gravar de 1 em 1 demora demais.
Nem todo caractere é aceito diretamente no MySQL.

Usei no começo, já faz muito tempo, dentro do aplicativo, pode depender de funções do aplicativo.
Mas é só pra dar uma idéia.

QueryCreate() é algo como aList := {}
QueryAdd() é algo como AAdd( aList, { nome, valor } )
QueryExecutexxx() é o que usa a lista pra criar o comando insert ou update, e já converte o valor conforme o tipo.
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/
Avatar do usuário
Itamar M. Lins Jr.
Administrador
Administrador
Mensagens: 7928
Registrado em: 30 Mai 2007 11:31
Localização: Ilheus Bahia
Curtiu: 1 vez

Carga do DBF para MySql/Postgres e LetoDbf juntos!

Mensagem por Itamar M. Lins Jr. »

Olá!
Não entendi nada.
Não tem nada aqui no meu CPU, está o DBF e Mysql sendo acessado por IP.
A sentença:

Código: Selecionar todos

INSERT INTO colaboradores (COLABORA,ENDERECO,BAIRRO,CIDADE,UF,CEP..) values ('ITAMAR'...etc), (mais outro reg...), (Mais outro reg.Sem precisar da palavra values...)
Estava colocando values (...), values (...)

Saudações,
Itamar M. Lins Jr.
Saudações,
Itamar M. Lins Jr.
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Carga do DBF para MySql/Postgres e LetoDbf juntos!

Mensagem por JoséQuintas »

Entendi.
Pode ser:

Código: Selecionar todos

INSERT INTO tabela ( colunas ) VALUES valoes, ( colunas ) VALUES valores
Mas isso seria gastar mais texto/tempo.

Também pode ser:

Código: Selecionar todos

INSERT INTO tabela VALUES ( valores )
Mas isso obriga a colocar os campos exatos da tabela, na mesma sequência definida na estrutura.

Colocando os valores, exceto do campo incremental, o campo incremental vai sendo numerado automático.

TRUNCATE antes zera tudo, e zera a contagem do campo incremental, pra recomeçar no 1, senão vai sempre o definido na tabela +1, mesmo que esteja vazio.

Pra Postgres não sei se vale a mesma coisa, nunca mexi.

Um erro que cometi no começo foi criar campo DOUBLE, ele é binário, e tem os problemas de arredondamento tradicionais.
DECIMAL ou NUMERIC ou CURRENCY (pra dinheiro) seguem o estilo do DBF pra não ter problema de arredondamento.
Mudar depois complica um pouqinho, porque mudar estrutura não altera o conteúdo, pode até dar erro do valor não poder ser gravado - justamente pelo erro de representação, 1.5 pode ser 1.4999999999999999999999
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/
Avatar do usuário
Itamar M. Lins Jr.
Administrador
Administrador
Mensagens: 7928
Registrado em: 30 Mai 2007 11:31
Localização: Ilheus Bahia
Curtiu: 1 vez

Carga do DBF para MySql/Postgres e LetoDbf juntos!

Mensagem por Itamar M. Lins Jr. »

Olá!
Outro detalhe! Se sobrar tempo vou fazer uns testes com Hwgui e LetoDBf, mais o Mysql, no desktop Linux ;-)
Quero ver a performance, a diferença de um e outro. Windows x Linux acessando base de dados no VPS.

Saudações,
Itamar M. Lins Jr.
Saudações,
Itamar M. Lins Jr.
Avatar do usuário
Itamar M. Lins Jr.
Administrador
Administrador
Mensagens: 7928
Registrado em: 30 Mai 2007 11:31
Localização: Ilheus Bahia
Curtiu: 1 vez

Carga do DBF para MySql/Postgres e LetoDbf juntos!

Mensagem por Itamar M. Lins Jr. »

Olá!
Mas isso obriga a colocar os campos exatos da tabela, na mesma sequência definida na estrutura.
Tá postado aqui, o trecho (função) que faz isso.
Peguei de 10 em 10, nesse DBF que só tem 5 registros.
Depois vou testar com um DBF maior e criar a estrutura na mesma ordem que será incluída.
E tem outra forma diferente ? A criação da estrutura(dbcreat()) da tabela em SQL ?

Saudações,
Itamar M. Lins Jr.
Saudações,
Itamar M. Lins Jr.
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Carga do DBF para MySql/Postgres e LetoDbf juntos!

Mensagem por JoséQuintas »

Itamar M. Lins Jr. escreveu:E tem outra forma diferente ? A criação da estrutura(dbcreat()) da tabela em SQL ?
Sim, por comando SQL.
A rotina que postei cria estrutura e índice, usando um campo adicional incremental.
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/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Carga do DBF para MySql/Postgres e LetoDbf juntos!

Mensagem por JoséQuintas »

Uso pra fazer backup, não sei como vai fazer isso no SQLMIX:

Código: Selecionar todos

SHOW CREATE TABLE nometabela
O nome do campo é "create table"

Também tem:

Código: Selecionar todos

SHOW CREATE FUNCTION xxxx
SHOW CREATE PROCDURE xxxx
O nome do campo é "create function" ou "create procedure"

Eles retornam o comando equivalente pra criação.

Pelo HeidiSQL dá pra ver também, é uma das abas da tabela.
.
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/
Avatar do usuário
Itamar M. Lins Jr.
Administrador
Administrador
Mensagens: 7928
Registrado em: 30 Mai 2007 11:31
Localização: Ilheus Bahia
Curtiu: 1 vez

Carga do DBF para MySql/Postgres e LetoDbf juntos!

Mensagem por Itamar M. Lins Jr. »

Olá!
Não sei! Bom! Vendo aqui como é.

Saudações,
Itamar M. Lins Jr.
Saudações,
Itamar M. Lins Jr.
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Carga do DBF para MySql/Postgres e LetoDbf juntos!

Mensagem por JoséQuintas »

No SQLMIX talvez dbStruct(), mas não vai ser cópia exata do servidor.
No HeidiSQL:
test1.png
Apesar de aparecer entre apóstofres, não faz falta, a não ser se o nome fosse reservado.

Ainda vai poder executar o comando de criação normalmente.
Apesar de poder usar dbCreate()

E pode não ser igual em todo banco de dados.

Nota: HEIDISQL é direto, é um utilitário, não tem nada a ver com ADO.
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/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Carga do DBF para MySql/Postgres e LetoDbf juntos!

Mensagem por JoséQuintas »

Aqui SQLite, abri o banco de dados do MediaMonkey, tocador de música.
Bem parecido pra criar tabela.
sqlite2.png
E é um banco cheio de tabelas, campos, e relacionamentos.
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/
Avatar do usuário
Itamar M. Lins Jr.
Administrador
Administrador
Mensagens: 7928
Registrado em: 30 Mai 2007 11:31
Localização: Ilheus Bahia
Curtiu: 1 vez

Carga do DBF para MySql/Postgres e LetoDbf juntos!

Mensagem por Itamar M. Lins Jr. »

Olá!
No SQLMIX talvez dbStruct(), mas não vai ser cópia exata do servidor.
Essa parte vai de boa. Não tem problema.
Só quando o resultado não é uma QUERY, é uma string... Deve ter... vou testar com tempo.
Qualquer comando de INPUT acredito que irá funcionar. O problema é saber quais são e o retorno. Pq pode ser apenas .T. ou .F. o retorno.

Saudações,
Itamar M. Lins Jr.
Saudações,
Itamar M. Lins Jr.
Fernando queiroz
Usuário Nível 4
Usuário Nível 4
Mensagens: 779
Registrado em: 13 Nov 2014 00:41
Localização: Porto Alegre/RS

Carga do DBF para MySql/Postgres e LetoDbf juntos!

Mensagem por Fernando queiroz »

Itamar M. Lins Jr. escreveu:Olá!
No SQLMIX talvez dbStruct(), mas não vai ser cópia exata do servidor.
Essa parte vai de boa. Não tem problema.
Só quando o resultado não é uma QUERY, é uma string... Deve ter... vou testar com tempo.
Qualquer comando de INPUT acredito que irá funcionar. O problema é saber quais são e o retorno. Pq pode ser apenas .T. ou .F. o retorno.

Saudações,
Itamar M. Lins Jr.
No caso de campos no DBF .T. ou .F. use o tipo tinyint e grave 0=.T. 1=.F.
se tiver duvidas nessa conversão eu tenho um programinha que usei para fazer isso por aqui que da uma boa ideia, meio antigo mas com os novos conhecimentos posso dar dicas de como melhorar
HARBOUR 3.2, HWGUI 2.23 B3, SEFAZCLASS, PDFClass, ADO + MariaDB/MySQL, RMChart
Responder