Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Firebird e Interbase (https://www.clubdelphi.com/foros/forumdisplay.php?f=19)
-   -   Problema con Procedimiento almacenado (https://www.clubdelphi.com/foros/showthread.php?t=40064)

Tauro78 06-02-2007 18:27:51

Problema con Procedimiento almacenado
 
hola, quisiera saber si me pueden ayudar en esto. Uso Delphi7, FB2, MDO e IBExpert. Lo que quiero lograr es que en el momento de dar de alta un cliente me verifique por medio del SP EXIST_CLIENTE si ya existe un cliente con un campo dicose (que es la clave) igual en la tabla. Entonces ejecuto el SP y luego pregunto si el SP es vacio, entonces no existe el cliente, si no esta vacio ya existe el cliente. La verdad no se si se puede hacerlo de esta forma, ya que yo hacia esto en Paradox pero usando uan query.
El SP CLIENTES_ALTAS funciona bien, lo para que vean todo el proceso.
El problema es que me deja entrar la misma clave 2 veces y por supuesto me da error en la clave primaria.
Desde ya muchas gracias.

Código:


SET TERM ^ ;
CREATE PROCEDURE SP_EXIST_CLIENTE (
    sp_dicose char(10))
returns (
    dicose char(10))
as
begin
FOR
  SELECT DICOSE
  FROM CLIENTES WHERE DICOSE=:SP_DICOSE
  INTO :DICOSE
  do
  suspend;
end^
SET TERM ; ^
GRANT SELECT ON CLIENTES TO PROCEDURE SP_EXIST_CLIENTE;
GRANT EXECUTE ON PROCEDURE SP_EXIST_CLIENTE TO SYSDBA;

Código:


SET TERM ^ ;
CREATE PROCEDURE SP_CLIENTES_ALTAS (
    sp_dicose char(10),
    sp_nombre varchar(20))
as
begin
  insert into CLIENTES (DICOSE, NOMBRE)
  values (:sp_dicose, :sp_nombre);
end^
SET TERM ; ^
GRANT INSERT ON CLIENTES TO PROCEDURE SP_CLIENTES_ALTAS;
GRANT EXECUTE ON PROCEDURE SP_CLIENTES_ALTAS TO SYSDBA;

Código Delphi [-]
procedure TfrmClientesAltas.BitBtn1Click(Sender: TObject);
begin
if (Edit1.Text = '') or (Edit2.Text = '') then
  begin
    MessageDlg('Se deben completar todos los campos.', MtInformation, [MbOK], 0);
    Exit;
  end
    else
      begin
        dmTablas.MDOSPExistCPCliente.Close;
        dmTablas.MDOSPExistCPCliente.ParamByName('SP_DICOSE').AsString := Edit1.Text;
        dmTablas.MDOSPExistCPCliente.Prepare;
        dmTablas.MDOSPExistCPCliente.ExecProc;
        if (not dmTablas.MDOSPExistCPCliente.IsEmpty) then
          begin
            MessageDlg('Ya existe un cliente con este número de DICOSE.', MtInformation, [MbOK], 0);
            Exit;
          end
            else
              begin
                with dmTablas.MDOSPClientesAltas do
                  begin      
                    Params.ParamByName('SP_DICOSE').Value := Edit1.Text;
                    Params.ParamByName('SP_NOMBRE').Value := UpperCase(Edit2.Text);
                    Prepared := True;
                    ExecProc;
                  end;
              end;
      end;

ArdiIIa 06-02-2007 18:58:13

No sería mas fácil controlar ese error y nada mas... a sabiendas de que se va a producir cuando hay un duplicado, así te ahorras el procedure SP_EXIST_CLIENTE.
Tampoco tengo muy claro para que utilizas un procedure SP_CLIENTES_ALTAS, si únicamente es para dar un alta, sin más... me parece un abuso de procedures innecesarios.

Tauro78 06-02-2007 19:21:22

Es que acaso lo procedimientos almacenados no deben usarse para realizar solo altas, bajas o modificaciones ?

ArdiIIa 06-02-2007 19:45:05

Cita:

Empezado por Tauro78
Es que acaso lo procedimientos almacenados no deben usarse para realizar solo altas, bajas o modificaciones ?

Los procedimientos se pueden utilizar para lo que se quieran... o como se quieran...
Yo cuando camino, trato de hacerlo hacia adelante, evito ir de lado o de espaldas...
A tu pregunta inicial, repito que los procedimientos que utilizas los considero superfluos siempre u cuando no haya algún otro punto que no comentes..

La forma de dar insertar un muevo registro desde Delphi, no lo puedo explicar. Lee algo sobre los métodos insert o append de los componentes dateset y la manera de controlar los errores y excepciones también podrás encontrar mucha literatura.

lbuelvas 07-02-2007 06:44:22

Hola foro,

Muy respetable tu forma de trabajar pero te recomendaria que utilizaras los procedimientos almacenados para realizar consultas a la base de datos que no son posibles directamente con la clausula select, para hacer calculos y operaciones donde intervienen muchas tablas, para informes cross-tab (donde se trasponen las filas por las columnas) y en general para casos muy especiales.

Voy acolocar un ejemplo, en un sistema que efectua liquidaciones a 10.000 clientes, si lo hiciera en codigo de Delphi, los datos de todos ellos tendrian que viajar por la red hasta el equipo que esta ejecutando el programa, con un procedimiento almacenado no tiene que viajar datos a ninguna parte y se hace la liquidacion directamente en el equipo (servidor) que contien la base de datos, esta es una de las caracteristicas de las tecnologias cliente/servidor.

Otra cosa, si dicose es la llave primaria pues atrapa el error enviado por el motor en caso de presentarse vioalcion de la llave y listo.

Pero volviendo al origen de tu pregunta, el codigo pasa "derecho" y no hace lo que quieres porque tu segmento de codigo

Código Delphi [-]
if (not dmTablas.MDOSPExistCPCliente.IsEmpty) then

siempre dara verdadero, esto debido a que el procedimiento almacenado SP_EXIST_CLIENTE retorna en el parametro de salida dicose un valor (nullo o no), lo que debes es preguntar por el contenido del parametro de salida.

Cambia la linea anterior por

Código Delphi [-]
if (not dmTablas.MDOSPExistCPCliente.ParamByName('DICOSE').IsNull) then

Muchos exitos

Tauro78 08-02-2007 03:41:48

Gracias por sus respuestas, ahora me funciona bien.
En cuanto a la forma de trabajo, prefiero usar definitivamente SP sobre consultas, he leido que no hay que abusar de los SP, bueno supongo que con la practica me dare cuenta.

rastafarey 12-02-2007 17:43:06

Resp
 
Compadre usa un trigger y listo

Anstes de insertar o actes de modificar(pono como debe ir )
Código SQL [-]
as
  declare variable "N" Bigint; 
Begin
   "N" = Null;
   Select "Id" from "Clientes" Where "Id" = new."Id" Into :"N" ;
   if ("N" is not null) 
     exception  "Msg"'Ya existe este cliente';
End
Eso soluciona tu pregunta segun lo que entendi.

Nota: "Msg" es un aexception en este caso vacia y le concateno el mensaje valido de firebird 1.5 en adelante (creo que es desde 1.5 bueno eso no es problema sino le pones el mensaje de uan vez)


La franja horaria es GMT +2. Ahora son las 01:50:33.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi