Narlem Posted June 24, 2019 Report Share Posted June 24, 2019 Olá, Eu preciso criar uma tabela com um campo como chave unica e auto incremento, com o codigo abaixo eu já consigo criar a tabela com o campo codigo como chave unica. colocando 1 no decimo campo do array do campo codigo. alguem sabe como eu conseguiria fazer este campo "codigo", ser alem de chave unica, auto incremento ou seja a cada append ele atribuiria o ultimo mais um * 1 2 3 4 5 6 7 8 9 10 aadd(wstruct, {"codigo" ,"C" ,06 ,0 , , , , , ,1 }) aadd(wstruct, {"nome" ,"D" ,40 ,0}) dbCreate( "teste_dbf" , wstruct, "SQLRDD" ) Desde já atencipo meus agradecimentos a quem puder me ajudar Narlem BH - MG Quote Link to comment Share on other sites More sharing options...
evandro Posted June 25, 2019 Report Share Posted June 25, 2019 Olá, Não uso a SqlRdd mas o princípio é básico. Crie a tabela com uma query SQL ( create table .... ). Com dbcreate você muito provavelmente estará criando uma tabela como se fosse "DBF". Quote Link to comment Share on other sites More sharing options...
aferra Posted June 25, 2019 Report Share Posted June 25, 2019 Tente dessa maneira. aAdd( aStructure, { "ID" , "+", 11, 0 } ) Quote Link to comment Share on other sites More sharing options...
coutinho.amauri Posted June 25, 2019 Report Share Posted June 25, 2019 tente assim vSql := 'Create TABLE USUARIO (' vSql += 'CODUSUARIO Integer(3) NOT NULL AUTO_INCREMENT Primary Key ,' vSql += 'USUARIO VarChar(20) NULL DEFAULT NULL ,' vSql += 'SENHA VarChar(6) NULL DEFAULT NULL ,' vSql += 'EMAIL VarChar(100) NULL DEFAULT NULL ,' vSql += 'SETOR VarChar(1) NULL DEFAULT NULL ,' vSql += 'DESCONTO Decimal(10,2) NULL DEFAULT "0.00" ,' vSql += 'VENDEDOR Integer(3) NULL DEFAULT "0" ,' vSql += 'PERIODO Date NOT NULL DEFAULT "0001-01-01" )' oSql := SR_GetConnection() oSql:Execute( vSql ) //-- Executa a operação no banco oSql:Commit() //-- Atualiza o banco Quote Link to comment Share on other sites More sharing options...
joaosolution Posted June 25, 2019 Report Share Posted June 25, 2019 Bom dia Você deve atentar para a forma que está utilizando o SQLRDD. Caso você esteja utilizando com comandos xBase (Set order,seek etc) você vai precisar criar a tabela com dbcreate, pois dessa forma outras tabelas SR_MGMNTINDEXES,SR_MGMNTTABLES e outras são atualizadas quando você utiliza o dbcreate. E depois de criar executar um alter table : ALTER TABLE dbo. USUARIO ADD CODUSUARIO INT IDENTITY Se você só utiliza comandos SQL você pode exectar o create table sem problemas. Att João Bosco Quote Link to comment Share on other sites More sharing options...
emotta Posted June 26, 2019 Report Share Posted June 26, 2019 Olá, Eu preciso criar uma tabela com um campo como chave unica e auto incremento, com o codigo abaixo eu já consigo criar a tabela com o campo codigo como chave unica. colocando 1 no decimo campo do array do campo codigo. alguem sabe como eu conseguiria fazer este campo "codigo", ser alem de chave unica, auto incremento ou seja a cada append ele atribuiria o ultimo mais um * 1 2 3 4 5 6 7 8 9 10 aadd(wstruct, {"codigo" ,"C" ,06 ,0 , , , , , ,1 }) aadd(wstruct, {"nome" ,"D" ,40 ,0}) dbCreate( "teste_dbf" , wstruct, "SQLRDD" ) Desde já atencipo meus agradecimentos a quem puder me ajudar Narlem BH - MG Na documentação do SQLRDD.CH da a entender que é no 8o parametro (FIELD_ENUM) mas não sei o que tem que passar, acredito ser 1. #define FIELD_NAME 1 #define FIELD_TYPE 2 #define FIELD_LEN 3 #define FIELD_DEC 4 #define FIELD_NULLABLE 5 #define FIELD_DOMAIN 6 /* Not used by dbCreate */ #define FIELD_MULTILANG 7 #define FIELD_ENUM 8 /* Not used by dbCreate */ #define FIELD_WAOFFSET 9 /* Not used by dbCreate */ #define FIELD_PRIMARY_KEY 10 #define FIELD_UNIQUE 11 Então tente assim: aadd(wstruct, {"codigo" ,"C" ,06 ,0 ,nil ,nil ,nil ,1 ,nil ,1 }) Quote Link to comment Share on other sites More sharing options...
Narlem Posted June 26, 2019 Author Report Share Posted June 26, 2019 Olá Pessoal esta necessidade do autoincrent é para sair de um erro muito estranho que ta acontecedo com o sqlrdd/postgres Tenho um arquivo chamado "ultimos_numero", neste arquivo tenho os campos de ultimos numeros de varias tabelas cliente - N - 6 Forneced - N - 6 - 0 venda - N - 8 - 0 no dbf eu abria este arquivo como exclusivo, e pegava o ultimo numero do codigo interno de vendas por exemplo, adicionava 1 a ele, e gravava este novo ultimo numero no arquivo e gravo este ultimo numero de venda no cadastro de vendas, como o arquivo era exclusivo, nunca dois usuarios pegava o mesmo codigo ao mesmo tempo, o segundo usuario tentava abrir o arquivo e atraves do neterror(), eu esperava ate o outro liberar e dava certo 100% mas banco de dados nao consegui abrir arquivo exclusivo, entao abro ele shared, e trava o primeiro registro, este arquivo so tem o primeiro registo, e adiciono + 1 ao ultimo numero, gravo e destravo. funciona quase sempre, mas quando tem muitos usuarios online, de vez em quando o usuario nao consegue travar este registro e fica travado esperando o outro destravar, e trava o sistema. isto nunca deveria acontecer, mas acontece, todos os usuarios ficam tentando travar o mesmo registo do arquivo. o auto incremento poderia resolver isto, mas nao consegui fazer funcionar, fiz uma mudanca, e vou colocar em producao para ver se resolve, o que eu fiz, eu criei um arquivo com o ultimo numero de vendas por exemplo e nao uso mais somente o primeiro registro para guardar o ultimo numero interno de venda, ai eu vou para o ultimo registro, vejo o nro dele, e dou um append para criar um novo registro, e gravo neste novo registro o ultimo numero, como os usuario agora nao tentam travar o mesmo registo, espero que funcione mesmo com esta solucao, o auto increment seria interessante, ja que nao precisaria travar o registro, so ler o conteudo dele, do jeito que fiz, é um passo intermediario ao auto increment me falaram sobre o sr_recno, que é criado no sqlrdd como auto increment, e vi que poderia usar ele, mas se tentei usar e nao deu o resultado que queria, pois se tenho por exemplo 50.000 vendas, eu teria de criar 50.000 registros para o proximo ser o 50.001, até consegui atribuir um valor ao campo sr_recno, por exemplo 50.000 a este campo, mas se for o registro 5, o proximo registro, o registro 6, nao pega 50.000+1, devendo ficar 50.001 nele, mas fica 6, ou seja mesmo que consiga o auto increment, nao resolveria o que quero. vou tentar do jeito que eu falei acima, se continuar esta doidura, ai vou usar o sr_recno, e gerar os 50.000 arquivos anteriores mas acho que esta solucao nao vai resolver para mim nos proximos dias vou ver se resolveu deste jeito e aviso aqui neste post eu uso o mysql e o postgres, vi que o processo de criar um campo em ambos sao diferentes, entao tentei usar a sqlrdd com o dbcreate, como faço com o primary key, para ela se virar com o bd e criar o campo autoincrement, sem ter de fazer isto para cada bd. Quote Link to comment Share on other sites More sharing options...
emotta Posted June 27, 2019 Report Share Posted June 27, 2019 Se era pra isso pq não falou antes... Pega ai esse código, eu adaptei de uma função que já tinha mas não testei, pode ser que tenha algum erro, mas se vc analisar vc consegue adaptar ao seu caso... testa ai e me fala se tiver algum problema eu te ajudo. vc apenas chama a função e iguala em uma variavel (ou direto no campo do replace) quando for gravar os dados da tabela. exemplo: cCodCli := ProxNum("CLIENTES","CODIGO","000001") append blank replace CODIGO with cCodCli replace NOME with cNome replace ENDERECO with cEnd Commit /* cTable = nome da tabela cCampo = nome do campo uDef = caso a tabela ainda esteja vazia ele indica o que a funcao retorna. Exemplo 1: chamada para um cadastro de cliente onde o nome da tabela é CLIENTES e o campo sequencial se chama CODIGO e é do tipo CARACTER 6 cCodCli := ProxNum("CLIENTES","CODIGO","000001") Exemplo 1: chamada para um cadastro de fornecedor onde o nome da tabela é FORNE e o campo sequencial se chama CODIGO e é do tipo NUMERICO nCodFor := ProxNum("FORNE","CODIGO",1) */ Function ProxNum(cTable,cCampo,uDef) Local cSelect Local aDados := {} Local uRet := uDef cSelect := "SELECT Max("+AllTrim(cCampo)+") AS TOTAL FROM "+cTable Sr_GetConnection():Exec(cSelect,,.t.,@aDados) If Len(aDados) > 0 If ValType(aDados[1,1]) == "N" uRet := aDados[1,1]+1 Else uRet := StrZero(Val(aDados[1,1])+1,Len(aDados[1,1])) EndIf EndIf Return uRet Quote Link to comment Share on other sites More sharing options...
Narlem Posted June 27, 2019 Author Report Share Posted June 27, 2019 Olá, Eu acho que assim, vai dar erros de vez enquando, quando por coincidencia, dois executarem o comando ao mesmo tempo, fiz inúmeras simulações, debugando, para dar certo tive que fazer assim: mas o campo C999 tem que estar definido como primary key, só assim dá certo select ultimos go bottom wv1 := val(c999)+1 do while .t. wsair := .f. sr_BeginTransaction() && try && select ultimos append blank if rlock() replace c999 with strzero(wv1,wtamanho) dbunlock() endif dbcommitall() && Ja Alterado sr_CommitTransaction() && wsair := .t. catch e sr_RollBackTransaction() && end && sr_EndTransaction() && if wsair exit endif wv1++ enddo Quote Link to comment Share on other sites More sharing options...
emotta Posted June 27, 2019 Report Share Posted June 27, 2019 simples, crie um semafaro na gravação... abraços Quote Link to comment Share on other sites More sharing options...
Wellington Vieira Posted June 28, 2019 Report Share Posted June 28, 2019 // Criando a tabela if oserver:tableexists("adloja") else cquery := 'create table adloja(' cquery += 'seqloja serial primary key,' cquery += 'razaosocial varchar(60))' oquery := oserver:query(cquery) if oquery:neterr() msgstop("Erro na tabela lojas. Contate o suporte.","Atenção") oserver:destroy() return .t. endif oquery:destroy() endif // Inserindo dados na tabela. // Esta é uma função que criei para facilitar os inserts, no sistema. Sempre note que como o seqloja e incremental, no insert // nunca é atribuido um valor a ele para ser gravado, o próprio postgres se encarrega do incremental. msimnao = "S" retorno = insere_na_tabela("adloja",; {; "razaosocial "; },; {; "'"+mrazaosocial+"'"; },; "[Tabela : adloja - erro no insert do cadastro de lojas]. Contacte o(s) administradore(s) do software.",; {; {mrazaosocial ,"Razão social está sem preencher."}; }; ) // Após toda a vez que for feito o INSERT NA TABELA, caso queira pegar o que esta contido em "seqloja", use o comando abaixo: "select * from adloja_seqloja_seq;", que no caso acima trará uma estrutura assim: |sequence_name |last_value |start_value |increment_by |max_value |min_value |cache_value |log_cnt |is_cycled |is_called |name |bigint |bigint |bigint |bigint |bigint | bigint |bigint |boolean |boolean //Em last_value, basta pegar o valor, que é o incremental gravado na tabela. Quote Link to comment Share on other sites More sharing options...
Wellington Vieira Posted June 28, 2019 Report Share Posted June 28, 2019 Ou ainda, basta criar um SELECT e pegar o último registro gravado na tabela, logo após o insert e pegar o valor do incremental que neste caso será o "seqloja" (incremental), enquanto não há uma gravação de outro usuário em rede que utilize o software. Quote Link to comment Share on other sites More sharing options...
Jmsilva Posted June 29, 2019 Report Share Posted June 29, 2019 Olá Narlem, para fazer o que vc quer usando a SQLRDD, é assim: Você cria a tabela sem a coluna "codigo", no seu exemplo fica assim: aadd(wstruct, {"nome" ,"C" ,40 ,0}) dbCreate( "teste_dbf" , wstruct, "SQLRDD" ) Após criado o dbf (tabela), vc faz as seguintes alterações: SR_SetHideRecno( .F. ) //o Default é .T. SR_RecnoName("codigo") Pronto que vc postou já está resolvido. Simples assim! vamos aos porques? Na realidade quando se cria uma tabela via SQLRDD através da função dbcreate(), será criado a coluna "SR_RECNO" como auto AUTOINCREMENT nativamente para qualquer tipo de servidor, mas sabiamente a SQLRDD permite ao programador ajustar o nome desta coluna, uma vez, que em um banco SQL permite apenas uma coluna com o parâmetro AUTOINCREMENT para cada tabela, MOTIVO PELO QUAL APRESENTA O ERRO MENCIONADO. Agora vamos para código: Use "teste_dbf" //via sqlrdd SR_SetHideRecno( .f.) xbrowse() //Neste caso exibe a coluna "codigo" SR_SetHideRecno( .T.) xbrowse() //Se verdadeiro a coluna "codigo" será ocultada. E por fim, para resolver o seu problema do incremente ser a partir de 50.000, você ajusta o seu banco com seguinte comando SQL: ALTER TABLE `teste_dbf` AUTO_INCREMENT = 50000; Espero que te ajude abraço aferra 1 Quote Link to comment Share on other sites More sharing options...
Jmsilva Posted July 1, 2019 Report Share Posted July 1, 2019 Olá Narlem, para fazer o que vc quer usando a SQLRDD, é assim: Você cria a tabela sem a coluna "codigo", no seu exemplo fica assim: aadd(wstruct, {"nome" ,"C" ,40 ,0}) dbCreate( "teste_dbf" , wstruct, "SQLRDD" ) Após criado o dbf (tabela), vc faz as seguintes alterações: SR_SetHideRecno( .F. ) //o Default é .T. SR_RecnoName("codigo") Pronto que vc postou já está resolvido. Simples assim! vamos aos porques? Na realidade quando se cria uma tabela via SQLRDD através da função dbcreate(), será criado a coluna "SR_RECNO" como auto AUTOINCREMENT nativamente para qualquer tipo de servidor, mas sabiamente a SQLRDD permite ao programador ajustar o nome desta coluna, uma vez, que em um banco SQL permite apenas uma coluna com o parâmetro AUTOINCREMENT para cada tabela, MOTIVO PELO QUAL APRESENTA O ERRO MENCIONADO. Agora vamos para código: Use "teste_dbf" //via sqlrdd SR_SetHideRecno( .f.) xbrowse() //Neste caso exibe a coluna "codigo" SR_SetHideRecno( .T.) xbrowse() //Se verdadeiro a coluna "codigo" será ocultada. E por fim, para resolver o seu problema do incremente ser a partir de 50.000, você ajusta o seu banco com seguinte comando SQL: ALTER TABLE `teste_dbf` AUTO_INCREMENT = 50000; Espero que te ajude abraço Cometi uns pequenos lapsos na mensagem acima,veja: 1 - A função SR_RecnoName("codigo") tem que estar antes da criação da tabela. SR_RecnoName("codigo") aadd(wstruct, {"nome" ,"C" ,40 ,0}) dbCreate( "teste_dbf" , wstruct, "SQLRDD" ) 2- A função SR_SetHideRecno( .f.) tem que estar antes da dbusearea() - antes de abrir o arquivo SR_SetHideRecno( .F.) Use "teste_dbf" //via sqlrdd xbrowse() //Neste caso exibe a coluna "codigo" SR_SetHideRecno( .T.) Use "teste_dbf" //via sqlrdd xbrowse() //Se verdadeiro a coluna "codigo" será ocultada. Desculpe-me o equívoco! Quote Link to comment Share on other sites More sharing options...
Jmsilva Posted July 1, 2019 Report Share Posted July 1, 2019 Caro Narlem, depois tudo isso, se não quiser fazer grandes alterações nas rotinas, poderá optar, em cria campo "codigo" tipo "C" ou "N", após dbappend() gravar recno() fica assim: * 1 2 3 4 5 6 7 8 9 10 aadd(wstruct, {"codigo" ,"C" ,06 ,0}) aadd(wstruct, {"nome" ,"C" ,40 ,0}) dbCreate( "teste_dbf" , wstruct, "SQLRDD" ) SR_SetHideRecno(.F.) //exibe a coluna sr_recno no alias Use "teste_dbf" //abrir //Gravação SR_BeginTransaction() DBAppend() //neste momento campo sr_recno já está com o valor incrementado de forma automática pela RDD replace nome with "bla bla bla" DBCcommit() replace codigo with strzero(sr_recno,6) SR_CommitTransaction() Devidamente testado. Lembrado que o autoincrement pode ser configurado à critério ALTER TABLE `teste_dbf` AUTO_INCREMENT = 150; Quote Link to comment Share on other sites More sharing options...
emotta Posted July 2, 2019 Report Share Posted July 2, 2019 JmSilva, veja no 7o comentário desse post ele explica o pq pra ele essa solução não funcionaria Caro Narlem, depois tudo isso, se não quiser fazer grandes alterações nas rotinas, poderá optar, em cria campo "codigo" tipo "C" ou "N", após dbappend() gravar recno() fica assim: * 1 2 3 4 5 6 7 8 9 10 aadd(wstruct, {"codigo" ,"C" ,06 ,0}) aadd(wstruct, {"nome" ,"C" ,40 ,0}) dbCreate( "teste_dbf" , wstruct, "SQLRDD" ) //abrir use "teste_dbf" dbappend() //neste momento campo sr_recno já está com o valor incrementado de forma automática pela RDD replace codigo with strzero(recno(),6) replace nome with "bla bla bla" dbcommit() Jmsilva 1 Quote Link to comment Share on other sites More sharing options...
Jmsilva Posted July 2, 2019 Report Share Posted July 2, 2019 JmSilva, veja no 7o comentário desse post ele explica o pq pra ele essa solução não funcionaria Emotta, li não vejo problemas nas duas soluções que apresentei, vai atender ele sem problemas. No dBase não tem remédio, com SQL a história é outra. Não consegui entender a solução apresentada por ele. Nesta última que apresentei precisa ajustar uns detalhes, fiz testes não funcionou 100 % no Maria dB. Tem quer ajustar hiderecno e salvar o Sr_recno ao invés de recno(). Vou postar mais tarde. O que percebi foi comportamento diferenciado no uso sqlrdd em relação ao tipo de banco. Uns somente o dbapend e o commit funciona bem caso sqlserver, já no Maria dB tem start transaction para que o dado fidelize no banco e seja visto instantaneamente por outra estação. São ajustes que devem ser testados conforme o banco usado. Valeu! Não servir prá ele serve como aprendizado. Quote Link to comment Share on other sites More sharing options...
emotta Posted July 2, 2019 Report Share Posted July 2, 2019 Eu tb não vejo problema na solução que apresentei a ele, mas ele disse que não o atenderia tb... A função que passei uso a anos e nunca me deu problema, é uma função genérica a se executar logo antes de gravar. Emotta, li não vejo problemas nas duas soluções que apresentei, vai atender ele sem problemas. No dBase não tem remédio, com SQL a história é outra. Não consegui entender a solução apresentada por ele. Nesta última que apresentei precisa ajustar uns detalhes, fiz testes não funcionou 100 % no Maria dB. Tem quer ajustar hiderecno e salvar o Sr_recno ao invés de recno(). Vou postar mais tarde. O que percebi foi comportamento diferenciado no uso sqlrdd em relação ao tipo de banco. Uns somente o dbapend e o commit funciona bem caso sqlserver, já no Maria dB tem start transaction para que o dado fidelize no banco e seja visto instantaneamente por outra estação. São ajustes que devem ser testados conforme o banco usado. Valeu! Não servir prá ele serve como aprendizado. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.