从 Delphi 应用识别 Interbase table 中更改的行

Identifying changed rows in an Interbase table from a Delphi app

我知道我可以在应用程序中使用 TIBEvents 对象来接收发布的事件 通过使用 POST_EVENT.

的 Interbase 服务器

通过在 IB 数据库上设置触发器,我可以使用这种机制来获取通知 何时 行被更新、插入或删除,但不涉及哪些行。阻止它识别行的是事件名称需要的事实 由 IBEvents 对象预先知道。尽管 IBEvents 对象(或者更可能是 POST_EVENT 机制)存在这种限制,是否有一种简单的方法来进行这种识别?

巧合的是,我最近一直在研究这个话题,今天我偶然发现了 一个原生的 Interbase 解决方案,使用一个相对较新的特性,称为 Change Views(参见 Stephen Ball 的博客在 https://delphiaball.co.uk/2015/02/06/interbase-change-views-part-1/.

上进行了介绍

本质上,这涉及在服务器上设置一个 "subscription",它定义了哪些 table 和操作的种类(更新插入和删除),授予用户订阅的权利 订阅,然后设置客户端应用程序以利用这些信息 来自订阅。

Change Views 的一个好处是它们可以与传统的 IBX 一起使用 只有几行代码的组件 - 请参见下面的示例。我没试过,但看不到任何 只要它们支持,它们就不能与 DBExpress 或 FireDAC 一起使用的原因 将交易类型设置为 "Snapshot".

几条皱纹:

  • 除非您回滚检索更改的事务(根据代码 下面),下次您查看订阅时,您将看不到您看到的更改 上次。如果下次只想查看后续更改,请在 Select 查询上调用 Commit 而不是 Rollback。

  • 订阅实现隐藏了对 table(s) 的更改 自己的登录 ID,因此对于设置和测试,您需要使用不同的登录名,一个 进行更改,另一个查看更改。

代码:

procedure TForm1.OpenQuery;
var
  Sql : String;
begin
  //  Note that it is VITAL for the SELECT to return the desired results
  //  that the transaction type is set to "Snapshot", which can be done in the IDE
  //  using the Transaction Editor or in code as follows

  IBTransaction1.Params.Clear;
  IBTransaction1.Params.Add('concurrency');
  IBTransaction1.Params.Add('nowait');

  //  Next, activate the subscription
  Sql := 'SET SUBSCRIPTION "TABLE1CHANGES" ACTIVE;';
  IBQuery1.SQL.Text := Sql;
  IBQuery1.ExecSQL;

  //  Now we can retrieve the changed rows.  Note the "where" clause
  Sql := 'SELECT id, aname, avalue FROM table1 where aname is changed';  // or "is updated", 
  //  inserted, or deleted
  IBQuery1.SQL.Text := Sql;
  IBQuery1.Open;

end;

Delphi apps 任何应用程序中的动态 Sql 一样,提防 SQL 注入。

更新: 显然 Interbase Express (IBX) 组件库已更新以支持订阅,我假设在西雅图(我有但没有使用)。