[firebase-br] EXECUTE BLOCK

Gladiston Santana gladiston em vidy.com.br
Qui Jan 21 11:03:54 -03 2016


Implementar execute block é muito fácil, você pode executá-lo como DML ou
como query.
Eu gosto de usá-lo como query então mesmo que não tenha interesse algum num
resultado, ela terá um resultado zero ou maior que zero para indicar
sucesso ou falha. Um exemplo de um execute block que faz um delete aninhado
apagando registros-filhos antes dos registros-pai de um determinado ano:

  sSQL:='';
  sSQL:=sSQL+CR+'EXECUTE BLOCK';
  sSQL:=sSQL+CR+'  returns (result_value integer) ';
  sSQL:=sSQL+CR+'AS';
  sSQL:=sSQL+CR+'declare variable lyear_start integer =
'+IntToStr(nAnoIni)+';';
  sSQL:=sSQL+CR+'declare variable lyear_finish integer;';
  sSQL:=sSQL+CR+'declare variable lyear_current integer;';
  sSQL:=sSQL+CR+'declare variable lid_processo type of column
PROCESSOS.id_processo;';
  sSQL:=sSQL+CR+'declare variable lid_tarefa type of column
PROC_TAREFAS.id_tarefa;';
  sSQL:=sSQL+CR+'declare variable lid_cv type of column CV.id_cv;';
  sSQL:=sSQL+CR+'declare variable lid_cv_item type of column
cv_itens.id_cv_item;';
  sSQL:=sSQL+CR+'declare variable lid_cv_itens_sub1 type of column
cv_itens_sub1.id_cv_itens_sub1;';
  sSQL:=sSQL+CR+'BEGIN';
  sSQL:=sSQL+CR+'  result_value=0;';
  sSQL:=sSQL+CR+'  select max( extract(year from a.dt_criacao) ) FROM CV a';
  sSQL:=sSQL+CR+'  into :lyear_finish;';
  sSQL:=sSQL+CR+'  lyear_current=:lyear_start;';
  sSQL:=sSQL+CR+'  while (:lyear_current<=:lyear_finish) do';
  sSQL:=sSQL+CR+'  begin';
  sSQL:=sSQL+CR+'    for';
  sSQL:=sSQL+CR+'      SELECT DISTINCT a.id_cv, coalesce(c.id_processo,0)
as id_processo';
  sSQL:=sSQL+CR+'      FROM CV a';
  sSQL:=sSQL+CR+'      LEFT JOIN PROCESSOS c ON (a.id_cv=c.id_cv)';
  sSQL:=sSQL+CR+'      WHERE extract(year from
a.dt_criacao)=:lyear_current';
  sSQL:=sSQL+CR+'      into :lid_cv, lid_processo do';
  sSQL:=sSQL+CR+'    begin';
  sSQL:=sSQL+CR+'      if (:lid_processo >0) then';
  sSQL:=sSQL+CR+'      begin';
  sSQL:=sSQL+CR+'        -- Apagando tarefas de processos e seus
colaboradores';
  sSQL:=sSQL+CR+'        for';
  sSQL:=sSQL+CR+'          select a.id_tarefa from  PROC_TAREFAS a';
  sSQL:=sSQL+CR+'          where (a.id_processo=:lid_processo)';
  sSQL:=sSQL+CR+'          into :lid_tarefa do';
  sSQL:=sSQL+CR+'        begin';
  sSQL:=sSQL+CR+'          DELETE FROM PROC_TAREFAS_COLABORADOR WHERE
id_tarefa=:lid_tarefa;';
  sSQL:=sSQL+CR+'        end';
  sSQL:=sSQL+CR+'        DELETE FROM PROC_TAREFAS WHERE
id_processo=:lid_processo;';
  sSQL:=sSQL+CR+'        -- restante dos processos';
  sSQL:=sSQL+CR+'        DELETE FROM PROC_ANEXOS WHERE
id_processo=:lid_processo;';
  sSQL:=sSQL+CR+'        DELETE FROM PROC_HISTORICO WHERE
id_processo=:lid_processo;';
  sSQL:=sSQL+CR+'        DELETE FROM PROC_COMISSAO WHERE
id_processo=:lid_processo;';
  sSQL:=sSQL+CR+'        DELETE FROM PROC_COMISSAO_PARCELAS WHERE
id_processo=:lid_processo;';
  sSQL:=sSQL+CR+'        DELETE FROM PROC_FINANCEIROS WHERE
id_processo=:lid_processo;';
  sSQL:=sSQL+CR+'        DELETE FROM PROCESSOS WHERE
id_processo=:lid_processo;';
  sSQL:=sSQL+CR+'      end';
  sSQL:=sSQL+CR+'      if (:lid_cv >0) then';
  sSQL:=sSQL+CR+'      begin';
  sSQL:=sSQL+CR+'        DELETE FROM CV_AGRE_VALORES2 WHERE id_cv=:lid_cv;';
  sSQL:=sSQL+CR+'        DELETE FROM CV_AGRE_VALORES WHERE id_cv=:lid_cv;';
  sSQL:=sSQL+CR+'        DELETE FROM CV_CARACTERISTICAS WHERE
id_cv=:lid_cv;';
  sSQL:=sSQL+CR+'        DELETE FROM CV_COMISSIONADOS WHERE id_cv=:lid_cv;';
  sSQL:=sSQL+CR+'        DELETE FROM CV_CONTATOS WHERE id_cv=:lid_cv;';
  sSQL:=sSQL+CR+'        DELETE FROM CV_DESFECHOS WHERE id_cv=:lid_cv;';
  sSQL:=sSQL+CR+'        DELETE FROM CV_FOLLOWUP WHERE id_cv=:lid_cv;';
  sSQL:=sSQL+CR+'        DELETE FROM CV_FOLLOWUP2 WHERE id_cv=:lid_cv;';
  sSQL:=sSQL+CR+'        DELETE FROM CV_TAGS WHERE id_cv=:lid_cv;';
  sSQL:=sSQL+CR+'        DELETE FROM CV_REFERENCIAS WHERE id_cv=:lid_cv;';
  sSQL:=sSQL+CR+'        DELETE FROM CV_HISTORICO WHERE id_cv=:lid_cv;';
  sSQL:=sSQL+CR+'        -- Apagando os itens, componentes e
subcomponentes';
  sSQL:=sSQL+CR+'        for';
  sSQL:=sSQL+CR+'          select a.id_cv_item from  CV_ITENS a';
  sSQL:=sSQL+CR+'          where (a.id_cv=:lid_cv)';
  sSQL:=sSQL+CR+'          into :lid_cv_item do';
  sSQL:=sSQL+CR+'        begin';
  sSQL:=sSQL+CR+'          for';
  sSQL:=sSQL+CR+'            select a.id_cv_itens_sub1 from  CV_ITENS_SUB1
a';
  sSQL:=sSQL+CR+'            where (a.id_cv_item=:lid_cv_item)';
  sSQL:=sSQL+CR+'            into :lid_cv_itens_sub1 do';
  sSQL:=sSQL+CR+'          begin';
  sSQL:=sSQL+CR+'            delete from CV_ITENS_SUB2';
  sSQL:=sSQL+CR+'            where (id_cv_itens_sub1=:lid_cv_itens_sub1);';
  sSQL:=sSQL+CR+'          end';
  sSQL:=sSQL+CR+'';
  sSQL:=sSQL+CR+'          delete from CV_ITENS_SUB1';
  sSQL:=sSQL+CR+'          where (id_cv_item=:lid_cv_item);';
  sSQL:=sSQL+CR+'';
  sSQL:=sSQL+CR+'          delete from CV_ITENS';
  sSQL:=sSQL+CR+'          where (id_cv_item=:lid_cv_item);';
  sSQL:=sSQL+CR+'        end';
  sSQL:=sSQL+CR+'        delete from CV WHERE id_cv=:lid_cv;';
  sSQL:=sSQL+CR+'      end';
  sSQL:=sSQL+CR+'    end';
  sSQL:=sSQL+CR+'    lyear_current=:lyear_current+1;';
  sSQL:=sSQL+CR+'  end';
  sSQL:=sSQL+CR+'  result_value=1;';
  sSQL:=sSQL+CR+'  suspend;';
  sSQL:=sSQL+CR+'END';
  ISQL_TO1.SQL.Text:=sSQL;
  ISQL_TO1.Open;
  if ISQL_TO1.FieldbyName('result_value').AsInteger<=0 then
  begin
    ShowMessage('Erro eliminar propostas.');
    Exit;
  end;

Sem o execute block eu teria de implementar numa procedure ou no lado
cliente, evidentemente certos processos é muito mais rápido no servidor,
daí o execute block ser um método mais escolhido.

[]´s e sucesso.



Mais detalhes sobre a lista de discussão lista