Clipper On Line • Ver Tópico - Dividindo tabelas

Dividindo tabelas

Discussão sobre Banco de Dados e RDDs para Clipper/[x]Harbour.

Moderador: Moderadores

 

Dividindo tabelas

Mensagempor JoséQuintas » 01 Set 2020 12:01

Estou no início de eliminar minha multitabela.
Por enquanto pensei em separar o que se refere a legislação, e o resto.
E não é que tem tabela de lei demais.

aux2.png


aux1.png


São só algumas, por enquanto.
Ainda decidindo se faço assim mesmo.
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: 18155
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1215 vezes

Dividindo tabelas

Mensagempor JoséQuintas » 01 Set 2020 18:14

Isso não deu certo.
É um tal de digitar AUX aonde é LEI, e LEI aonde é AUX, e isso não dá pro compilador conferir.
Ainda bem que precisei criar algumas rotinas, e descobri isso antes de terminar tudo.

Tem essa também... na alteração não vemos problema, mas na hora de criar rotina nova... aí que o bicho pega.
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: 18155
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1215 vezes

Dividindo tabelas

Mensagempor JoséQuintas » 02 Set 2020 16:40

Ainda não gostei, ficou tudo no início poluindo a lista.
Vai ficar meio idiota, chamar tabela de tabela.... mas vou fazer isso.
Ao invés de JPAUXCFOP, JPAUXPIS, ou chamar de JPTABCFOP, JPTABPIS.
Pelo menos vai ficar tudo mais pro fim da lista.

Mas... talvez seja coisa de DBF.... porque preciso de uma lista bonitinha? ou ficar olhando a lista?

Mas sei lá... encerrar como TAB mesmo.... antes que decida colocar tudo de volta na multitabela, pra ficar escondido kkkkk

Além do que.... isso dá trabalho... e é perigoso ficar mexendo tanto nos fontes, mudando nome de tudo...
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: 18155
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1215 vezes

Dividindo tabelas

Mensagempor JoséQuintas » 02 Set 2020 16:45

Pior que é sério isso.
Olhem só a quantidade de fontes alterando novamente.... de AUX pra TAB
Faltam mais, aí são os que já foram....

alt.png
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: 18155
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1215 vezes

Dividindo tabelas

Mensagempor JoséQuintas » 02 Set 2020 16:59

Fora essas, e as alterações pra TAB do que foi pra AUX.....

Ainda tem as que não comecei a mexer....

#define AUX_BANCO   "BANCO." // bancos
#define AUX_CADCTL  "CADCTL" // Contábil para Cadastro
#define AUX_CARCOR  "CARCOR" // códigos de carta de correção
#define AUX_CCUSTO  "CCUSTO" // centros de custo
#define AUX_CLIGRU  "CLIGRU" // Cliente - Grupos
#define AUX_CNAE    "CNAE.." // CNAE
#define AUX_CTAADM  "CTAADM" // contas administrativas
#define AUX_EDICFG  "EDICFG" // configuracao de edi
#define AUX_FILIAL  "FILIAL" // filiais
#define AUX_FINOPE  "FINOPE" // financeiro - operações
#define AUX_FINPOR  "FINPOR" // financeiro - portadores
#define AUX_IPIENQ  "IPIENQ" // IPI Enquadramento
#define AUX_LICTIP  "LICTIP" // Tipo de licença
#define AUX_LICOBJ  "LICOBJ" // Tipo de objeto
#define AUX_MIDIA   "MIDIA." // Midia, forma por onde chegou o cliente
#define AUX_MODFIS  "MODFIS" // Modelo de documento fiscal
#define AUX_MOTIVO  "MOTIVO" // Motivo de cancelamento
#define AUX_ORIMER  "ORIMER" // origem da mercadoria
#define AUX_PISCST  "PISCST" // PIS CST
#define AUX_PISENQ  "PISENQ" // PIS Enquadramento
#define AUX_PPRECO  "PPRECO" // percentuais de tabelas de preço
#define AUX_PROUNI  "PROUNI" // Produto unidade
#define AUX_QUAASS  "QUAASS" // Qualificação do Assinante
#define AUX_TABAUX  "TABAUX" // Tabelas Auxiliares
#define AUX_TRICAD  "TRICAD" // Tributação de Cadastros
#define AUX_TRIEMP  "TRIEMP" // Tributação de empresa
#define AUX_TRIPRO  "TRIPRO" // Tributação de produtos
#define AUX_TRIUF   "TRIUF." // Tributação de UFs


Deveria ter criado uns VIEW.... era mais fácil...
Um problema é que tem tabela onde o código é numérico, mas outras não.
E também as tabelas juntas causarem um certo tipo de limitação, apesar de ter campos adicionais pra outras coisas além de descrição.
Como pro MySQL, separar não é problema.... vamos em frente....

Isso vai aumentar umas 50 tabelas no total, até surgirem mais....
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: 18155
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1215 vezes

Dividindo tabelas

Mensagempor JoséQuintas » 02 Set 2020 17:02

A vantagem:

         " LEFT JOIN JPAUXILIAR AS AUXTRIUF  ON AUXTRIUF.AXTABELA="  + StringSQL( AUX_TRIUF ) + " AND AUXTRIUF.AXCODIGO = JPIMPOSTO.IMTRIUF" + ;
         " LEFT JOIN JPAUXILIAR AS AUXTRICAD ON AUXTRICAD.AXTABELA=" + StringSQL( AUX_TRICAD ) + " AND AUXTRICAD.AXCODIGO = JPIMPOSTO.IMTRICAD" + ;
         " LEFT JOIN JPAUXILIAR AS AUXTRIPRO ON AUXTRIPRO.AXTABELA=" + StringSQL( AUX_TRIPRO ) + " AND AUXTRIPRO.AXCODIGO = JPIMPOSTO.IMTRIPRO" + ;


fica mais "bonitinho"... rs.... fica mais legível

         " LEFT JOIN JPTABTRIUF ON JPTABTRIUF.IDTRIUF = JPIMPOSTO.IMTRIUF" + ;
         " LEFT JOIN JPTABTRICAD ON JPTABTRICAD.IDTRICAD = JPIMPOSTO.IMTRICAD" + ;
         " LEFT JOIN JPTABTRIPRO ON JPTABTRIPRO.IDTRIPRO = JPIMPOSTO.IMTRIPRO" + ;
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: 18155
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1215 vezes

Dividindo tabelas

Mensagempor JoséQuintas » 03 Set 2020 21:46

 " LEFT JOIN JPAUXILIAR AS AUXTRIUF  ON AUXTRIUF.AXTABELA="  + StringSQL( AUX_TRIUF ) + " AND AUXTRIUF.AXCODIGO = JPIMPOSTO.IMTRIUF" + ;


" LEFT JOIN JPTABTRICAD ON JPTABTRICAD.IDTRICAD = JPIMPOSTO.IMTRICAD" + ;


Tem outra coisa que nem me dei conta antes.... menos código fonte Harbour.

A mudança é pequena mas... o significado é grande:

Fonte SQL serve em qualquer linguagem de programação da atualidade.
O fonte "Clipper", que poderia ser considerado obsoleto, se tornou totalmente atual.
E com isso, tanto o aplicativo quanto o programador estão na moda !!!

Lembram que falei que o mundo do xbase é uma merd.?
Pois é... estou usando MySQL/MariaDB GRÁTIS, ADO GRÁTIS. São soluções pra qualquer linguagem de programação SEM QUALQUER CUSTO.
Já pra xbase ou estilo DBF... tem muita solução paga....

Desenvolvimento pra Android, pra Linux, pra Web... tem SQL? então a parte principal já está pronta !!!
Falta só a parte de enfeitar tela, etc... que qualquer estagiário faz.... e sai mais barato pagar estagiário do que aprender.
Lógico... na prática a gente sempre quer fazer tudo, mas....

Estou gostando muito disso tudo.
Passada a fase de adaptação, é só alegria.
Sinceramente, talvez essa sensação de liberdade é que seja a melhor parte.
É passar de "éca tô usando o que ninguém usa" pra "uau tô usando o que todo mundo usa".
E nem precisei abandonar o Harbour pra isso.

Também é passar de: Quem será que pode ajudar? Chapolin Colorado? para: tem milhares que podem me ajudar com SQL, qualquer programador de qualquer linguagem de programação.

Recomendo a todos.
É como diz Luan Santana: podem se passar 10, 20, 30 anos... o SQL tá aqui... te esperando kkkkk
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: 18155
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1215 vezes

Dividindo tabelas

Mensagempor JoséQuintas » 04 Set 2020 13:19

Sobre dividir tabelas:

O interessante é o seguinte:
Antes, era JPAUXILIAR multi-tabela.
A vantagem era ter quase um fonte só, e um arquivo só, facilitando ter menos fonte, e menos arquivos pra controlar.

"facilitando ter menos fonte, e menos arquivos pra controlar"

Mas tá parecendo o contrário.
Justamente por separar, a ocorrência nos fontes de cada tabela é pequena, e isso vai facilitar modificar qualquer tabela a qualquer momento.
Acaba deixando tudo mais flexível, e o que parecida problema, na prática deixa de ser.
Aumenta o trabalho inicial, de desenvolvimento, mas o de manutenção vai facilitar.

Como eu já disse por aqui: o que mais fazemos é alterar fontes. Se isso facilita alterar fontes..... parece o caminho certo.
Multiplica os cadastros? e daí? se tiver que fazer manutenção, NUNCA fazemos em muitos de uma vez, geralmente é um só.
E esse é o ponto: alterar um só vai ficar extremamente mais fácil, porque não afeta as outras 50 tabelas que estavam dentro do mesmo lugar.

O único lado ruim está sendo acostumar com os nomes... .tô achando que vou acabar trocando o prefixo JPTAB, ou de volta pra JPAUX, ou só TAB ou só JP

Tenho UM CASO, onde dois aplicativos compartilham a mesma base de dados.
O prefixo JP para o meu aplicativo serve como uma espécie de isolamento de nomes.

Por enquanto vou terminar como JPTAB mesmo, deixar qualquer mudança disso pro ano que vém.
Já tem muita conversão acumulando, pra ficar enchendo de mais conversão.

Pois é.... ainda estou me acostumando com essas "novidades".... talvez no ano que vém consiga definir algum padrão de nome único, ou quase único, para o SQL, ou talvez até abandone isso... vamos ver... melhor deixar isso pro ano que vém kkkkk

Parece piada, mas é sério.
Tem certos nomes, que só na hora de ficar digitando é que a gente percebe que facilita digitar errado, e por isso deixa de ser um bom nome.
Então, nem sempre trata-se apenas de escolher um nome, mas de colocá-lo em prática, pra ver se a digitação é fácil.
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: 18155
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1215 vezes

Dividindo tabelas

Mensagempor JoséQuintas » 04 Set 2020 14:55

Com certeza mexer com isso é perigoso, são muitas tabelas.
Mas.... eu uso as tabelas por #define

#define AUX_CADCTL  "CADCTL" // Contábil para Cadastro
#define AUX_CARCOR  "CARCOR" // códigos de carta de correção
#define AUX_CCUSTO  "CCUSTO" // centros de custo
#define AUX_CNAE    "CNAE.." // CNAE
#define AUX_CTAADM  "CTAADM" // contas administrativas
#define AUX_EDICFG  "EDICFG" // configuracao de edi
#define AUX_LICTIP  "LICTIP" // Tipo de licença
#define AUX_LICOBJ  "LICOBJ" // Tipo de objeto
#define AUX_MODFIS  "MODFIS" // Modelo de documento fiscal
#define AUX_ORIMER  "ORIMER" // origem da mercadoria
#define AUX_PISCST  "PISCST" // PIS CST
#define AUX_PISENQ  "PISENQ" // PIS Enquadramento
#define AUX_PPRECO  "PPRECO" // percentuais de tabelas de preço
#define AUX_QUAASS  "QUAASS" // Qualificação do Assinante
#define AUX_TABAUX  "TABAUX" // Tabelas Auxiliares


Aonde usa essa multitabela, usa essa definição.
Nem preciso procurar aonde alterar, o próprio compilador me avisa.
Apenas apago uma linha desse CH e mando compilar.

mudanca.png


Olhem aí....
É a compilação -w3 -es2.
NÃO preciso procurar aonde mexer, apago o #define, e meu editor de textos vai direto aonde precisa mexer.

Então... não tem nada a ver com saber mais ou saber menos, tem a ver apenas com usar as ferramentas disponíveis.
O Harbour consegue fazer essa checagem, o editor permite pegar o resultado da compilação... pronto.

Qualquer um conseguiria fazer isso fácil.
É só usar o "ajudante" chamado compilador, com as opções -w3 -es2

É como eu já disse: ajustar os fontes pra compilar com -w3 -es2 no começo dá muito trabalho, mas depois.... vixe... a gente vira o aplicativo de ponta cabeça, sem se preocupar, porque sabe que o compilador vai impedir muito erro.
E a padronização também, os #define, etc. tudo isso que parece "perfumaria/enfeite", pode até ser trabalho extra na criação, mas o que mais fazemos mesmo é manutenção... e é nisso que precisamos concentrar o "investimento".

Agora imagine alterar 50 arquivos, chaves de acesso, campos, sem essa ajuda do compilador... aí sim, seria extremamente perigoso.
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: 18155
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1215 vezes

Dividindo tabelas

Mensagempor JoséQuintas » 04 Set 2020 19:57

Vou alterar esta rotina, que acabou sendo criada pelas mudanças.
Depois, com as alterações, vai ficar bem mais fácil de entender.
Substituir por um FOR/EACH

   WITH OBJECT cnSQL
      :cSQL := "SELECT * FROM JPAUXILIAR"
      :Execute()
      DO WHILE ! :Eof()
         DO CASE
         CASE :String( "AXTABELA" ) == "PRODEP"
            IF :Number( "AXCODIGO" ) != 0
               :QueryCreate()
               :QueryAdd( "IDPRODEP", :Number( "AXCODIGO" ) )
               :QueryAdd( "PRODEPNOME",   :String( "AXDESCRI" ) )
               :QueryAdd( "PRODEPINFINC", :String( "AXINFINC" ) )
               :QueryAdd( "PRODEPINFALT", :String( "AXINFALT" ) )
               :QueryExecuteInsert( "JPTABPRODEP", .T. )
            ENDIF
            :ExecuteCmd( "DELETE FROM JPAUXILIAR WHERE AXTABELA=" + StringSQL( "PRODEP" ) + " AND AXCODIGO=" + NumberSQL( :Number( "AXCODIGO" ) ) )
         CASE :String( "AXTABELA" ) == "PROGRU"
            IF :Number( "AXCODIGO" ) != 0
               :QueryCreate()
               :QueryAdd( "IDPROGRU", :Number( "AXCODIGO" ) )
               :QueryAdd( "PROGRUNOME",   :String( "AXDESCRI" ) )
               :QueryAdd( "PROGRUINFINC", :String( "AXINFINC" ) )
               :QueryAdd( "PROGRUINFALT", :String( "AXINFALT" ) )
               :QueryExecuteInsert( "JPTABPROGRU", .T. )
            ENDIF
            :ExecuteCmd( "DELETE FROM JPAUXILIAR WHERE AXTABELA=" + StringSQL( "PROGRU" ) + " AND AXCODIGO=" + NumberSQL( :Number( "AXCODIGO" ) ) )
         CASE :String( "AXTABELA" ) == "PROSEC"
            IF :Number( "AXCODIGO" ) != 0
               :QueryCreate()
               :QueryAdd( "IDPROSEC", :Number( "AXCODIGO" ) )
               :QueryAdd( "PROSECNOME",   :String( "AXDESCRI" ) )
               :QueryAdd( "PROSECINFINC", :String( "AXINFINC" ) )
               :QueryAdd( "PROSECINFALT", :String( "AXINFALT" ) )
               :QueryExecuteInsert( "JPTABPROSEC", .T. )
            ENDIF
            :ExecuteCmd( "DELETE FROM JPAUXILIAR WHERE AXTABELA=" + StringSQL( "PROSEC" ) + " AND AXCODIGO=" + NumberSQL( :Number( "AXCODIGO" ) ) )
         CASE :String( "AXTABELA" ) == "PROLOC"
            IF :Number( "AXCODIGO" ) != 0
               :QueryCreate()
               :QueryAdd( "IDPROLOC", :Number( "AXCODIGO" ) )
               :QueryAdd( "PROLOCNOME",   :String( "AXDESCRI" ) )
               :QueryAdd( "PROLOCINFINC", :String( "AXINFINC" ) )
               :QueryAdd( "PROLOCINFALT", :String( "AXINFALT" ) )
               :QueryExecuteInsert( "JPTABPROLOC", .T. )
            ENDIF
            :ExecuteCmd( "DELETE FROM JPAUXILIAR WHERE AXTABELA=" + StringSQL( "PROLOC" ) + " AND AXCODIGO=" + NumberSQL( :Number( "AXCODIGO" ) ) )
         CASE :String( "AXTABELA" ) == "CFOP.."
            IF ! Empty( :String( "AXCODIGO" ) )
               :QueryCreate()
               :QueryAdd( "IDCFOP", :String( "AXCODIGO" ) )
               :QueryAdd( "CFOPNOME", :String( "AXDESCRI" ) )
               :QueryAdd( "CFOPINFINC", :String( "AXINFINC" ) )
               :QueryAdd( "CFOPINFALT", :String( "AXINFALT" ) )
               :QueryExecuteInsert( "JPTABCFOP", .T. )
            ENDIF
            :ExecuteCmd( "DELETE FROM JPAUXILIAR WHERE AXTABELA=" + StringSQL( "CFOP.." ) + " AND AXCODIGO=" + StringSQL( :String( "AXCODIGO" ) ) )
         CASE :String( "AXTABELA" ) == "ICMCST"
            IF ! Empty( :String( "AXCODIGO" ) )
               :QueryCreate()
               :QueryAdd( "IDICMCST", :String( "AXCODIGO" ) )
               :QueryAdd( "ICMCSTNOME", :String( "AXDESCRI" ) )
               :QueryAdd( "ICMCSTINFINC", :String( "AXINFINC" ) )
               :QueryAdd( "ICMCSTINFALT", :String( "AXINFALT" ) )
               :QueryExecuteInsert( "JPTABICMCST", .T. )
            ENDIF
            :ExecuteCmd( "DELETE FROM JPAUXILIAR WHERE AXTABELA=" + StringSQL( "ICMCST" ) + " AND AXCODIGO=" + StringSQL( :String( "AXCODIGO" ) ) )
         CASE :String( "AXTABELA" ) == "IPICST"
            IF ! Empty( :String( "AXCODIGO" ) )
               :QueryCreate()
               :QueryAdd( "IDIPICST", :String( "AXCODIGO" ) )
               :QueryAdd( "IPICSTNOME", :String( "AXDESCRI" ) )
               :QueryAdd( "IPICSTINFINC", :String( "AXINFINC" ) )
               :QueryAdd( "IPICSTINFALT", :String( "AXINFALT" ) )
               :QueryExecuteInsert( "JPTABIPICST", .T. )
            ENDIF
            :ExecuteCmd( "DELETE FROM JPAUXILIAR WHERE AXTABELA=" + StringSQL( "IPICST" ) + " AND AXCODIGO=" + StringSQL( :String( "AXCODIGO" ) ) )
         CASE :String( "AXTABELA" ) == "IPIENQ"
            IF ! Empty( :String( "AXCODIGO" ) )
               :QueryCreate()
               :QueryAdd( "IDIPIENQ", :String( "AXCODIGO" ) )
               :QueryAdd( "IPIENQNOME", :String( "AXDESCRI" ) )
               :QueryAdd( "IPIENQINFINC", :String( "AXINFINC" ) )
               :QueryAdd( "IPIENQINFALT", :String( "AXINFALT" ) )
               :QueryExecuteInsert( "JPTABIPIENQ", .T. )
            ENDIF
            :ExecuteCmd( "DELETE FROM JPAUXILIAR WHERE AXTABELA=" + StringSQL( "IPIENQ" ) + " AND AXCODIGO=" + StringSQL( :String( "AXCODIGO" ) ) )
         CASE :String( "AXTABELA" ) == "PROUNI"
            IF ! Empty( :String( "AXCODIGO" ) )
               :QueryCreate()
               :QueryAdd( "IDUNIDADE", :String( "AXCODIGO" ) )
               :QueryAdd( "UNIDNOME", :String( "AXDESCRI" ) )
               :QueryAdd( "UNIDINFINC", :String( "AXINFINC" ) )
               :QueryAdd( "UNIDINFALT", :String( "AXINFALT" ) )
               :QueryExecuteInsert( "JPTABUNIDADE", .T. )
            ENDIF
            :ExecuteCmd( "DELETE FROM JPAUXILIAR WHERE AXTABELA=" + StringSQL( "PROUNI" ) + " AND AXCODIGO=" + StringSQL( :String( "AXCODIGO" ) ) )
         CASE :String( "AXTABELA" ) == "TRICAD"
            IF :Number( "AXCODIGO" ) != 0
               :QueryCreate()
               :QueryAdd( "IDTRICAD",     :Number( "AXCODIGO" ) )
               :QueryAdd( "TRICADNOME",   :String( "AXDESCRI" ) )
               :QueryAdd( "TRICADINFINC", :String( "AXINFINC" ) )
               :QueryAdd( "TRICADINFALT", :String( "AXINFALT" ) )
               :QueryExecuteInsert( "JPTABTRICAD", .T. )
            ENDIF
            :ExecuteCmd( "DELETE FROM JPAUXILIAR WHERE AXTABELA = " + StringSQL( "TRICAD" ) + " AND AXCODIGO = " + NumberSQL( :Number( "AXCODIGO" ) ) )
         CASE :String( "AXTABELA" ) == "TRIPRO"
            IF :Number( "AXCODIGO" ) != 0
               :QueryCreate()
               :QueryAdd( "IDTRIPRO",     :Number( "AXCODIGO" ) )
               :QueryAdd( "TRIPRONOME",   :String( "AXDESCRI" ) )
               :QueryAdd( "TRIPROINFINC", :String( "AXINFINC" ) )
               :QueryAdd( "TRIPROINFALT", :String( "AXINFALT" ) )
               :QueryExecuteInsert( "JPTABTRIPRO", .T. )
            ENDIF
            :ExecuteCmd( "DELETE FROM JPAUXILIAR WHERE AXTABELA = " + StringSQL( "TRIPRO" ) + " AND AXCODIGO = " + NumberSQL( :Number( "AXCODIGO" ) ) )
         CASE :String( "AXTABELA" ) == "TRIUF."
            IF :Number( "AXCODIGO" ) != 0
               :QueryCreate()
               :QueryAdd( "IDTRIUF",     :Number( "AXCODIGO" ) )
               :QueryAdd( "TRIUFNOME",   :String( "AXDESCRI" ) )
               :QueryAdd( "TRIUFINFINC", :String( "AXINFINC" ) )
               :QueryAdd( "TRIUFINFALT", :String( "AXINFALT" ) )
               :QueryExecuteInsert( "JPTABTRIUF", .T. )
            ENDIF
            :ExecuteCmd( "DELETE FROM JPAUXILIAR WHERE AXTABELA = " + StringSQL( "TRIUF." ) + " AND AXCODIGO = " + NumberSQL( :Number( "AXCODIGO" ) ) )
         CASE :String( "AXTABELA" ) == "TRIEMP"
            IF :Number( "AXCODIGO" ) != 0
               :QueryCreate()
               :QueryAdd( "IDTRIEMP",     :Number( "AXCODIGO" ) )
               :QueryAdd( "TRIEMPNOME",   :String( "AXDESCRI" ) )
               :QueryAdd( "TRIEMPINFINC", :String( "AXINFINC" ) )
               :QueryAdd( "TRIEMPINFALT", :String( "AXINFALT" ) )
               :QueryExecuteInsert( "JPTABTRIEMP", .T. )
            ENDIF
            :ExecuteCmd( "DELETE FROM JPAUXILIAR WHERE AXTABELA = " + StringSQL( "TRIEMP" ) + " AND AXCODIGO = " + NumberSQL( :Number( "AXCODIGO" ) ) )
         CASE :String( "AXTABELA" ) == "BANCO."
            IF :Number( "AXCODIGO" ) != 0
               :QueryCreate()
               :QueryAdd( "IDBANCO",     :Number( "AXCODIGO" ) )
               :QueryAdd( "BANCONOME",   :String( "AXDESCRI" ) )
               :QueryAdd( "BANCOINFINC", :String( "AXINFINC" ) )
               :QueryAdd( "BANCOINFALT", :String( "AXINFALT" ) )
               :QueryExecuteInsert( "JPTABBANCO", .T. )
            ENDIF
            :ExecuteCmd( "DELETE FROM JPAUXILIAR WHERE AXTABELA = " + StringSQL( "BANCO." ) + " AND AXCODIGO = " + NumberSQL( :Number( "AXCODIGO" ) ) )
         CASE :String( "AXTABELA" ) == "CLIGRU"
            IF :Number( "AXCODIGO" ) != 0
               :QueryCreate()
               :QueryAdd( "IDCADGRU",     :Number( "AXCODIGO" ) )
               :QueryAdd( "CADGRUNOME",   :String( "AXDESCRI" ) )
               :QueryAdd( "CADGRUINFINC", :String( "AXINFINC" ) )
               :QueryAdd( "CADGRUINFALT", :String( "AXINFALT" ) )
               :QueryExecuteInsert( "JPTABCADGRU", .T. )
            ENDIF
            :ExecuteCmd( "DELETE FROM JPAUXILIAR WHERE AXTABELA = " + StringSQL( "CLIGRU" ) + " AND AXCODIGO = " + NumberSQL( :Number( "AXCODIGO" ) ) )
         CASE :String( "AXTABELA" ) == "FILIAL"
            IF :Number( "AXCODIGO" ) != 0
               :QueryCreate()
               :QueryAdd( "IDFILIAL",     :Number( "AXCODIGO" ) )
               :QueryAdd( "FILIALNOME",   :String( "AXDESCRI" ) )
               :QueryAdd( "FILIALINFINC", :String( "AXINFINC" ) )
               :QueryAdd( "FILIALINFALT", :String( "AXINFALT" ) )
               :QueryExecuteInsert( "JPTABFILIAL", .T. )
            ENDIF
            :ExecuteCmd( "DELETE FROM JPAUXILIAR WHERE AXTABELA = " + StringSQL( "FILIAL" ) + " AND AXCODIGO = " + NumberSQL( :Number( "AXCODIGO" ) ) )
         CASE :String( "AXTABELA" ) == "FINOPE"
            IF :Number( "AXCODIGO" ) != 0
               :QueryCreate()
               :QueryAdd( "IDFINOPE",     :Number( "AXCODIGO" ) )
               :QueryAdd( "FINOPENOME",   :String( "AXDESCRI" ) )
               :QueryAdd( "FINOPEINFINC", :String( "AXINFINC" ) )
               :QueryAdd( "FINOPEINFALT", :String( "AXINFALT" ) )
               :QueryExecuteInsert( "JPTABFINOPE", .T. )
            ENDIF
            :ExecuteCmd( "DELETE FROM JPAUXILIAR WHERE AXTABELA = " + StringSQL( "FINOPE" ) + " AND AXCODIGO = " + NumberSQL( :Number( "AXCODIGO" ) ) )
         CASE :String( "AXTABELA" ) == "FINPOR"
            IF :Number( "AXCODIGO" ) != 0
               :QueryCreate()
               :QueryAdd( "IDFINPOR",     :Number( "AXCODIGO" ) )
               :QueryAdd( "FINPORNOME",   :String( "AXDESCRI" ) )
               :QueryAdd( "FINPORINFINC", :String( "AXINFINC" ) )
               :QueryAdd( "FINPORINFALT", :String( "AXINFALT" ) )
               :QueryExecuteInsert( "JPTABFINPOR", .T. )
            ENDIF
            :ExecuteCmd( "DELETE FROM JPAUXILIAR WHERE AXTABELA = " + StringSQL( "FINPOR" ) + " AND AXCODIGO = " + NumberSQL( :Number( "AXCODIGO" ) ) )
         CASE :String( "AXTABELA" ) == "MIDIA."
            IF :Number( "AXCODIGO" ) != 0
               :QueryCreate()
               :QueryAdd( "IDMIDIA",     :Number( "AXCODIGO" ) )
               :QueryAdd( "MIDIANOME",   :String( "AXDESCRI" ) )
               :QueryAdd( "MIDIAINFINC", :String( "AXINFINC" ) )
               :QueryAdd( "MIDIAINFALT", :String( "AXINFALT" ) )
               :QueryExecuteInsert( "JPTABMIDIA", .T. )
            ENDIF
            :ExecuteCmd( "DELETE FROM JPAUXILIAR WHERE AXTABELA = " + StringSQL( "MIDIA." ) + " AND AXCODIGO = " + NumberSQL( :Number( "AXCODIGO" ) ) )
         CASE :String( "AXTABELA" ) == "MOTIVO"
            IF :Number( "AXCODIGO" ) != 0
               :QueryCreate()
               :QueryAdd( "IDMOTIVO",     :Number( "AXCODIGO" ) )
               :QueryAdd( "MOTIVONOME",   :String( "AXDESCRI" ) )
               :QueryAdd( "MOTIVOINFINC", :String( "AXINFINC" ) )
               :QueryAdd( "MOTIVOINFALT", :String( "AXINFALT" ) )
               :QueryExecuteInsert( "JPTABMOTIVO", .T. )
            ENDIF
            :ExecuteCmd( "DELETE FROM JPAUXILIAR WHERE AXTABELA = " + StringSQL( "MOTIVO" ) + " AND AXCODIGO = " + NumberSQL( :Number( "AXCODIGO" ) ) )
         ENDCASE
         :MoveNext()
         Inkey()
      ENDDO
      :CloseRecordset()
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: 18155
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1215 vezes

Dividindo tabelas

Mensagempor JoséQuintas » 04 Set 2020 20:22

Melhorou.
Pena que não pensei nisso antes.
Mas ainda tem outras tabelas pra converter.

STATIC FUNCTION Update0903B()

   LOCAL oItem, xCodigo
   LOCAL cnSQL := ADOClass():New( AppConexao() )

   IF AppConexao() == NIL
      RETURN NIL
   ENDIF

   SayScroll( "2020.09.03 Separação de tabelas" )
   WITH OBJECT cnSQL
      :cSQL := "SELECT * FROM JPAUXILIAR"
      :Execute()
      DO WHILE ! :Eof()
         FOR EACH oItem IN { ;
            { "JPTABPRODEP", "IDPRODEP", "PRODEPNOME", "PRODEPINFINC", "PRODEPINFALT", "PRODEP", "N" }, ;
            { "JPTABPROGRU", "IDPROGRU", "PROGRUNOME", "PROGRUINFINC", "PROGRUINFALT", "PROGRU", "N" }, ;
            { "JPTABPROSEC", "IDPROSEC", "PROSECNOME", "PROSECINFINC", "PROSECINFALT", "PROSEC", "N" }, ;
            { "JPTABPROLOC", "IDPROLOC", "PROLOCNOME", "PROLOCINFINC", "PROLOCINFALT", "PROLOC", "N" }, ;
            { "JPTABCFOP",   "IDCFOP",   "CFOPNOME",   "CFOPINFINC",   "CFOPINFALT",   "CFOP..", "C" }, ;
            { "JPTABICMCST", "IDICMCST", "ICMCSTNOME", "ICMCSTINFINC", "ICMCSTINFALT", "ICMCST", "C" }, ;
            { "JPTABIPICST", "IDIPICST", "IPICSTNOME", "IPICSTINFINC", "IPICSTINFALT", "IPICST", "C" }, ;
            { "JPTABIPIENQ", "IDIPIENQ", "IPIENQNOME", "IPIENQINFINC", "IPIENQINFALT", "IPIENQ", "C" }, ;
            { "JPTABPROUNI", "IDPROUNI", "PROUNINOME", "PROUNIINFINC", "PROINIINFALT", "PROUNI", "C" }, ;
            { "JPTABTRICAD", "IDTRICAD", "TRICADNOME", "TRICADINFINC", "TRICADINFALT", "TRICAD", "N" }, ;
            { "JPTABTRIPRO", "IDTRIPRO", "TRIPRONOME", "TRIPROINFINC", "TRIPROINFALT", "TRIPRO", "N" }, ;
            { "JPTABTRIUF",  "IDTRIUF",  "TRIUFNOME",  "TRIUFINFINC",  "TRIUFINTALT",  "TRIUF.", "N" }, ;
            { "JPTABTRIEMP", "IDTRIEMP", "TRIEMPNOME", "TRIEMPINFINC", "TRIEMPINFALT", "TRIEMP", "N" }, ;
            { "JPTABBANCO",  "IDBANCO",  "BANCONOME",  "BANCOINFINC",  "BANCOINFALT",  "BANCO.", "N" }, ;
            { "JPTABCADGRU", "IDCADGRU", "CADGRUNOME", "CADGRUINFINC", "CADGRUINFALT", "CLIGRU", "N" }, ;
            { "JPTABFILIAL", "IDFILIAL", "FILIALNOME", "FILIALINFINC", "FILIALINFALT", "FILIAL", "N" }, ;
            { "JPTABFINOPE", "IDFINOPE", "FINOPENOME", "FINOPEINFINC", "FINOPEINFALT", "FINOPE", "N" }, ;
            { "JPTABFINPOR", "IDFINPOR", "FINPORNOME", "FINPORINFINC", "FINPORINFALT", "FINPOR", "N" }, ;
            { "JPTABMIDIA",  "IDMIDIA",  "MIDIANOME",  "MIDIAINFINC",  "MIDIAINFALT",  "MIDIA.", "N" }, ;
            { "JPTABMOTIVO", "IDMOTIVO", "MOTIVONOME", "MOTIVOINFINC", "MOTIVOINFALT", "MOTIVO", "N" } }
            IF :String( "AXTABELA" ) == oItem[ 6 ]
               xCodigo := :String( "AXCODIGO" )
               IF oItem[ 7 ] == "N"
                  xCodigo := Val( xCodigo )
               ENDIF
               IF ! Empty( xCodigo )
                  :QueryCreate()
                  :QueryAdd( oItem[ 2 ], iif( oItem[ 7 ] == "N", :Number( "AXCODIGO" ), :String( "AXCODIGO" ) ) )
                  :QueryAdd( oItem[ 3 ], :String( "AXDESCRI" ) )
                  :QueryAdd( oItem[ 4 ], :String( "AXINFINC" ) )
                  :QueryAdd( oItem[ 5 ], :String( "AXINFALT" ) )
                  :QueryExecuteInsert( oItem[ 1 ], .T. )
               ENDIF
               :ExecuteCmd( "DELETE FROM JPAUXILIAR WHERE AXTABELA = " + StringSQL( "MOTIVO" ) + " AND AXCODIGO = " + StringSQL( :String( oItem[ 2 ] ) ) )
            ENDIF
         NEXT
         :MoveNext()
         Inkey()
      ENDDO
      :CloseRecordset()
      SayScroll( "2020.09.03 Cadastrando em tabelas vazias" )
      IF ADORecCount( "JPTABUNIDADE" ) == 0
         FOR EACH oItem IN SEFAZ_UNIDADE
            :QueryCreate()
            :QueryAdd( "IDUNIDADE", oItem[ 1 ] )
            :QueryAdd( "UNIDNOME",  oItem[ 2 ] )
            :QueryExecuteInsert( "JPTABUNIDADE", .T. )
         NEXT
      ENDIF
      IF ADORecCount( "JPTABCFOP" ) == 0
         FOR EACH oItem IN SEFAZ_CFOP
            :QueryCreate()
            :QueryAdd( "IDCFOP",   oItem[ 1 ] )
            :QueryAdd( "CFOPNOME", oItem[ 2 ] )
            :QueryExecuteInsert( "JPTABCFOP", .T. )
         NEXT
      ENDIF
      IF ADORecCount( "JPTABICMCST" ) == 0
         FOR EACH oItem IN SEFAZ_ICMCST
            :QueryCreate()
            :QueryAdd( "IDICMCST",   oItem[ 1 ] )
            :QueryAdd( "ICMCSTNOME", oItem[ 2 ] )
            :QueryExecuteInsert( "JPTABICMCST", .T. )
         NEXT
      ENDIF
      IF ADORecCount( "JPTABIPICST" ) == 0
         FOR EACH oItem IN SEFAZ_IPICST
            :QueryCreate()
            :QueryAdd( "IDIPICST",   oItem[ 1 ] )
            :QueryAdd( "IPICSTNOME", oItem[ 2 ] )
            :QueryExecuteInsert( "JPTABIPICST", .T. )
         NEXT
      ENDIF
      FOR EACH oItem IN { ;
         { "JPTABCADGRU", "IDCADGRU", 1,     "CADGRUNOME", "GERAL" }, ;
         { "JPTABCADSTA", "IDCADSTA", 1,     "CADSTANOME", "GERAL" }, ;
         { "JPTABFILIAL", "IDFILIAL", 1,     "FILIALNOME", "MATRIZ" }, ;
         { "JPTABFINOPE", "IDFINOPE", 1,     "FINOPENOME", "GERAL" }, ;
         { "JPTABFINPOR", "IDFINPOR", 1,     "FINPORNOME", "GERAL" }, ;
         { "JPTABFORPAG", "IDFORPAG", 1,     "FORPAGNOME", "GERAL" }, ;
         { "JPTABIPIENQ", "IDIPIENQ", "999", "IPIENQNOME", "OUTROS" }, ;
         { "JPTABMIDIA",  "IDMIDIA",  1,     "MIDIANOME",  "GERAL" }, ;
         { "JPTABMOTIVO", "IDMOTIVO", 1,     "MOTIVONOME", "GERAL" }, ;
         { "JPTABPRODEP", "IDPRODEP", 1,     "PRODEPNOME", "GERAL" }, ;
         { "JPTABPROGRU", "IDPROGRU", 1,     "PROGRUNOME", "GERAL" }, ;
         { "JPTABPROLOC", "IDPROLOC", 1,     "PROLOCNOME", "GERAL" }, ;
         { "JPTABPROSEC", "IDPROSEC", 1,     "PROSECNOME", "GERAL" }, ;
         { "JPTABTRICAD", "IDTRICAD", 1,     "TRICADNOME", "GERAL" }, ;
         { "JPTABTRIEMP", "IDTRIEMP", 1,     "TRIEMPNOME", "GERAL" }, ;
         { "JPTABTRIPRO", "IDTRIPRO", 1,     "TRIPRONOME", "GERAL" }, ;
         { "JPTABTRIUF",  "IDTRIUF",  1,     "TRIUFNOME",  "GERAL" } }
         IF ADORecCount( oItem[ 1 ] ) == 0
            :QueryCreate()
            :QueryAdd( oItem[ 2 ], oItem[ 3 ] )
            :QueryAdd( oItem[ 4 ], oItem[ 5 ] )
            :QueryExecuteInsert( oItem[ 1 ] )
         ENDIF
      NEXT

   ENDWITH

   RETURN NIL


A rotina completa.
Além da conversão, tem o default caso estejam vazias, e mais um cadastramento pelos arquivos da sefazclass.
Além do que estava na outra rotina, tem o resto.

Acho que nem precisa dizer.... em todo caso... com conversão e tudo, mais prático do que em DBF.
É bom chamar atenção pra isso, porque assim pode ajudar quem tem medo de trocar.
Essas e outras rotinas, vão ser executadas quando eu instalar versão nova em cliente.

Bom... aqui, por enquanto, roda toda hora que eu carrego o aplicativo
É que só altero o número da versão no final.
E enquanto não altero a versão... fica executando toda hora...
Se aqui funciona trocentas vezes... no cliente vai funcionar.

E é por isso que de vez em quando volto backups, e abro vários aplicativos de uma vez....
Uma coisa é testar atualizando o que está em andamento, parcialmente convertido, e outra coisa é com um backup fazendo exatamente como está no cliente.
Esse será o teste final, antes da liberação.
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: 18155
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1215 vezes

Dividindo tabelas

Mensagempor JoséQuintas » 07 Set 2020 10:10

Tenho a tabela multi-tabelas no SQL, e em DBF.
Descobri algumas que estão sendo usadas em DBF ainda, e não percebi.
Lembrando que o contábil ainda está em DBF, então ainda sobraram algumas em DBF.

Foi curioso o que aconteceu com esta:

      IF AppVersaoSQLAnt() < 20200905
         IF :TableExists( "JPANPATI" )
            :ExecuteCmd( "DROP TABLE JPANPATI" )
         ENDIF
         IF :TableExists( "JPLEIANPATI" )
            :ExecuteCmd( "DROP TABLE JPLEIANPATI" )
         ENDIF
         IF :TableExists( "JPAUXANPATI" )
            :ExecuteCmd( "DROP TABLE JPAUXANPATI" )
         ENDIF
         IF :TableExists( "JPTABANPATI" )
            :ExecuteCmd( "DROP TABLE JPTABANPATI" )
         ENDIF
      ENDIF


Depois de passar por vários nomes.... ela foi eliminada.
De certa forma ela ficou em duplicidade, já que só uso CNAE pra isso, e existe a tabela de CNAE.
Tabela de atividades da ANP é praticamente a tabela de CNAE, que também é a tabela de ramos de atividade do governo.

Pois é.... dando uma geral no "amontoado" de tabelas.

Como outros devem fazer isso também, de muitas tabelas, pode servir de referência pra alguma coisa.
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: 18155
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1215 vezes

Dividindo tabelas

Mensagempor JoséQuintas » 13 Set 2020 10:15

Primeiro resultado vantajoso depois das divisões.
Não está preso a ser SQL, mas no SQL melhor ainda.
Também a tela poderia ter sido diferente, mesmo as coisas sendo gravadas desse jeito.

patrimonio.png


Essa lista de licenças era um campo "linguição", contendo os códigos das licenças 1,2,3,4,5
E também as datas ficavam em outro "linguição".
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: 18155
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1215 vezes

Dividindo tabelas

Mensagempor JoséQuintas » 13 Set 2020 10:25

Ainda está em andamento a mudança.
Agora os "linguições" tem cadastro próprio, e fiz por browse.

pat2.png


Nem se trata apenas do browse.
A diferença foi criar uma tabela auxiliar contendo cada licença.
Dividi o que era o patrimônio em duas partes.

Vantagem:
Antes eu tinha que processar CADA item, e CADA licença com FOR/NEXT pra ver se tava vencido.
Tudo bem, em DBF também facilitaria já pegar tudo pronto, ao invés de ficar usando FOR/NEXT e Substr().
Mas em SQL..... é só dar um comando e pronto, vém tudo calculado e pronto.
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: 18155
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1215 vezes




Retornar para Banco de Dados

Quem está online

Usuários vendo este fórum: Nenhum usuário registrado online e 6 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