Informix:如何获取最后一条插入语句的rowid

发布于 2024-10-04 15:01:55 字数 489 浏览 4 评论 0原文

这是我之前问过的问题的扩展: C#:如何获取使用 Informix 插入的最后一行的 ID 号

我正在 C# 中编写一些代码,以使用 .NET Informix 驱动程序将记录插入 informix 数据库。我能够获取最后一次插入的 id,但在我的某些表中,未使用“串行”属性。我正在寻找类似于以下的命令,但要获取 rowid 而不是 id。

SELECT DBINFO ('sqlca.sqlerrd1') FROM systables WHERE tabid = 1;

是的,我确实意识到使用 rowid 是危险的,因为它不是常量。但是,如果表以重新排列 rowid 等方式更改,我计划让我的应用程序强制客户端应用程序重置数据。

This is an extension of a question I asked before: C#: How do I get the ID number of the last row inserted using Informix

I am writing some code in C# to insert records into the informix db using the .NET Informix driver. I was able to get the id of the last insert, but in some of my tables the 'serial' attribute is not used. I was looking for a command similar to the following, but to get rowid instead of id.

SELECT DBINFO ('sqlca.sqlerrd1') FROM systables WHERE tabid = 1;

And yes, I do realize working with the rowid is dangerous because it is not constant. However, I plan to make my application force the client apps to reset the data if the table is altered in a way that the rowids got rearranged or the such.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

初与友歌 2024-10-11 15:01:56

ROWID 的一个问题是它是 4 字节的数量,但在分段表上使用的值是 8 字节的数量(名义上为 FRAGID 和 ROWID),但 Informix 从未公开过 FRAGID。

理论上,SQLCA 数据结构在 sqlca.sqlerrd[5] 元素中报告 ROWID(假设 C 样式索引从 0 开始;它是 sqlca.sqlerrd[6]在 Informix 4GL 中,索引从 1) 开始。如果有任何东西可以与 DBINFO 一起使用,那就是 DBINFO('sqlca.sqlerrd5'),但我得到:

SQL -728: Unknown first argument of dbinfo(sqlca.sqlerrd5).

所以,使用 DBINFO 的间接方法尚未启用。在 ESQL/C 中,sqlca 随时可用,信息也可用:

SQL[739]: begin;
BEGIN WORK: Rows processed = 0
SQL[740]: create table p(q integer);
CREATE TABLE: Rows processed = 0
SQL[741]: insert into p values(1);
INSERT:  Rows processed = 1, Last ROWID = 257
SQL[742]: select dbinfo('sqlca.sqlerrd5') from dual;
SQL -728: Unknown first argument of dbinfo(sqlca.sqlerrd5).
SQLSTATE: IX000 at /dev/stdin:4
SQL[743]: 

我不是 C# 或 .NET 驱动程序的用户,所以我不知道是否存在后门获取信息的机制。即使在 ODBC 中,也可能没有前门机制来获取它,但您可以使用 C 代码来轻松读取全局数据结构:

#include <sqlca.h>
#include <ifxtypes.h>
int4 get_sqlca_sqlerrd5(void)
{
    return sqlca.sqlerrd[5];
}

或者,甚至:

int4 get_sqlca_sqlerrdN(int N)
{
    if (N >= 0 && N <= 5)
        return sqlca.sqlerrd[N];
    else
        return -22;  /* errno 22 (EINVAL): Invalid argument */
}

如果 C# 可以访问用 C 编写的 DLL,您可以打包就这样。

否则,识别数据行的批准方法是通过该行的主键(或任何其他唯一标识符,有时称为替代键或候选键)。如果您没有该行的主键或其他唯一标识符,那么您的生活就会很困难。如果它是复合键,则可以“工作”,但可能会不方便。也许您需要考虑向表中添加 SERIAL 列(或 BIGSERIAL 列)。

您可以使用:

SELECT ROWID
  FROM TargetTable
 WHERE PK_Column1 = <value1> AND PK_Column2 = <value2>

或类似的方法来获取 ROWID,前提是您可以准确地识别该行。

在最困难的情况下,有一种机制可以将物理 ROWID 列添加到碎片表中(通常,它是虚拟列)。然后您可以使用上面的查询。不建议这样做,但有这个选项。

One problem with ROWID is that it is a 4-byte quantity but the value used on a fragmented table is an 8-byte quantity (nominally FRAGID and ROWID), but Informix has never exposed the FRAGID.

In theory, the SQLCA data structure reports the ROWID in the sqlca.sqlerrd[5] element (assuming C-style indexing from 0; it is sqlca.sqlerrd[6] in Informix 4GL which indexes from 1). If anything was going to work with DBINFO, it would be DBINFO('sqlca.sqlerrd5'), but I get:

SQL -728: Unknown first argument of dbinfo(sqlca.sqlerrd5).

So, the indirect approach using DBINFO is not on. In ESQL/C, where sqlca is readily available, the information is available too:

SQL[739]: begin;
BEGIN WORK: Rows processed = 0
SQL[740]: create table p(q integer);
CREATE TABLE: Rows processed = 0
SQL[741]: insert into p values(1);
INSERT:  Rows processed = 1, Last ROWID = 257
SQL[742]: select dbinfo('sqlca.sqlerrd5') from dual;
SQL -728: Unknown first argument of dbinfo(sqlca.sqlerrd5).
SQLSTATE: IX000 at /dev/stdin:4
SQL[743]: 

I am not a user of C# or the .NET driver, so I have no knowledge of whether there is a back-door mechanism to get at the information. Even in ODBC, there might not be a front-door mechanism to get at it, but you could drop into C code to read the global data structure easily enough:

#include <sqlca.h>
#include <ifxtypes.h>
int4 get_sqlca_sqlerrd5(void)
{
    return sqlca.sqlerrd[5];
}

Or, even:

int4 get_sqlca_sqlerrdN(int N)
{
    if (N >= 0 && N <= 5)
        return sqlca.sqlerrd[N];
    else
        return -22;  /* errno 22 (EINVAL): Invalid argument */
}

If C# can access DLL's written in C, you could package that up.

Otherwise, the approved way of identifying rows of data is via the primary key (or any other unique identifier, sometimes known as an alternative key or candidate key) for the row. If you don't have a primary key or other unique identifier for the row, you are making life difficult for yourself. If it is a compound key, that 'works' but could be inconvenient. Maybe you need to consider adding a SERIAL column (or BIGSERIAL column) to the table.

You can use:

SELECT ROWID
  FROM TargetTable
 WHERE PK_Column1 = <value1> AND PK_Column2 = <value2>

or something similar to obtain the ROWID, assuming you can identify the row accurately.

In dire straights, there is a mechanism to add a physical ROWID column to a fragmented table (normally, it is a virtual column). You'd then use the query above. This is not recommended, but the option is there.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文