ClientDataSet中的“密钥违规”自动增量字段[Delphi]

时间:2010-02-20 17:17:36

标签: database delphi dbgrid

这是我的第三个问题,到目前为止优秀的回应^^

我在浏览,编辑数据方面没有任何问题,但是插入......

这是我的疑问: 在财务/股票软件中,我有一个表单来创建新订单,
当然我需要在 t_orders 表中插入一个新行 并在 t_orderitems 表中插入项目, orderId 字段链接到 t_orders

中的行
CREATE TABLE `t_orders` (
    `orderId` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
    `clientId` INT(10) UNSIGNED NOT NULL,
    ...)

CREATE TABLE `t_orderitems` (
    `orderitemId` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
    `orderId` INT(10) UNSIGNED NOT NULL,
    ...)

--> INDEXES AND FOREIGN KEYS OMITTED <--

如何将项目订单添加到网格中,最后在“FinalizeOrder”按钮中单击

  • t_orders
  • 中创建订单
  • t_orderitems 中插入与该订单关联的项目

使用ADO进行连接。

我不确定是否可以这样做,在这种情况下,我该怎么做?

编辑:我尝试使用嵌套的ClientDataSets,它在部分工作,但我仍然不知道如何获取插入的订单ID

EDIT2:
现在我有另一个问题,我不能在ClientDataSet中添加多个项目 因为OrderItemId对于所有项目都是空的(我只能在数据库插入时获得该值),当我尝试添加第二项时,它会给我关键违规,任何想法?

如果我将Updatemode设置为与upWhereKeyOnly不同的东西并将pfInKey设置为False它可以工作,但我不认为这是一个选项

任何想法?

提前致谢!
亚瑟。

4 个答案:

答案 0 :(得分:1)

我假设您有一个ADO数据集,它从您的数据库获取数据并链接到网格?你需要做的是一个中间层。

创建TClientDataset并将其连接到ADO数据集,然后将网格连接到客户端数据集。当新订单进入时,在客户端数据集上调用Append并将新订单的数据插入其中。这将使它显示在网格上。如果要将更改保存到数据库,请在客户端数据集上调用.Update。它使用它链接的ADO数据集将更新发送到DB。查看TClientDataset上的文档,了解如何设置全部内容;这是最近版本中为数不多的几件事实际记录得非常好。

要更新多个表,请查看有关主/明细关系的文档,并使用这样的两个数据集,相互链接。

答案 1 :(得分:1)

如果在应用程序中的两个数据集之间建立主 - 详细信息关系,ADO可以自动处理它。这意味着,一旦您将新记录插入主数据集(订单),您就可以在详细数据集(order_items)中插入新记录,而无需指定order_id,因为将自动检索主数据集中当前记录的order_id,以及插入新插入的详细数据集记录中。

要在数据集之间建立主/详细信息关系,如果使用AdoTable作为详细数据集,则可以将其MasterSource设置为连接到主数据集的数据源,并使用MasterFields属性定义两个数据集之间的关联关系。 如果您使用的是AdoDataset或AdoQuery,则应将详细数据集中的DataSource属性设置为连接到主数据集的数据源。然后,您必须使用与主数据集中的关键字段同名的SQL参数在详细数据集的SQL语句中添加WHERE子句。在你的情况下,它将是这样的:

SELECT * FROM t_orderitems WHERE OrderID = :OrderID

现在,您可以在详细数据集的MasterFields属性中设置关系。

由于您的订单可以包含多个项目,因此您可以在详细数据集(order_items)中将LockType设置为ltBatchOptimistic,这样一旦您插入新项目,它就不会立即发送到数据库。使用ltBatchOptimistic意味着您的更改将暂时保存在客户端内存中,直到您调用UpdateBatch方法。 UpdateBatch将所有更改发送到数据库。

如果要取消订单,则必须调用CancelBatch方法取消对详细数据集执行的修改,并手动删除主数据集中创建的订单记录。

答案 2 :(得分:0)

感谢RRUZ,这不是我想要的(我仍然需要在插入之前手动设置所有orderitem OrderId),但是会这样做

with DataModule1.ADOQuery1 do
begin
  SQL.Text := 'SELECT LAST_INSERT_ID()';
  Open();
  First();
  LastInsertId := Fields[0].Value;
  Close();
end;

答案 3 :(得分:0)