【问题标题】:Why do I get "Duplicate entry" exception when inserting a record?为什么插入记录时出现“重复条目”异常?
【发布时间】:2015-02-25 15:14:38
【问题描述】:

我收到此错误消息:

[FireDAC][Phys][MySQL] 键“PRIMARY”的重复条目“1111”

尝试将数据插入数据库时​​。数据库中唯一的数据是一个主键为“0000”的元组,所以我知道主键不是另一个键的副本。数据已正确插入数据库,那么当主键不重复时,有什么方法可以阻止错误弹出?

我正在使用 Delphi XE7、MySQL 6.2、FDConnectionFDQuery。我的代码是:

FDQuery1.SQL.Clear;
FDQuery1.SQL.Add(
  'Insert into Customer (' +
    'CustID,' +
    'Forename,' +
    'Surname,' +
    'Address,' +
    'PostCode' +
  ') ' +
  'Values (' +
    QuotedStr(CustID) + ',' + 
    QuotedStr(Forename) + ',' +
    QuotedStr(Surname) + ',' +
    QuotedStr(Address) + ',' +
    QuotedStr(Postcode) +
  ')'
);
FDQuery1.ExecSQL;
FDQuery1.Open;

【问题讨论】:

  • 我怀疑FDQuery1.Open; 调用再次执行INSERT 查询。为什么你有它?为什么不使用参数?如果您可以简单地分配Text,为什么还要使用ClearAdd,或者更好的是,准备语句并保持准备状态,只更改参数并调用ExecSQL
  • 为什么要指定ID而不是依赖MySQL的自增特性?
  • 摆脱FDQuery1.Open 工作谢谢
  • 进一步澄清:ExecSQL 用于NOT 返回行集的 SQL 语句,例如 INSERTUPDATEDELETEOpen 用于DO 返回行集的查询,例如SELECT。将有 ZERO 个实例,其中两者都适用,而无需更改方法执行之间的 SQL。

标签: mysql delphi delphi-xe7 firedac


【解决方案1】:

您正在执行相同的 SQL 语句两次。首先是ExecSQL,然后是Open。您应该只使用一个或另一个,具体取决于您的 SQL 语句是否实际返回任何结果。

在您的情况下,您编写了一个简单的INSERT 查询,因此ExecSQL 是正确的选择。请注意,如果您在此查询中使用 Open(没有 ExecSQL),您仍然会收到错误,因为“没有要打开的数据”(可以这么说)。

强调规则:如果 SQL 语句返回数据,则使用Open。这是一个示例,即使您的语句插入一行,您也可以Open

LQuery.SQL.Text :=
    'INSERT INTO Customer (CustId, CustomerName)'#13#10 +
    'VALUES ('+QuotedStr(ACustId)+','#13#10 +
               QuotedStr(ACustomerName)+');'#13#10 +
    'SELECT  CustId, CustomerName, DateAdded'#13#10 +
    'WHERE   CustId = '+QuotedStr(ACustId)
LQuery.Open;

如图所示,如果数据库分配了任何值(例如默认值、自动键、行版本),您可能希望在插入后立即返回新行。如果是这样的话,那么你应该使用Open

旁注:根据您的问题,我坚持使用动态查询。但是,通常建议使用参数化查询甚至存储过程。

【讨论】:

    猜你喜欢
    • 2022-01-19
    • 2021-06-29
    • 1970-01-01
    • 2019-08-24
    • 1970-01-01
    • 1970-01-01
    • 2014-09-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多