Jump to content
Fivewin Brasil

criar tabela com campo auto increment no postgres usando o sqlrdd


Narlem

Recommended Posts

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

Link to comment
Share on other sites

      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
 

Link to comment
Share on other sites

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

 

 

 

Link to comment
Share on other sites

 

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 })

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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

 

Link to comment
Share on other sites

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    

 

 

 

 

Link to comment
Share on other sites

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

 

Link to comment
Share on other sites

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
 
 
 
 
 
Link to comment
Share on other sites

 

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!
Link to comment
Share on other sites

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;

Link to comment
Share on other sites

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()

 

 

Link to comment
Share on other sites

 

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.

Link to comment
Share on other sites

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.

 

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