gpt4 book ai didi

delphi - 如何修复 'Unable to find record. No key specified' ?

转载 作者:行者123 更新时间:2023-12-03 18:25:40 26 4
gpt4 key购买 nike

我正在使用 firebird 2.5 服务器写入数据库文件 (BD.fbd)。我的 delphi XE8 项目有一个数据模块 (DMDados):

  • SQLConnection (conexao)

  • TSQLQUery1 (QueryBDPortico_Inicial) + TDataSetProvider1 (DSP_BDPortico_Inicial) + TClientDataSet1 (cdsBDPortico_Inicial)

  • TSQLQUery2 (QueryConsulta)(仅用于 SQL 字符串)

我的数据库文件有这个表:

  • PORTICO_INICIAL

该表有这些字段(全部为整数):

  • NPORTICO

  • 元素

  • ID

这些字段都不是主键,因为在某些情况下我会有重复的值。与文件的连接是好的。当我运行代码时,客户端数据集是打开的。 TSQLQUery2 (QueryConsulta) 在需要时打开。

我的代码,当被一个按钮触发时,必须删除所有表的记录(如果存在的话)然后用循环创建的整数填充表。在第一次尝试时,代码工作正常,但是当我第二次按下按钮时,出现错误“无法找到记录”。没有指定键”然后当我检查记录时表是空的。

我试图更改查询的 ProviderFlags 但这没有任何区别。我检查了字段名、表名或一些 SQL 文本错误,但什么也没找到。我怀疑当我的代码删除记录时,旧值保留在内存中,然后当尝试使用新值应用更新时,数据库使用旧值来查找新记录的位置,因此导致此错误。

    procedure monta_portico ();
var
I,K,L,M, : integer;
begin
with DMDados do
begin
QUeryCOnsulta.SQL.Text := 'DELETE FROM PORTICO_INICIAL;';
QueryConsulta.ExecSQL();
K := 1;
for I := 1 to 10 do
begin
L := I*100;
for M := 1 to 3 do
begin
cdsBDPortico_Inicial.Insert;
cdsBDPortico_Inicial.FieldbyName('NPORTICO').AsInteger :=
M+L;
cdsBDPortico_Inicial.FieldbyName('ELEMENTO').AsInteger := M;
cdsBDPortico_Inicial.ApplyUpdates(0);
K := K +1;
end;
end;
end;
end;

我希望每次使用上面的代码时,它首先删除表中的所有记录,然后用循环再次填充它。当我第一次使用该代码时,它会按照我的意愿进行操作,但在第二次时,它只会删除记录,无法用值填充表格。

最佳答案

更新 我在下面添加了一些示例代码。另外,当我写这个答案的原始版本时,我忘记了其中一个 TDataSetProvider 选项是poAllowMultiRecordUpdates,但我不确定这与您的问题有关。

错误消息无法找到记录。 No key specified 是由 DataSetProvider 生成的,因此没有直接连接到您的

QUeryCOnsulta.SQL.Text := 'DELETE FROM PORTICO_INICIAL;'

因为它绕过了 DataSetProvider。该错误来自于对 CDS 的 ApplyUpdates 尝试失败。尝试将您对它的调用更改为

Assert(cdsBDPortico_Inicial.ApplyUpdates(0) = 0);

这将在错误发生时向您显示,因为 ApplyUpdates 的返回结果给出了调用它时发生的错误数。

你说

will have repeated values in some cases

如果出现问题时确实如此,那是因为您遇到了 DataSetProvider 工作方式的基本限制。要在源数据集上应用更新,它必须生成 SQL 以发送回源数据集 (TSqlQuery1),它唯一标识源数据中要更新的行,如果源数据集是不可能的包含重复的行。

基本上,您需要重新考虑您的代码,以便源数据集的行都是唯一的。完成后,将 DSP 的 UpdateMode 设置为 upWhereAll 应该可以避免该问题。当然,源数据集最好有一个主键。

一个快速的解决方法是在您插入记录的循环中使用 CDS.Locate,看看它是否可以找到一个已经存在的记录以及您要添加的值。

顺便说一句,很抱歉提出有关 ProviderFlags 的问题。如果存在重复的行,则无关紧要,因为无论将它们设置为什么,DSP 仍然无法更新单个记录。

如果有帮助,这里有一些代码可能有助于填充您的表格以一种避免重复的方式。它只填充前两个列,如您在 q 中显示的代码。

function RowExists(ADataset : TDataSet; FieldNames : String; Values : Variant) : Boolean;
begin
Result := ADataSet.Locate(FieldNames, Values, []);
end;

procedure TForm1.PopulateTable;
var
Int1,
Int2,
Int3 : Integer;
i : Integer;
RowData : Variant;
begin
CDS1.IndexFieldNames := 'Int1;Int2';
for i := 1 to 100 do begin
Int1 := Round(Random(100));
Int2 := Round(Random(100));
RowData := VarArrayOf([Int1, Int2]);
if not RowExists(CDS1, 'Int1;Int2', RowData) then
CDS1.InsertRecord([Int1, Int2]);
end;
CDS1.First;
Assert(CDS1.ApplyUpdates(0) = 0);
end;

关于delphi - 如何修复 'Unable to find record. No key specified' ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55479887/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com