Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   SQL (https://www.clubdelphi.com/foros/forumdisplay.php?f=6)
-   -   Función en SQL para retornar valor (https://www.clubdelphi.com/foros/showthread.php?t=76495)

rubio 04-11-2011 19:49:02

Función en SQL para retornar valor
 
Hola amigos del foro, como yo puedo ejecutar una función hecha en una base de datos, la cual me retorna un valor y como puedo obtener ese valor en Delphi.

Gracias de antemano a todos.

Casimiro Notevi 04-11-2011 19:56:39

¿Informas, confirmas o preguntas?

rubio 04-11-2011 20:02:32

Pregunto, ya que no se ejecutarlo desde delphi.

Casimiro Notevi 04-11-2011 20:06:38

Tu pregunta es muy genérica, ¿a qué te refieres con "función"?, ¿un query desde delphi?, ¿un store procedure en la base de datos?, ¿de qué base de datos estamos hablando?, etc.
Deberías explicar detalladamente lo que necesitas, porque podemos adivinar, cierto, pero sería eso, adivinar.

Recuerda leer nuestra guía de estilo, por favor, gracias.

rubio 04-11-2011 20:15:13

Disculpa, estoy hablando de SQL 2000, en la misma se pueden definir funciones por el usuario, de esas son las que estoy hablando, las que se programan en el mismo SQL. Te pongo un ejemplo hipotético, yo hago una función para sumar dos valores y retornar ese resultado. Esa función la programo en la sección "Funciones definidas por el usuario" de la base de datos en SQL. Ahora, ¿como yo ejecuto esa función desde Delphi para recuperar el valor que ella me devuelve?.

oscarac 04-11-2011 20:16:07

Cita:

Empezado por Casimiro Notevi (Mensaje 417633)
Tu pregunta es muy genérica, ¿a qué te refieres con "función"?, ¿un query desde delphi?, ¿un store procedure en la base de datos?, ¿de qué base de datos estamos hablando?, etc.
Deberías explicar detalladamente lo que necesitas, porque podemos adivinar, cierto, pero sería eso, adivinar.

Recuerda leer nuestra guía de estilo, por favor, gracias.

me parece que es un procedimiento almacenado... pq menciona que esta hecha en la base de datos, en delphi hay componentes para ejecutar SP (Store Procedure), no se si estoy en lo correcto... como dice casimiro.. da mas detalles

rubio 04-11-2011 20:58:16

Hola oscarac, mi problema es el siguiente, yo solo conozco para ejecutar procedimientos almacenados los componentes de ADO, y estos solo devuelven tipo recordset, yo necesito que el valor devuelto no sea del tipo recordset, yo he estado investigando y no he encontrado otros componentes para esto que no sean los de ADO. Te pongo un ejemplo sencillo, yo ejecuto un consulta en SQL en un procedimiento almacenado que me devuelve un valor entero (cantidad de articulos), ¿como lo obtengo en Delphi?.

oscarac 04-11-2011 21:08:20

lo que se me ocurre es que definas una variable en delphi y que la pases como parametro al SP, luego el resultado lo asignas a esa variable

rubio 09-11-2011 16:49:14

Cita:

Empezado por oscarac (Mensaje 417643)
lo que se me ocurre es que definas una variable en delphi y que la pases como parametro al SP, luego el resultado lo asignas a esa variable

Hola oscarac, me he demorado en contestar ya que he estado buscando información, pero aún no he logrado saber como asignar a una veriable en Delphi un valor retornado de un procedimiento almacenado que no sea un recorset. Por otro lado (no se si esto lo debo mostrar en otro hilo, lo hago aquí ya que tiene relación), como podría ver los mensajes que se emitan desde un procedimiento alm... con las instrucciones PRINT y RAISERROR de SQL.

Código SQL [-]
PRINT 'No Existe el área'

Código SQL [-]
RAISERROR ('El trabajo sobrepaso el nivel', 16, 1)

estos son ejemplos de lo que se pudiera retornar.

Gracias.

fjcg02 09-11-2011 17:03:43

Te contesto al menos a una de las preguntas que haces.

Buscas en goole por SQLSERVER function y la primera entrada te da la sintaxis de cómo se realiza una función que devuelve un entero. a partir de ahí, ya tienes para investigar.

Para recoger el valor desde Delphi, en los componentes ADO tienes el componente TADOStoredProc. Lo sueltas en el formulario, le indicas el store procedure, le indicas qué parámetros tienes, y lo ejecutas. Atención que los parámetros tendrás que revisar si son de entrada o de salida ( input ó output).

Espero que te sirva.

Un saludo

olbeup 10-11-2011 08:58:51

Es lo mismo que una SQL normal y corriente,
eje.: Función ya definida como MySuma(X, Y)
Código SQL [-]
SELECT MySuma(5, 8)
El resultado seria 13.

Con ADO:
Código Delphi [-]
...
var
  xSuma: Integer;
begin
with ADOQry do
begin
  SQL.Add('SELECT MySuma(5,8) AS TOTALSUMA');
  Open;
  xSuma := FieldByName('TOTALSUMA').AsInteger;
end;

Espero que te sirva

Un saludo.

rubio 10-11-2011 19:12:49

Cita:

Empezado por fjcg02 (Mensaje 418006)
Para recoger el valor desde Delphi, en los componentes ADO tienes el componente TADOStoredProc. Lo sueltas en el formulario, le indicas el store procedure, le indicas qué parámetros tienes, y lo ejecutas. Atención que los parámetros tendrás que revisar si son de entrada o de salida ( input ó output).
Un saludo

Hola fjcg02, yo veo bien los de los parámetros de entrada/salida, pero te explico, yo tendo en SQL esto

Código SQL [-]
CREATE PROCEDURE Clonar

@AnoAClonar CHAR(4),
@AnoClonado CHAR(4),
@Salida CHAR(255) OUTPUT

AS

DECLARE @IdIndicador INT, @CodigoI CHAR(10), @NombreI CHAR(255), @CUPI MONEY, @CUCI MONEY,
                  @IdAcapite INT, @CodigoA CHAR(10), @NombreA CHAR(255), @CUPA MONEY, @CUCA MONEY,
                  @IdPartida INT, @CodigoP CHAR(10), @NombreP CHAR(255), @CUPP MONEY, @CUCP MONEY,
                  @IdElemento INT, @CodigoE CHAR(10), @NombreE CHAR(255), @CUPE MONEY, @CUCE MONEY,
                  @IdSubElemento INT, @CodigoSE CHAR(10), @NombreSE CHAR(255), @CUPSE MONEY, @CUCSE MONEY

DECLARE @varIdIndicador INT


DECLARE Todos CURSOR
FOR
SELECT     dbo.Indicador.IdIndicador, dbo.Indicador.Codigo, dbo.Indicador.Nombre, dbo.Indicador.CUP, dbo.Indicador.CUC, 
                          dbo.Acapite.IdAcapite, dbo.Acapite.Codigo, dbo.Acapite.Nombre, dbo.Acapite.CUP, dbo.Acapite.CUC, 
        dbo.Partida.IdPartida, dbo.Partida.Codigo, dbo.Partida.Nombre, dbo.Partida.CUP, dbo.Partida.CUC, 
        dbo.Elemento.IdElemento, dbo.Elemento.Codigo, dbo.Elemento.Nombre, dbo.Elemento.CUP, dbo.Elemento.CUC, 
        dbo.SubElemento.IdSubElemento, dbo.SubElemento.Codigo, dbo.SubElemento.Nombre, dbo.SubElemento.CUP, dbo.SubElemento.CUC
FROM         dbo.Indicador LEFT OUTER JOIN
        dbo.Acapite ON dbo.Indicador.IdIndicador = dbo.Acapite.IdIndicador LEFT OUTER JOIN
        dbo.Partida ON dbo.Acapite.IdAcapite = dbo.Partida.IdAcapite LEFT OUTER JOIN
        dbo.Elemento ON dbo.Partida.IdPartida = dbo.Elemento.IdPartida LEFT OUTER JOIN
        dbo.SubElemento ON dbo.Elemento.IdElemento = dbo.SubElemento.IdElemento    
WHERE     (dbo.Indicador.Ano = @AnoAClonar)

OPEN Todos

FETCH Todos INTO @IdIndicador, @CodigoI, @NombreI, @CUPI, @CUCI, 
                                 @IdAcapite, @CodigoA, @NombreA, @CUPA, @CUCA,
                                 @IdPartida, @CodigoP, @NombreP, @CUPP, @CUCP,
                        @IdElemento, @CodigoE, @NombreE, @CUPE, @CUCE,
                        @IdSubElemento, @CodigoSE, @NombreSE, @CUPSE, @CUCSE

WHILE (@@FETCH_STATUS = 0)
BEGIN

SET @Salida='Paso 1'

    IF (SELECT COUNT(*) FROM Indicador WHERE Ano=@AnoClonado)=0
    BEGIN
        INSERT INTO Indicador (Ano, Codigo, Nombre, CUP, CUC) VALUES (@AnoClonado, @CodigoI, @NombreI, @CUPI, @CUCI)
        SET @varIdIndicador=@@IDENTITY
    END

    FETCH Todos INTO @IdIndicador, @CodigoI, @NombreI, @CUPI, @CUCI, 
                                         @IdAcapite, @CodigoA, @NombreA, @CUPA, @CUCA,
                                     @IdPartida, @CodigoP, @NombreP, @CUPP, @CUCP,
                            @IdElemento, @CodigoE, @NombreE, @CUPE, @CUCE,
                            @IdSubElemento, @CodigoSE, @NombreSE, @CUPSE, @CUCSE

END
GO

Te pregunto, al parámetro @Salida se le puede asignar el valor así?, al ejecutar el programa Delphi me da el siguiente error,



en Delphi lo hago así:

Código Delphi [-]
procedure TfrmGenerales.ADOProcedimiento(Nombre: array of WideString;
                TipoDato: array of TDataType;
                Direccion: array of TParameterDirection;
                Tamano: array of Integer;
                Valor: array of OleVariant;
                Procedimiento: string);
var
  i: integer;
  sp:TADOStoredProc;
begin
  sp := TADOStoredProc.Create( self );
  with sp do
    try
      Connection:=frmAutenticacion.ADOCSistema;
      ProcedureName := Procedimiento;
      with parameters do begin
        for i:=0 to Length(Nombre)-1 do
          CreateParameter(Nombre[i], TipoDato[i], Direccion[i], Tamano[i], Valor[i]);
      end;
      Open;
      Close;
    finally
      sp.Free;
    end;
end;

y la llamada al procedimiento así:

Código Delphi [-]
frmGenerales.ADOProcedimiento(['@AnoAclonar', '@AnoClonado', '@Salida'],
                  [ftString, ftString, ftString],
                  [pdInput, pdInput, pdOutput],
                  [4, 4, 255],
                  [leAClonar.Text, leClonado.Text, ''],
                  'Clonar');

Ahora me sigue la duda, el valor que retorna @Salida como lo recojo en Delphi?

Saludos y gracias.

olbeup 10-11-2011 21:15:57

La variable @Salida = 'Paso 1' tiene un valor fijo, que quieres que te devuelva lo mismo
La variable @varIdIndicador=@@IDENTITY no tiene ninguna utilidad en tu procedimiento, el @@IDENTITY lo que hace es guardar el valor que ha tomado al añadir el registro, pero nada más.
¿Que quieres que te devuelva el procedimiento, @Salida = 'Paso 1'?

rubio 10-11-2011 21:23:05

Cita:

Empezado por olbeup (Mensaje 418158)
La variable @Salida = 'Paso 1' tiene un valor fijo, que quieres que te devuelva lo mismo
La variable @varIdIndicador=@@IDENTITY no tiene ninguna utilidad en tu procedimiento, el @@IDENTITY lo que hace es guardar el valor que ha tomado al añadir el registro, pero nada más.
¿Que quieres que te devuelva el procedimiento, @Salida = 'Paso 1'?

Disculpa, no explique, en ese procedimiento faltan una serie de instrucciones, el valor que devuelve @@IDENTITY yo lo uso mas adelante, en este caso yo le puse un valor fijo a la variable @Salida para hacer las pruebas, pero ella en realidad mas adelante toma diferentes valores en dependencia de lo que se haga, por eso quiero retornar la variable @Salida,

Gracias.

fjcg02 10-11-2011 22:33:28

Creo que quieres ir demasiado rápido.

Haz una pequeña prueba de concepto, y cuando la domines, te metes en harina.

Por otro lado, las instrucciones

with parameters do begin
for i:=0 to Length(Nombre)-1 do
CreateParameter(Nombre[i], TipoDato[i], Direccion[i], Tamano[i], Valor[i]);
end;

no son necesarias, ya que estás creando los parámetros. Si asignas la procedure al TADOStoredProc, ya dispones de los parámetros. Sólo tienes que asignarles el valor.

Código Delphi [-]
procedure TfrmGenerales.ADOProcedimiento(Nombre: array of WideString;
                TipoDato: array of TDataType;
                Direccion: array of TParameterDirection;
                Tamano: array of Integer;
                Valor: array of OleVariant;
                Procedimiento: string);
var
  i: integer;
  sp:TADOStoredProc;
begin
  sp := TADOStoredProc.Create( self );
  with sp do
    try
      Connection:=frmAutenticacion.ADOCSistema;
      ProcedureName := Procedimiento;
      // Damos valor a los parámetros de entrada
      for i:=0 to parameters.Count-1 do
       begin
          with ParameterByName(Nombre[i]) do
          begin
            if Direccion = TInput then // al asignar el SP ya te pone los parámetros y si son de entrada o salida
            begin
              DataType:= TipoDato[i]; -> podría obviarse
              Direction:= Direccion[i]; -> podría obviarse
              Size:=Tamano[i]; -> Podría obviarse
              Value:=Valor[i];
            end;
          end;
      end;

      Execute; ->> Importante, con los SP's no se utiliza Open, o eso creo

    // recogemos los valores de los parámetros de salida
      for i:=0 to parameters.Count-1 do
       begin
          with ParameterByName(Nombre[i]) do
          begin
            if Direccion = TOutput then // al asignar el SP ya te pone los parámetros y si son de entrada o salida
            begin
              Valor[i]:= Value;
            end;
          end;
      end;

     // y ahora deberás hacer algo con los valores recogidos. Podrías definir como var el array de valores en la llamada a la función ya que si no los perdierías

    finally
      sp.Free;
    end;
end;

Buano, estoy escribiendo de memoria, pero creo que lo he puesto claro.

De todas maneras, crea un proyecto nuevo, tira un TADOStoredProc, asignale la conexión y el SP y mira cómo ya dispones de los parámetros.

Prueba a ver y nos cuentas.

Saludos

abelg 11-11-2011 13:50:16

Creo puedes solucionanrlo asi en un TADOQuery en la propiedad SQL pones:
Código SQL [-]
declare@AnoAClonar CHAR(4), @AnoClonado CHAR(4), @Salida CHAR(255)
set @AnoAClonar = :AnoClonar
set @AnoClonado = :AnoClonado

Exec Clonar @AnoAClonar, @AnoClonado, @Salida OUTPUT
Set :Salida = @Salida
En su propiedad Parameters Listará 3 Los cuqales son (AnoClonar, AnoClonado, Salida),
Luego en Delphi lo Llamarias asi: ahi escogemos DataType ftstring para los 3 y solo para el parámetro "Salida" en Direction ponemos pdOutput.
Código Delphi [-]
 with ADOQuery1 do
Begin
  Close;
  Parameters.ParamByName('AnoClonar').Value := edit1.text; //Depende lo que quieras mandar
  Parameters.ParamByName('AnoClonado').Value := edit2.text; //Lo mismo depende de tu parametro
  Parameters.ParamByName('Salida').Value := ''; //Asignado asi porque es un parámetro de Salida
  ExecSQL;
  Edit3.Text := Parameters.ParamByName('Salida').Value; // Estoy Asignando a Edit3 lo que tiene despues 
                                                                           //de ejecutarse el Procedure
end;
Salu2


La franja horaria es GMT +2. Ahora son las 22:21:47.

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