【问题标题】:I keep getting "Data type mismatch in criteria expression" error in delphi我在delphi中不断收到“标准表达式中的数据类型不匹配”错误
【发布时间】:2020-07-01 11:46:12
【问题描述】:

每当此代码运行时,我都会收到上述错误。该代码应该将一条记录插入到一​​个表中,然后从另一个表中删除记录。

for I := iMax - K to iMax do
begin
  Inc(a);
  with dmMenu.qryMcDonalds do
  begin
    SQL.Text :=
      'SELECT ID, ItemID, ItemPrice, ItemCategory FROM tblCheckout WHERE ID = ' + IntToStr(I);
    Open;
    sItemID := Fields[1].AsString;
    rItemPrice := Fields[2].AsFloat;
    sItemCategory := Fields[3].AsString;

    ShowMessage(IntToStr(I));
     // I get the error here
    SQL.Text :=
      'INSERT INTO tblOrderItems (OrderItemID, OrderID, ItemID, ItemCategory, ItemPrice) VALUES ("' + sOrderID + '_' + IntToStr(a) + '"' + ', "' + sOrderID + '", "' + sItemID + '", "' + sItemCategory + '", "' + FloatToStrF(rItemPrice, ffCurrency, 10, 2) + '")';
    ExecSQL;

    SQL.Text := 'DELETE FROM tblCheckout WHERE ID = ' + IntToStr(I); 
    ExecSQL;
  end; // with SQL 
end; // for I 

编辑:我认为问题出在“插入”部分。除最后一列外,所有列都是短文本,ItemPrice 是一种货币。我也在使用 Access

【问题讨论】:

  • 注意此代码可用于SQL injection
  • 我们看不到您的屏幕 - 错误发生在哪一行?如果是“INSERT INTO ...”,请将其替换为正确参数化的 INSERT 语句,您的问题将立即消失。
  • 顺便说一句,您使用的是什么 DBMS?
  • 停止在 cmets 中提供详细信息,并 edit 你的问题将它们放在那里。
  • 好的,我会在接下来的一个小时左右发布一个答案,显示插入的正确方法。

标签: sql delphi error-handling delphi-2010


【解决方案1】:

请在主窗体上仅使用以下项目开始一个新项目:

  • 一个 TAdoConnection 配置为连接到您的数据库;
  • 配置为使用 TAdoConnection 的 TAdoQuery
  • 配置为显示 TAdoQuery 内容的 TDataSource 和 TDBGrid。

然后,将以下代码添加到表单中

  const
    sSelect = 'select * from tblOrderItems';
    sInsert = 'insert into tblOrderItems(OrderItemID, OrderID, ItemID, ItemCategory, ItemPrice) '#13#10
    +  'values(:OrderItemID, :OrderID, :ItemID, :ItemCategory, :ItemPrice)';

    sOrderItemID = '0999';
    sOrderID = '1999';
    sItemID = '2999';
    sItemCategory = 'Bolt';
    fItemPrice = 5.99;

  procedure TForm2.FormCreate(Sender: TObject);
  begin

    AdoQuery1.SQL.Text := sInsert;
    AdoQuery1.Prepared := True;

    AdoQuery1.Parameters.ParamByName('OrderItemID').Value:= sOrderItemID;
    AdoQuery1.Parameters.ParamByName('OrderID').Value := sOrderID;
    AdoQuery1.Parameters.ParamByName('ItemID').Value := sItemID;
    AdoQuery1.Parameters.ParamByName('ItemCategory').Value := sItemCategory;
    AdoQuery1.Parameters.ParamByName('ItemPrice').Value := fItemPrice;

    AdoQuery1.ExecSQL;

    AdoQuery1.SQL.Text  := sSelect;
    AdoQuery1.Open;
  end;

在编译和运行程序之前,检查并更改常量的值 以免它们与表中已有的任何行发生冲突。

常量 sInsert 在 Values 内部定义了一个所谓的“参数化 SQL 语句” 列表中,项目 :OrderItemID、:OrderID 等是 AdoQuery 将变成的占位符 您可以在运行时提供其值的参数,如 AdoQuery1.Parameters.ParamByName(... 之后的块中的值

您应该始终以这种方式构造 SQL 语句,而 不应该通过连接字符串 正如您的代码尝试做的那样。它更不容易出错,因为它很容易进入 如果您使用 DIY 代码,语法混乱,它也确保您的查询不容易 到Sql-Injection exploits,如果你 让用户有机会编辑 SQL。

如果您使用的是 FireDAC FDQuery,则它具有 Params(FD 数据类型)而不是参数 但它们的工作方式几乎相同 - 请参阅在线帮助。

以后,请更加小心,以确保包含重要的详细信息,尤其是发生错误的 exact 行之类的内容 - 您可以使用调试器 - 以及您正在使用的确切 db-access 组件之类的东西。还要尝试获取详细信息,例如列是“短文本”类型还是自动编号。

对于一个需要调试的问题,比如这个,你还应该提供一个完整的,minimal, reproducible example,而不仅仅是一个sn-p的代码。很多时候,您会在准备 mre 时意识到问题所在,因此它对您和我们都有帮助。

【讨论】:

  • 当我在向数据库中添加新记录时在同一个实例中运行此代码时,我仍然遇到同样的问题。
  • 唏嘘,如果你在我要求你使用的独立项目中这样做呢?无论如何,我明天会考虑在 MDB 数据库中进行操作。我现在不能再花时间在这上面了。
  • 我想通了,谢谢。它适用于一个独立的项目,但我忘了在参数之一的末尾添加递增的整数。
  • 很好,很高兴您解决了问题。同时,我使用 Access2016 数据库检查了我的答案是否有效,并且效果很好。
【解决方案2】:

我敢打赌,问题在于不兼容的浮点格式。 使用参数来避免它。

【讨论】:

  • 已经提出并接受了一个答案,它提供了更多细节。请务必在提交新答案之前查看现有答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-09
  • 2013-12-23
  • 1970-01-01
  • 2021-08-16
  • 1970-01-01
相关资源
最近更新 更多