使用 FireDac 仅更新重复行中的 1 个(无主键或唯一字段)

Posted

技术标签:

【中文标题】使用 FireDac 仅更新重复行中的 1 个(无主键或唯一字段)【英文标题】:Using FireDac to update only 1 of a duplicate row (no primary key or unique field) 【发布时间】:2019-06-20 16:35:56 【问题描述】:

我支持使用 Microsoft Access 数据库的旧应用程序。最初的表设计并没有为每个表添加主键。我正在开发一个迁移程序,其中包括在需要时添加和填写新的主键字段 (GUID)。

这分三个步骤发生:

    添加一个没有约束的新 guid 字段 用新的独特指南填写该字段 添加主键约束

我的问题是当表有重复行时设置唯一的 guid。这是我设置指南的代码。

  Query.SQL.Add('SELECT * FROM ' + TableName);
  Query.Open;

  while Query.Eof = false do
  begin
    Query.Edit;
    Query.FieldByName(NewPrimaryKeyFieldName).AsGuid := TGuid.NewGuid;
    Query.Post;

    Query.Next;
  end;

FireDac 生成一个更新语句,其中包含一个 where 子句,其中包含行中的所有原始字段/值(因为它没有唯一的字段可供使用)。但是,由于这些行是完全重复的,因此该语句仍会更新两行。

FireDac 正确错误地显示此消息

Update command updated [2] instead of [1] record.  

我可以在 Access 中打开数据库并删除重复的记录,或者通过编辑表格为它们分配唯一的 guid。我希望我的转换工具能够自动执行此操作。

有什么方法可以在 FireDac 中处理这些重复的行吗?一次只更新一个,还是只删除其中一个?

【问题讨论】:

我不认为这是可能的,但不确定,所以不回答。相反,首先添加一个自动编号字段以具有不同的标识符,并在分配 GUID 后将其删除 为什么要保留重复项?如果行确实重复(每个字段与其他记录具有相同的值),则使用聚合或 DISTINCT 查询来构建唯一值的数据集。从该数据集中制作表。消除旧表。将新表重命名为旧名称。 既然你想保留dups,我建议你将数据从db加载到数据集,然后清除表,添加主字段并使用数组DML再次填充刷新的数据。 @NasreddineGalfout 我不需要保留重复项。我也可以删除它们,但我想不出一种方法让 FireDac 删除除一个重复记录之外的所有重复记录。 【参考方案1】:

在我看来,仅使用一条 SQL 语句是无法做到的。

我会这样做: 1.使用新的临时表复制整个表而不重复

SELECT DISTINCT * FROM <TABLENAME>
    添加密钥 删除旧表格内容并从新表格复制新内容

注意事项:

对于该操作,其他人应该无法使用数据库 2.BACKUP之前

【讨论】:

我可以使用 sql 语句轻松删除表中的所有内容。但是如何让 FireDac 将原始查询中的记录视为插入而不是更新? SQL 对此负责。 Firedac 只是一个“工具”。你应该使用类似的东西:INSERT INTO dbo.EmployeeSales SELECT BusinessEntityID, SalesYTD FROM Sales.SalesPerson;

以上是关于使用 FireDac 仅更新重复行中的 1 个(无主键或唯一字段)的主要内容,如果未能解决你的问题,请参考以下文章

更新分隔行中的第 n 个元素 [unix 脚本]

KB4484218 更新后 FireDAC MSAcc ODBC 驱动程序损坏

无重复背包与有重复背包的不同应用

使用C++生成1-33中的6个随机数,无重复

ReactJS:仅更新嵌套状态对象中的特定字段[重复]

仅复制多个插入行中的公式