我有两张桌子:
OutputPackages(master)
|PackageID|
OutputItems(详细信息)
|ItemID|PackageID|
OutputItems在PackageID列上设置了一个名为“idxPackage”的索引。 ItemID设置为自动增量。
这是我用来在这些表中插入主人/细节的代码:
//fill packages table
for i := 1 to 10 do
begin
Package := TfPackage(dlgSummary.fcPackageForms.Forms[i]);
if Package.PackageLoaded then
begin
with tblOutputPackages do
begin
Insert;
FieldByName('PackageID').AsInteger := Package.ourNum;
FieldByName('Description').AsString := Package.Title;
FieldByName('Total').AsCurrency := Package.Total;
Post;
end;
//fill items table
for ii := 1 to 10 do
begin
Item := TfPackagedItemEdit(Package.fc.Forms[ii]);
if Item.Activated then
begin
with tblOutputItems do
begin
Append;
FieldByName('PackageID').AsInteger := Package.ourNum;
FieldByName('Description').AsString := Item.Description;
FieldByName('Comment').AsString := Item.Comment;
FieldByName('Price').AsCurrency := Item.Price;
Post; //this causes the primary key exception
end;
end;
end;
end;
只要我不搞乱IDE中的MasterSource / MasterFields属性,这就可以正常工作。但是一旦我设置它并运行此代码,我会收到一条错误消息,说我有一个重复的主键'ItemID'。
我不确定发生了什么 - 这是我第一次涉及到主/细节,所以可能会出现问题。我正在为这个项目使用ComponentAce的绝对数据库。
如何正确插入?
更新
好的,我删除了我的数据库中的主键约束,我看到由于某种原因,OutputItems表的自动增量功能不像我预期的那样工作。以下是运行上述代码后OutputItems表的外观:
ItemID|PackageID|
1 |1 |
1 |1 |
2 |2 |
2 |2 |
我仍然不明白为什么所有ItemID值都不是唯一的......有什么想法吗?
答案 0 :(得分:2)
使用insert而不是append在items表上的行为是否有所不同?我的猜测是细节上的附加“看到”一个空的数据集,所以自动递增逻辑从一个,下一个记录二开始,等等,即使这些值已被分配...只是为了一个不同的主记录
我过去使用的一个解决方案是创建一个名为UniqueNums的新表,该表持久存储我将要使用的下一个可用记录ID号。当我使用一个数字时,我会锁定该表,增加值并将其写回然后解锁并使用。这可能会让您了解您遇到的具体问题。
答案 1 :(得分:0)
首先,在我看来,通过代码冲突自动增量和设置ID的想法。明确的路径是在代码中自己生成密钥。特别是对于需要主/细节插入的多用户应用程序,很难无法为细节插入正确的密钥。
因此,按代码生成ID。设计表时,将ID字段设置为主键但不设置自动增量。如果我没有弄错,Append用于操作。
此外,您似乎在启用可视控件时进行迭代? (Item.Activated)。但该操作本质上是一个批处理过程。对于GUI性能,您应该考虑,禁用已连接的数据库控件,然后执行该操作。作为主/详细范围,这可能是另外两个游标没有按预期迭代的问题。
答案 2 :(得分:0)
您是否尝试使用编辑替换附加/插入?
并跳过“FieldByName('PackageID')。AsInteger:= Package.ourNum;”线。
我认为M / D关系会根据需要自动附加详细记录,还会设置详细信息表的主键。
这也可能是重复主键错误的原因。当您尝试追加/插入另一个时,记录已由M / D关系创建。