【问题标题】:Type mismatch in expression in Delphi 7 on SQL append在 SQL 追加的 Delphi 7 中的表达式类型不匹配
【发布时间】:2010-04-11 11:35:04
【问题描述】:

我有一个代码,它检查加载表单时的当前日期,执行简单的计算,并在 Delphi 中附加一条 SQL。它可以在带有 Delphi 7 的 Windows 7 和另一台带有 Xp 的计算机上运行,​​但不能在其他 3 台带有 Xp 的计算机上运行。加载表单时,它会显示“表达式中的类型不匹配”,并指向追加后的行。可能是什么问题?

procedure TfmJaunumi.FormCreate(Sender: TObject);
var d1, d2: TDate; 

begin  
 d1:= Date;  
 d2:= Date-30;  
 With qrJaunumi do
     begin
         Open;
         SQL.Append('WHERE Sanem_datums BETWEEN' + #39 + DateToStr(d1) +
         #39 + 'AND' + #39 + DateToStr(d2) + #39);
         Active := True; 
     end; 
end;

【问题讨论】:

  • 比较电脑上的区域设置,首先是日期格式
  • OT 我知道,但我就是不能忍受看着格式不正确的代码。如果我正在审查这个,我会让你修复缩进并将这些日期分配放在他们自己的行中. jcl.delphi-jedi.org/documents/styleguide.html#4.3
  • 使用参数而不是连接 SQL 语句。这使得切换连接层变得更加容易,并使 SQL 注入攻击更难成功。根据您的连接层,使用参数的语法略有不同。
  • 如果参数化查询不能解决问题,我会查看不同机器的客户端库版本号。
  • 您连接到什么数据库,使用什么类型的数据库连接(dbExpress、dbGo(TADOQuery 等)或 BDE)?

标签: sql delphi


【解决方案1】:

正如 robsoft 所说,这可能是国际化设置。您可以改用参数化查询 - 如果使用日期和时间,它们通常会更简单。

此外,在 with 开头之后的 Open 也不需要 - 事实上,它会在没有您添加的 WHERE 子句的情况下打开查询。

 procedure TfmJaunumi.FormCreate(Sender: TObject);

 var d1, d2: TDate; 

 begin  d1:= Date;  d2:= Date-30;  With
 qrJaunumi do
         begin
         SQL.Append('WHERE Sanem_datums BETWEEN :StartDate AND :EndDate');
         // exact expression will vary according to DB connection type.
         // Example is for TADOQuery.
         Parameters.ParamByName('StartDate').Value := d1;
         Parameters.ParamByName('EndDate').Value := d2;
         Active := True; 
         end; 
 end;

【讨论】:

    【解决方案2】:

    您可以使用准备好的语句来克服日期时间值的任何本地化问题。 DateToStr 取决于客户端。如果服务器的本地化不接受日期格式,FormatDateTime 可能会失败。

    procedure TfmJaunumi.FormCreate(Sender: TObject);
    var
      d1, d2: TDate;
    begin
      d1:= Date;
      d2:= Date - 30;
      //qrJaunumi.SQL.Clear; removed because it would remove the "SELECT ... FROM ..." part
      qrJaunumi.SQL.Add('WHERE Sanem_datums BETWEEN :StartDate AND :StopDate ');
      qrJaunumi.Prepared := True;
      qrJaunumi.ParamByName('StartDate').AsDateTime := d1;
      qrJaunumi.ParamByName('StopDate').AsDateTime := d2;
      qrJaunumi.Open; // = qrJaunumi.Active := True;
    end;
    

    ":StopDate" 后面的空格很重要,因为 Delphi 在参数解析器中存在错误,除非他们在较新的版本中修复它。

    【讨论】:

    • Andreas - 您需要删除 qrJaunumi.SQL.Clear;,否则我们将得到一个只有 WHERE 子句的查询。
    • @Gerry 是对的,但公平地说,@Andreas 编写了您通常希望看到的代码。 OP 似乎正在其他地方构建查询的第一部分,可能是在设计器中(不寒而栗)。 IMO,将设计时 SQL 与运行时 SQL 混合在一起是糟糕的设计。这只是一场等待发生的灾难,维护将是一个问题。
    【解决方案3】:

    这几乎肯定与这些计算机上的本地国际化设置有关 - DateToStr 将返回本地日期格式的字符串(可能是 MM/DD/YYYY 或 DD/MM/YYYY) - 取决于您所在的位置,这可能不是你所期待的。

    我怀疑您会发现它无法运行的计算机认为它们位于不同的国家/地区/使用与运行它的计算机不同的国际化设置。

    更好的解决方案是使用 FormatDateTime 将日期转换为您的 SQL Server 安装将接受的标准格式,因此任何本地“国际化”设置都不会像这样干扰。

    【讨论】:

    • 我检查了服务器设置,所有可以更改的日期格式,它们是相同的,但错误仍然没有消失。我什至尝试了各种 FormatDateTime 选项。还有什么可以解决这个问题的吗?
    • @Demonick - 好的,那么我们需要比较字符串。您能否在每种情况下都将 SQL.Strings 属性的内容发送到剪贴板? (将 ClipBrd 添加到您的 uses 子句,然后执行 Clipboard.AsText:=SQL.Text)。或者甚至只是 ShowMessage ——我们真的需要比较在工作和非工作案例之间生成的实际 SQL。 :-)
    【解决方案4】:

    很遗憾,上述方法均无效,但解决方案是将格式替换为“yy.mm.dd”。而不是“yyyy.mm.dd.”,并添加单引号。奇怪的是,它说格式是“yyyy.mm.dd”。到处。 现在的代码如下所示:

    procedure TfmJaunumi.FormCreate(Sender: TObject);
    var d1, d2: TDate; d3, d4, atd: String;
    
    begin
      d1:= Date;
      d3:= FormatDateTime('yy.mm.dd.',d1);
      d2:= Date-30;
      d4:= FormatDateTime('yy.mm.dd.',d2);
      atd := '''';
      With qrJaunumi do
        begin
          Open;
          SQL.Append('WHERE Sanem_datums BETWEEN'+ atd+d4+atd +'AND'+ atd+d3+atd+';');
          Active := True;
        end;
    end;
    

    【讨论】:

      【解决方案5】:

      您好,我遇到了同样的错误,并从 MS Support 找到了不同的解决方案:

      SQL.Text:='Delete * from TableName where((kno='+(inttostr(userNo))+')and(Sanem_datums >= # '+(FormatDateTime('mm-dd-yy',d1) )+' # ))';执行SQL;

      https://support.microsoft.com/en-us/kb/175258

      【讨论】:

      • 欢迎来到 Stack Overflow。请熟悉如何提出一个好问题 :) 请进行格式化,并将您的代码包装在代码部分中 :) 祝你好运 :)
      猜你喜欢
      • 2020-02-17
      • 2020-07-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多