Abrir SQLQuery está com erro de ´Cursor not returned´

27/08/2004

0

Boa tarde

Atualmente estou desenvolvendo uma rotina utilizando D7 + Firebird 15 + dbExpress + Driver UIBFire15 (free) e neste desenvolvimento preciso fazer um travamento de registro (pessimista).

Estou fazendo da seguinte forma

qry.close;
qry.sql.clear;
qry.sql.add(´select pedido_venda from SEQUENCIA´);
qry.sql.add(´for update with lock´); // comando para travar registro
qry.open;

Logo apos realizar o open no SqlQuery o Delphi da o erro: ´Cursor not returned from Query´

1) Como posso resolver este problema ou como faço para fazer travamento de registro utilizando D7 + Firebird15 + DbExpress.

2) Gostaria de saber se assim como o Firebird tem o comando SQL para travamento de registro, outros bancos de dados tb tem? Como por exemplo SqlServer, Oracle e Sybase?


Andrevinni

Andrevinni

Responder

Posts

27/08/2004

Vinicius2k

Colega,

A instrução está correta : ... FOR UPDATE WITH LOCK ...

À primeira vista creio eu q está faltando o WHERE... desta forma vc não está informando ao servidor qual registro travar...

Espero ter ajudado...
T+


Responder

27/08/2004

Andrevinni

Jah tentei esta sentenca de travamento de registros varias formas?

1) select pedido_venda from SEQUENCIA where empresa = 1 for update with lock

2) select pedido_venda from SEQUENCIA where empresa = 1 for update

3) select pedido_venda from SEQUENCIA for update with lock

e nenhuma delas funciona para travar o registro no firebird. Teria uma outra solucao pra este travamento pessimista? Desta forma via sentenca seria bom pq o proprio bco gerenciaria o travamento, se funcionasse iria ficar show de bola.

Olha Vinicius2k, jah pesquisei bastante sobre transacao aqui mesmo neste forum e vi muitas respostas suas sobre controle de transacao. Devido algumas resposta percebi q nao há necessidade de abrir transacao se estiver trabalhando com ClientDataSet e usando ApplyUpdates. Porem se eu abrir uma transacao, depois utilizar varios ApplyUpdates e antes do Commit acontecer um pique de energia os dados aplicados serao salvos ou nao?


Responder

27/08/2004

Vinicius2k

Colega,

1. Consegui simular seu erro...
O problema está no driver, e é o primeiro problema que eu encontrei com ele... fiquei desanimado agora... :?
Troque para o driver nativo dbexpint.dll e seu problema será solucionado...
A instrução para travamento é :
select PEDIDO_VENDA from SEQUENCIA where EMPRESA = 1 for update with lock


2. Sobre as transações...
Realmente se vc não fizer o controle explícito da transação a MIDAS irá fazer... mas vc fizer o isolamento do(s) ApplyUpdates dentro de uma transação controlada por você ela só será ´commitada´ ao seu sinal, se não houver commit, quando da desconexão com o banco, o rollback é automático (Incluindo neste contexto uma possível queda de energia)...
Se não for dado commit, todos os ApplyUpdates envolvidos naquela transação são perdidos...
Um erro comum é pensar em proteger o ApplyUpdates em blocos Try/Except o que não faz sentido... pq um ApplyUpdates não gera exceção

[b:5331f6e9ff]ERRADO:[/b:5331f6e9ff]
TD.TransactionID := 1; 
TD.IsolationLevel := xilReadCommitted;
SQLConnection1.StartTransaction(TD); 
try 
  CDS.ApplyUpdates(0)
  SQLConnection1.Commit(TD); 
except 
  SQLConnection1.Rollback(TD); 
end;

Neste exemplo *errado* o Rollback nunca será efetuado.

[b:5331f6e9ff]CORRETO:[/b:5331f6e9ff]
TD.TransactionID := 1;
TD.IsolationLevel := xilReadCommitted;
SQLConnection1.StartTransaction(TD); 
if CDS.ApplyUpdates(0) = 0  then
  begin  
    SQLConnection1.Commit(TD); 
    ShowMessage(´Aplicado com sucesso!´);
  end
else
  begin  
    SQLConnection1.Rollbabck(TD);   
    ShowMessage(´Ocorreram erros !´); 
  end;

Neste exemplo é dado o Commit se não houverem erros no ApplyUpdates.

Um exemplo mais ´complexo´:
var 
  TudoOK: Boolean; 
try 
  TudoOK:= False;    
  TD.TransactionID:= 1; 
  TD.IsolationLevel:= xilReadCommitted; 
  SQLConnection1.StartTransaction(TD); 
  {****} 
  if ClientDataSet1.ApplyUpdates(0) > 0 then 
    if ClientDataSet2.ApplyUpdates(0) > 0 then 
      if ClientDataSet3.ApplyUpdates(0) > 0 then 
        TudoOK:= True; 
  {****}  
  if TudoOK then SQLConnection1.Commit(TD) 
    else 
      begin 
        ShowMessage(´Ocorreram erros !´); 
        SQLConnection1.Rollback(TD);        
      end; 
except 
  On E: Exception do 
    ShowMessage(´Não foi possível abrir a transação.´ + #13 + E.Message); 
end;

Aqui eu usei try/except mas não para controlar a transação e sim para exibir uma mensagem caso ocorra algum erro na abertura dela... o controle está sendo feito baseado no valor de retorno do ApplyUpdates, que deve ser sempre = 0 (zero), caso contrário não grava nada...
Para exibir o erro e/ou tratá-lo vc precisa trabalhar no evento OnReconcileError do ClientDataSet...
Lá vc pode, além de mostrar uma mensagem personalizada, tomar alguma providência em relação ao erro setando a variável ´Action´, por exemplo :
Action:= raCancel;
Shomessage(´O erro ocorrido foi: ´ + E.Message);


Espero ter ajudado...
T+


Responder

27/08/2004

Vinicius2k

Colega,
Erro de digitação...

Neste trecho :
  {****} 
  if ClientDataSet1.ApplyUpdates(0) > 0 then 
    if ClientDataSet2.ApplyUpdates(0) > 0 then 
      if ClientDataSet3.ApplyUpdates(0) > 0 then 
        TudoOK:= True; 
  {****}  


Leia-se :
  {****} 
  if ClientDataSet1.ApplyUpdates(0) = 0 then 
    if ClientDataSet2.ApplyUpdates(0) = 0 then 
      if ClientDataSet3.ApplyUpdates(0) = 0 then 
        TudoOK:= True; 
  {****}  


T+


Responder

28/08/2004

Andrevinni

Primeiramente Bom dia

Obrigado pelas respostas que esta me ajudando e muito. Agora consigo perceber a importancia em alguns momentos o travamento pessimista e o controle de transacao.
Eu jah suspeitava o que o problema era no driver, porem nao tive a ideia de utilizar a dxExpint.dll

Porem ainda estou com uma duvida?
1) Troquei a dll e funcionou beleza havendo o travamento do regitro. Porem como vou saber que o registro está travado, uma vez que quando
tento acessar pela segunda vez (por outro aplicativo) o programa trava no open da SQLQUERY e fica processando sem dar nenhum erro. Acho que o modo de bloqueio está como WAIT. Como resolver isto?


Responder

28/08/2004

Vinicius2k

Olá !
Realmente a transação deve estar com o WAIT ativado, pq é o default do driver do Interbase...
Altere o parametro ´WaitOnLocks´ da TSQLConnection para ´False´, que deve resolver o problema, levantando a exceção imediatamente, caso o registro esteja travado...

Eu raramente uso travamentos, então, tenho conhecimento das instruções, mas não quase não uso na prática... nunca achei necessário dentro do contexto das minhas aplicações e da forma como trabalho as transações, mas cada caso é um caso, e não me cabe questioná-lo, mas sugiro que vc leia este artigo, que é fantástico...
http://www.comunidade-firebird.org/cflp/downloads/CFLP_T032.PDF

T+


Responder

Assista grátis a nossa aula inaugural

Assitir aula

Saiba por que programar é uma questão de
sobrevivência e como aprender sem riscos

Assistir agora

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.

Aceitar