Newsgroup: it.comp.lang.delphi
Titolo: Firebird - Stored procedure in delphi con componenti Zeos (lungo)

Salve a tutto il newsgroup,
ho il seguente problema che dopo svariati tentativi e prove non riesco a 
risolvere. Dovrei aggiungere dei nuovi records ad una tabella e 
controllare prima dell'inserimento del nuovo dato se questo esiste già; 
per fare questo ho creato una stored procedure che ha un parametro di 
input (GVAL varchar(20)) e un parametro in output (IDGEN integer). La 
cosa strana, che non capisco, è che quando la procedure viene eseguita 
per la prima volta tutto va bene, quando viene richiamata la seconda 
volta mi dà il seguente errore:
SQL Error: Dynamic SQL Error parameter mismath for procedure FIND_GENRE. 
Error Code: -902. Unsuccessful execution caused by a system error that 
preclude sucessful execution of subsequent statements The SQL: EXECUTE 
PROCEDURE FIND_GENRE(?,?).
Uso Delphi 7, Componenti Zeos 6.5.1 alpha CVS 13/10/2005, Firebird 
1.5.2.4731, il tutto in Winzoz XP Home con SP2.
Inserisco nel messaggio anche tutti i sorgenti del programma di test.
File : TEST.DPR
-----
program test;
uses
   Forms,
   Unit1 in 'Unit1.pas' {Form1};
{$R *.res}
begin
   Application.Initialize;
   Application.CreateForm(TForm1, Form1);
   Application.Run;
end.
-----
File : UNIT1.DFM
-----
object Form1: TForm1
   Left = 309
   Top = 208
   Width = 618
   Height = 451
   Caption = 'Form1'
   Color = clBtnFace
   Font.Charset = DEFAULT_CHARSET
   Font.Color = clWindowText
   Font.Height = -11
   Font.Name = 'MS Sans Serif'
   Font.Style = []
   OldCreateOrder = False
   PixelsPerInch = 96
   TextHeight = 13
   object Memo1: TMemo
     Left = 4
     Top = 126
     Width = 133
     Height = 285
     Lines.Strings = (
       'Blues'
       'Classic Rock'
       'Country'
       'Dance'
       'Disco'
       'Funk'
       'Grunge')
     ScrollBars = ssVertical
     TabOrder = 0
   end
   object DBGrid1: TDBGrid
     Left = 290
     Top = 0
     Width = 320
     Height = 417
     Align = alRight
     DataSource = DataSource1
     TabOrder = 1
     TitleFont.Charset = DEFAULT_CHARSET
     TitleFont.Color = clWindowText
     TitleFont.Height = -11
     TitleFont.Name = 'MS Sans Serif'
     TitleFont.Style = []
   end
   object Button1: TButton
     Left = 8
     Top = 6
     Width = 75
     Height = 25
     Caption = 'inserisci'
     TabOrder = 2
     OnClick = Button1Click
   end
   object Memo2: TMemo
     Left = 144
     Top = 126
     Width = 99
     Height = 287
     Lines.Strings = (
       'Memo2')
     ScrollBars = ssVertical
     TabOrder = 3
   end
   object ZConnection1: TZConnection
     Protocol = 'firebird-1.5'
     Database = 'D:\Dati\Delphi\Prog\CDDBtoDB\Test\TESTDB.FDB'
     User = 'sysdba'
     Password = 'sysDBkey'
     Connected = True
     Left = 254
     Top = 86
   end
   object ZQuery1: TZQuery
     Connection = ZConnection1
     Active = True
     SQL.Strings = (
       'select * from genres')
     Params = <>
     Left = 252
     Top = 120
     object ZQuery1ID: TIntegerField
       FieldName = 'ID'
       Required = True
     end
     object ZQuery1GENERE: TStringField
       FieldName = 'GENERE'
       Required = True
     end
   end
   object ZSequence1: TZSequence
     Connection = ZConnection1
     SequenceName = 'GENRES_ID_GEN'
     Left = 254
     Top = 152
   end
   object ZStoredProc1: TZStoredProc
     Connection = ZConnection1
     Active = True
     Params = <
       item
         DataType = ftInteger
         Name = 'IDGEN'
         ParamType = ptResult
       end
       item
         DataType = ftString
         Name = 'GVAL'
         ParamType = ptInput
       end>
     StoredProcName = 'FIND_GENRE'
     Left = 248
     Top = 378
     ParamData = <
       item
         DataType = ftInteger
         Name = 'IDGEN'
         ParamType = ptResult
       end
       item
         DataType = ftString
         Name = 'GVAL'
         ParamType = ptInput
       end>
   end
   object DataSource1: TDataSource
     DataSet = ZQuery1
     Left = 254
     Top = 220
   end
   object ZStoredProc2: TZStoredProc
     Connection = ZConnection1
     Active = True
     Params = <
       item
         DataType = ftInteger
         Name = 'MAXIN'
         ParamType = ptResult
       end>
     StoredProcName = 'MAX_ID_GENRES'
     Left = 254
     Top = 186
     ParamData = <
       item
         DataType = ftInteger
         Name = 'MAXIN'
         ParamType = ptResult
       end>
   end
end
-----
File : UNIT1.PAS
-----
unit Unit1;
interface
uses
   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, 
Forms,
   Dialogs, ZConnection, ZStoredProcedure, ZSequence, DB,
   ZAbstractRODataset, ZAbstractDataset, ZDataset, StdCtrls, Grids, DBGrids;
type
   TForm1 = class(TForm)
     ZConnection1: TZConnection;
     ZQuery1: TZQuery;
     ZQuery1ID: TIntegerField;
     ZQuery1GENERE: TStringField;
     ZSequence1: TZSequence;
     ZStoredProc1: TZStoredProc;
     Memo1: TMemo;
     DataSource1: TDataSource;
     DBGrid1: TDBGrid;
     Button1: TButton;
     ZStoredProc2: TZStoredProc;
     Memo2: TMemo;
     procedure Button1Click(Sender: TObject);
   private
     { Private declarations }
   public
     { Public declarations }
   end;
var
   Form1: TForm1;
implementation
{$R *.dfm}
function Normalize(Value: String; MaxSize: Word): String;
begin
      Result := Value;
      if (Length(Value)>MaxSize) then Value := Copy(Value,1,MaxSize);
      Result := LowerCase(Trim(Value));
end;
function CheckGenreID(Value: String): Longint;
begin
      Result := 0;
      if Value<>'' then
        try
           form1.ZStoredProc1.ParamByName('GVAL').AsString := Value;
           form1.ZStoredProc1.ExecProc;
           Result := form1.ZStoredProc1.ParamByName('IDGEN').AsInteger;
        finally
        end;
end;
function GetGenreID(Value: String): Longint;
const Inql = 'INSERT INTO GENRES (
GENRES.ID
, GENRES.GENERE) '+
              'VALUES (:ID, :GENERE)';
begin
      Value := Normalize(Value,form1.ZQuery1GENERE.Size);
      Result := CheckGenreID(Value);
      if Result<=0 then
        try
           form1.ZQuery1.SQL.Text := Inql;
           form1.ZQuery1.Params[1].AsString := Value;
           form1.ZQuery1.ExecSQL;
           form1.ZStoredProc2.ExecProc;
           Result := form1.ZStoredProc2.Params[0].AsInteger;
        finally
        end;
end;
procedure ConvertMemo;
var Nx, NewId: Integer;
begin
      form1.Memo2.Lines.Clear;
      for Nx := 0 to form1.Memo1.Lines.Count-1 do
        begin
             NewId := GetGenreID(form1.Memo1.Lines[Nx]);
             Form1.Memo2.Lines.Add(IntToStr(NewId));
        end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
      Convertmemo;
end;
end.
-----
Aggiungo anche la struttura del database:
-----
CREATE TABLE "GENRES"
(
   "ID"	 	INTEGER NOT NULL,
   "GENERE"	VARCHAR(20) CHARACTER SET WIN1251 NOT NULL,
CONSTRAINT "PK_GENRES" PRIMARY KEY ("ID")
);
CREATE TRIGGER "AI_GENRES_ID" FOR "GENRES"
ACTIVE BEFORE INSERT POSITION 0
AS
BEGIN
   IF (
NEW.ID
 IS NULL) THEN
 
NEW.ID
 = GEN_ID(GENRES_ID_GEN, 1);
END
CREATE GENERATOR "GENRES_ID_GEN";
CREATE PROCEDURE MAX_ID_GENRES
RETURNS ( MAXIN INTEGER)
AS
BEGIN
   MAXIN = gen_id(genres_id_gen, 0);
   SUSPEND;
END
CREATE PROCEDURE FIND_GENRE (GVAL VARCHAR (20))
RETURNS (IDGEN INTEGER)
AS
BEGIN
   select 
genres.id
 from genres
    where :GVAL = genres.genere
   into :IDGEN;
   SUSPEND;
END
-----
Grazie in anticipo e ciao a tutti
Michele Rossa

1) a prescindere alla prima o seconda volta, l'errore ti viene fuori
sia se il dato esiste sia se il dato non esiste?
2) prova a fare la stessa cosa via odbc e vedi cosa succede
A.

Alberto Salvati ha scritto:

Ho provato con i componenti IBX e tutto funziona perfettamente, a questo 
punto penso che ci sia in piccolo bug sul componente TZStoredProc.
Il mio era solo un test sui componenti Zeos in previsione di utilizzarli 
in un progetto un po' più complesso, ma visti i problemi continuo a 
utilizzare gli IBX.
Se posso approfittare della tua cortesia sai dirmi se i componenti IBX 
sono supportati anche nelle versioni successive di Delphi?
Ciao
Michele Rossa

 sono supportati anche nelle versioni successive di Delphi?
su d7 ci sono.
su d200x (win32) non so.
Ma un altra cosa che NON SO e' se gli ibx funzionano con firebird...
Se vuoi stare tranquillo, ci sono questi:
http://crlab.com/ibdac/
che a detta di alcuni del ng funzionano come si deve.
Se poi vai su .net sempre dal sito di firebird puoi scaricare il
provider 
ado.net
.
A.

 
Grazie per il link, ma se era possibile cercavo qualcosa di freeware 
possibilmente anche con i sorgenti
Grazie ancora
Ciao
Michele Rossa

 possibilmente anche con i sorgenti
Lo so... Prima pagavamo i db.. mo paghiamo i componenti di accesso ai
dati.
A.