为什么插入记录时出现 "Duplicate entry" 异常?
Why do I get "Duplicate entry" exception when inserting a record?
我收到此错误消息:
[FireDAC][Phys][MySQL] Duplicate entry '1111' for key 'PRIMARY'
尝试将数据插入数据库时。数据库中唯一的数据是一个主键为“0000”的元组,所以我知道主键不是另一个键的副本。数据已正确插入数据库,那么当主键不重复时,有什么方法可以阻止弹出错误?
我正在使用 Delphi XE7、MySQL 6.2、FDConnection
和 FDQuery
。我的代码是:
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;
您正在执行相同的 SQL 语句两次。首先是 ExecSQL
,然后是 Open
。您应该只使用 一个或另一个 取决于您的 SQL 语句是否确实 return 任何结果。
在您的例子中,您编写了一个简单的 INSERT
查询,因此 ExecSQL
是正确的选择。请注意,如果您在此查询中使用 Open
(没有 ExecSQL
),您仍然会收到错误消息,因为存在 "no data to open"(可以这么说)。
强调规则:如果SQL语句returns数据,则使用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;
如图所示,如果数据库分配了任何值(例如默认值、自动键、行版本),您可能希望在插入后立即 return 新行。如果是这样,那么您应该使用 Open
.
SIDE NOTE: I've stuck with a dynamic query as per your question. However, it's generally advisable to go with a parametrised query or even stored procedure.
我收到此错误消息:
[FireDAC][Phys][MySQL] Duplicate entry '1111' for key 'PRIMARY'
尝试将数据插入数据库时。数据库中唯一的数据是一个主键为“0000”的元组,所以我知道主键不是另一个键的副本。数据已正确插入数据库,那么当主键不重复时,有什么方法可以阻止弹出错误?
我正在使用 Delphi XE7、MySQL 6.2、FDConnection
和 FDQuery
。我的代码是:
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;
您正在执行相同的 SQL 语句两次。首先是 ExecSQL
,然后是 Open
。您应该只使用 一个或另一个 取决于您的 SQL 语句是否确实 return 任何结果。
在您的例子中,您编写了一个简单的 INSERT
查询,因此 ExecSQL
是正确的选择。请注意,如果您在此查询中使用 Open
(没有 ExecSQL
),您仍然会收到错误消息,因为存在 "no data to open"(可以这么说)。
强调规则:如果SQL语句returns数据,则使用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;
如图所示,如果数据库分配了任何值(例如默认值、自动键、行版本),您可能希望在插入后立即 return 新行。如果是这样,那么您应该使用 Open
.
SIDE NOTE: I've stuck with a dynamic query as per your question. However, it's generally advisable to go with a parametrised query or even stored procedure.