2

我正在开发 Delphi 7 中的搜索查询功能(使用 Paradox 数据库),在两个日期之间进行选择时,我不断收到类型不匹配错误。如果我使用我得到的日期类型

Project Project1.Exe 引发异常类 EDBEngineError,并带有消息“表达式中的类型不匹配”。过程停止。

如果我使用 dateTime 类型,我会得到

项目 Project1.Exe 引发异常类 EDBEngineError 并带有消息“无效使用关键字。代币:13?和行号:8'。过程停止。

其中 13 是时间的第一个数字。

这是我的代码:

procedure TForm1.Button1Click(Sender: TObject);
var
  Search1 :string;
  Search2 :string;
  outputveld : string;
  datum : TDateTime;
  datumZoek: TdateTime;
  countmails : integer;
  outfile: textfile;
  Zoek6MaandenTerug: Double;
begin
  Zoek6MaandenTerug := 182.621099;
  datum := tdate(now);
  datumZoek := datum - Zoek6MaandenTerug;
  ShowMessage(DateTimeToStr(Datum));
  ShowMessage(DateTimeToStr(datumZoek));
  Memo1.Lines.Add(DateTimeToStr(Datum));
  //datum := datum- StrToDate('21-4-2004');
  {radio button date controll}

  {//radio button date controll}
  Search1 := Edit1.Text;
  Search2 := Edit2.Text;

  assignfile(outfile,'text\Emails.txt');
  rewrite(outfile);
  outputveld := '';
  countmails := 0;

  {sets up  and executesSQL query(Query1)}
  Query1.close;
  Query1.SQL.Clear;
  memo1.Clear;
  if Search1 <> EmptyStr then
  begin
    //Query1.SQL.add('SELECT * FROM Verkoop');
    Query1.SQL.add('SELECT DISTINCT Verkoophandelingen.Klantnr, Verkoophandelingen.Type, verkoop.Klantnr, Verkoop.Artikelnr, Artikels.Nummer, Artikels.artikelgroep, Verkoophandelingen.Datum, Klanten.Email');
    Query1.SQL.add('FROM Verkoop');
    Query1.SQL.add('full Join Artikels ON Verkoop.Artikelnr = Artikels.Nummer');
    Query1.SQL.add('full Join Klanten ON Verkoop.Klantnr = Klanten.Nummer');
    Query1.SQL.add('full Join Verkoophandelingen ON Verkoop.verkoophandelingnr = Verkoophandelingen.nummer');
    Query1.SQL.add('WHERE Verkoophandelingen.Type = "Bestelling" ');
    Query1.SQL.add('AND Verkoop.Artikelnr = '+Search1+'');
    //Query1.SQL.add('AND Verkoophandelingen.Datum = '+ DateToStr(Date1) +'');
    Query1.SQL.add('AND Verkoophandelingen.Datum BETWEEN '+DateTimeToStr(datum)+'');
    Query1.SQL.Add('AND '+DateToStr(datumzoek)+'');
    Query1.SQL.add('ORDER BY Datum');

    Query1.RequestLive := true;
    Query1.open;
  end
  else if Search2 <> EmptyStr then
  begin
    Query1.SQL.add('SELECT DISTINCT Verkoophandelingen.Klantnr, Verkoophandelingen.Type, verkoop.Klantnr, Verkoop.Artikelnr, Artikels.Nummer, Artikels.artikelgroep, Verkoophandelingen.Datum, Klanten.Email');
    Query1.SQL.add('FROM Verkoop');
    Query1.SQL.add('full Join Artikels ON Verkoop.Artikelnr = Artikels.Nummer');
    Query1.SQL.add('full Join Klanten ON Verkoop.Klantnr = Klanten.Nummer');
    Query1.SQL.add('full Join Verkoophandelingen ON Verkoop.verkoophandelingnr = Verkoophandelingen.nummer');
    Query1.SQL.add('WHERE Verkoophandelingen.Type = "Bestelling" ');
    Query1.SQL.add('AND Artikels.ArtikelGroep = '+Search2+'');
    Query1.SQL.add('AND Verkoophandelingen.Datum BETWEEN '+DateToStr(datum)+'');
    Query1.SQL.Add('AND '+DateToStr(datumZoek)+'');
    Query1.SQL.add('ORDER BY Datum');
    Query1.RequestLive := true;
    Query1.open;
  end;

  while not Query1.Eof do
  begin
    if Query1.FieldByName('Email').AsString <>  EmptyStr then
    begin
      memo1.Lines.Add(Query1.FieldByName('Email').AsString + ';');
      writeln(outfile, Query1.FieldByName('Email').AsString+ ';');
      Query1.next;
      inc(countmails);
    end
    else
    begin
      Query1.next;
    end;
  end;

  if Query1.Eof then
  begin
    CloseFile(outfile);
    memo1.lines.add('totaal aantal valid email adressen = ' + IntToStr(countmails));
  end;
end;

我希望即时发布在正确的地方。这是我在为我的查询添加参数后仍然得到“表达式中的类型不匹配”的代码。

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Grids, DBGrids, DB, DBTables, DBCtrls;

type
  TForm1 = class(TForm)
    DataSource1: TDataSource;
    Query1: TQuery;
    DBGrid1: TDBGrid;
    Button1: TButton;
    ComboBox1: TComboBox;
    Memo1: TMemo;
    Edit1: TEdit;
    Edit2: TEdit;
    Label1: TLabel;
    Label2: TLabel;
    Button2: TButton;
    RadioButton1: TRadioButton;
    RadioButton2: TRadioButton;
    RadioButton3: TRadioButton;
    procedure Button1Click(Sender: TObject);
    procedure FormActivate(Sender: TObject);
    procedure ComboBox1Change(Sender:TObject);
    procedure Edit1Change(Sender: TObject);
    procedure Edit2Change(Sender: TObject);

  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

uses ComObj;

{$R *.dfm}




procedure TForm1.FormActivate(Sender: TObject);

 var
i : integer;
mystringlist : tstringlist;
 datum: TDateTime;
   Zoek6MaandenTerug : Double;
begin
        Zoek6MaandenTerug := 182.621099;
        datum := tdate(now);
        datum := datum - Zoek6MaandenTerug;
        ShowMessage(DateToStr(datum));
        Memo1.Lines.Add(DateTimeToStr(Datum));
        Memo1.Lines.Add(DateToStr(datum));
        //datum := datum- StrToDate('21-4-2004');

   MyStringList := TStringList.Create;
    {
    memo1.Clear;
    Edit1.Clear;
    Edit2.Clear;
    }

  try
    Session.GetAliasNames(MyStringList);
    { fill a list box with alias names for the user to select from }
    for I := 0 to MyStringList.Count - 1 do begin
      combobox1.Items.Add(MyStringList[I]);
    end
    finally
    MyStringList.Free;
    end;

   end;

   procedure TForm1.ComboBox1Change(Sender: TObject);
begin

try
      Query1.SQL.Clear;
            Query1.Databasename := string(combobox1.items[combobox1.ItemIndex]);

        except
        with Application do
        begin
            NormalizeTopMosts;
            MessageBox(' wrong database ', 'fout..', MB_OK);
            RestoreTopMosts;
            combobox1.SetFocus;
        Exit;
        end;

end;
 end;



procedure TForm1.Button1Click(Sender: TObject);
var

  Search1 :String;
  Search2 :String;
  outputveld : string;
  datum : TDateTime;
  datumZoek: TDateTime;
  countmails : integer;
  outfile: textfile;
  Zoek6MaandenTerug: Double;

begin

        Zoek6MaandenTerug := 182.621099;
        datum := tdate(now);
        datumZoek := datum - Zoek6MaandenTerug;
        ShowMessage(DateTimeToStr(Datum));
        ShowMessage(DateTimeToStr(datumZoek));
        Memo1.Lines.Add(DateToStr(datum));
        Memo1.Lines.Add(DateToStr(datumZoek));

        //datum := datum- StrToDate('21-4-2004');



{//radio button date controll}
      Search1 := Edit1.Text;
      Search2 := Edit2.Text;


      assignfile(outfile,'text\Emails.txt');
      rewrite(outfile);
      outputveld := '';
      countmails := 0;


        {sets up  and executesSQL query(Query1)}
            Query1.close;
      Query1.SQL.Clear;
      memo1.Clear;
       if Search1 <> EmptyStr then
          begin


             //Query1.SQL.add('SELECT * FROM Verkoop');
            Query1.SQL.add('SELECT DISTINCT Verkoophandelingen.Klantnr, Verkoophandelingen.Type, verkoop.Klantnr, Verkoop.Artikelnr, Artikels.Nummer, Artikels.artikelgroep, Verkoophandelingen.Datum, Klanten.Email');
            Query1.SQL.add('FROM Verkoop');
            Query1.SQL.add('full Join Artikels ON Verkoop.Artikelnr = Artikels.Nummer');
            Query1.SQL.add('full Join Klanten ON Verkoop.Klantnr = Klanten.Nummer');
            Query1.SQL.add('full Join Verkoophandelingen ON Verkoop.verkoophandelingnr = Verkoophandelingen.nummer');
            Query1.SQL.add('WHERE Verkoophandelingen.Type = "Bestelling" ');
            Query1.SQL.add('AND Verkoop.Artikelnr = :Search1');
            //Query1.SQL.add('AND Verkoophandelingen.Datum = '+ DateToStr(Date1) +'');
           Query1.SQL.add('AND Verkoophandelingen.Datum BETWEEN :datum AND :datumzoek');


            Query1.SQL.add('ORDER BY Datum');


            Query1.ParamByName('datumzoek').Value := datumzoek;
            Query1.ParamByName('datum').Value := datum;
            Query1.ParamByName('Search1').Value := Search1;

                Query1.RequestLive := true;
                  Query1.open;

          end
          else if Search2 <> EmptyStr then
          begin

            Query1.SQL.add('SELECT DISTINCT Verkoophandelingen.Klantnr, Verkoophandelingen.Type, verkoop.Klantnr, Verkoop.Artikelnr, Artikels.Nummer, Artikels.artikelgroep, Verkoophandelingen.Datum, Klanten.Email');
            Query1.SQL.add('FROM Verkoop');
            Query1.SQL.add('full Join Artikels ON Verkoop.Artikelnr = Artikels.Nummer');
            Query1.SQL.add('full Join Klanten ON Verkoop.Klantnr = Klanten.Nummer');
            Query1.SQL.add('full Join Verkoophandelingen ON Verkoop.verkoophandelingnr = Verkoophandelingen.nummer');
            Query1.SQL.add('WHERE Verkoophandelingen.Type = "Bestelling" ');
            Query1.SQL.add('AND Artikels.ArtikelGroep = :Search2');
            //Query1.SQL.add('AND Verkoophandelingen.Datum BETWEEN '+DateToStr(datum)+'');
            //Query1.SQL.Add('AND '+DateToStr(datumZoek)+'');

            Query1.SQL.add('AND Verkoophandelingen.Datum BETWEEN :datum AND :datumzoek');

            Query1.SQL.add('ORDER BY Datum');

            Query1.ParamByName('datumzoek').Value := datumzoek;
            Query1.ParamByName('datum').Value := datum;
            Query1.ParamByName('Search2').Value := Search2;

            Query1.RequestLive := true;
                  Query1.open;

        end;




      while not Query1.Eof do
 begin
      if Query1.FieldByName('Email').AsString <>  EmptyStr then
        begin
          memo1.Lines.Add(Query1.FieldByName('Email').AsString + ';');
          writeln(outfile, Query1.FieldByName('Email').AsString+ ';');
          Query1.next;
          inc(countmails);
        end

        else
          begin
            Query1.next;
          end;
 end;

  if Query1.Eof then
 begin
  CloseFile(outfile);
  memo1.lines.add('totaal aantal valid email adressen = ' + IntToStr(countmails));

 end;

end;





procedure TForm1.Edit1Change(Sender: TObject);
begin
Edit2.Text := '';
end;

procedure TForm1.Edit2Change(Sender: TObject);
begin
Edit1.Text := '';
end;


 end.

添加后

        ... 
        Query1.ParamByName('datumzoek').DataType := ftDate;
        Query1.ParamByName('datum').DataType := ftDate;
        Query1.ParamByName('Search1').DataType := ftInteger;

        Query1.ParamByName('datumzoek').Value := datumzoek;
        Query1.ParamByName('datum').Value := datum;
        Query1.ParamByName('Search1').Value := Search1;
        ...

查询运行但没有结果,在显示查询后,文本似乎参数有一个“?” 价值 ?

...
SELECT DISTINCT    Verkoophandelingen.Klantnr, Verkoophandelingen.Type, verkoop.Klantnr, Verkoop.Artikelnr, Artikels.Nummer, Artikels.artikelgroep, Verkoophandelingen.Datum, Klanten.Email
FROM Verkoop
full Join Artikels ON Verkoop.Artikelnr = Artikels.Nummer
full Join Klanten ON Verkoop.Klantnr = Klanten.Nummer
full Join Verkoophandelingen ON Verkoop.verkoophandelingnr = Verkoophandelingen.nummer
WHERE Verkoophandelingen.Type = "Bestelling"
AND Verkoop.Artikelnr = ?
AND Verkoophandelingen.Datum BETWEEN ? AND ?
ORDER BY Datum
...
4

1 回答 1

8

也许这些行会导致问题:

Query1.SQL.add('AND Verkoophandelingen.Datum BETWEEN '+DateTimeToStr(datum)+'');
Query1.SQL.Add('AND '+DateToStr(datumzoek)+'');

在这里,您插入由DateTimeToStrand返回的日期DateToStr,但您没有以任何方式分隔插入的值,因此生成的查询将如下所示:

...
AND Verkoophandelingen.Datum BETWEEN 21-04-2004
AND 22-04-2004
...

我不确定 Paradox 对日期常量使用什么分隔符,但我几乎可以肯定它确实使用了一些分隔符。也许,它应该是'

...
AND Verkoophandelingen.Datum BETWEEN '21-04-2004'
AND '22-04-2004'
...

检查手册以获取正确的手册并相应地修复您的代码。

另一方面,正如@Rob Kennedy 正确建议的那样,使用参数化查询会是一个更好的主意。在参数化查询中,您使用占位符,例如:name参数值应该放在哪里。因此,在您的情况下,它可能如下所示:

...
Query1.SQL.add('WHERE Verkoophandelingen.Type = "Bestelling" ');
Query1.SQL.add('AND Verkoop.Artikelnr = :Search');
Query1.SQL.add('AND Verkoophandelingen.Datum BETWEEN :date1');
Query1.SQL.Add('AND :date2');
...

在运行查询之前,您需要使用TQuery.Params属性设置参数,如下所示:

Query1.Params.CreateParam(ftInteger, 'Search', ptInput).AsInteger := StrToInt(Search1);
Query1.Params.CreateParam(ftDateTime, 'date1', ptInput).AsDateTime := datum;
Query1.Params.CreateParam(ftDateTime, 'date2', ptInput).AsDateTime := datumzoek;

Params或者,如果查询组件在分配 SQL 语句时自动填充集合:

Query1.Params.ParamByName('Search').AsInteger := StrToInt(Search1);
Query1.Params.ParamByName('date1').AsDateTime := datum;
Query1.Params.ParamByName('date2').AsDateTime := datumzoek;

这样你就不需要担心分隔值:组件会处理这个问题。

于 2013-01-30T12:52:39.340 回答