Informix: Как да получите реда на последния израз за вмъкване

Това е разширение на въпрос, който зададох преди: C#: Как да получа идентификационния номер на последния вмъкнат ред с помощта на Informix

Пиша някакъв код на C# за вмъкване на записи в informix db с помощта на .NET Informix драйвера. Успях да получа идентификатора на последното вмъкване, но в някои от моите таблици атрибутът "serial" не се използва. Търсих команда, подобна на следната, но за получаване на rowid вместо id.

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

И да, осъзнавам, че работата с rowid е опасна, защото не е постоянна. Планирам обаче да накарам приложението си да принуди клиентските приложения да нулират данните, ако таблицата е променена по начин, по който редовете са пренаредени или нещо подобно.


person myermian    schedule 24.11.2010    source източник
comment
Можете ли да изберете rowid, като използвате последния идентификатор на вмъкване във вашата клауза where?   -  person johnny    schedule 24.11.2010
comment
Е, не... защото някои таблици не използват типа "serial". Така че ще получи обратно '0' във всички тези случаи.   -  person myermian    schedule 24.11.2010


Отговори (1)


Един проблем с ROWID е, че това е 4-байтово количество, но стойността, използвана на фрагментирана таблица, е 8-байтово количество (номинално FRAGID и ROWID), но Informix никога не е излагал FRAGID.

На теория структурата на данните SQLCA отчита ROWID в елемента sqlca.sqlerrd[5] (приемайки индексиране в стил 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# има достъп до DLL, написани на C, можете да го пакетирате.

В противен случай одобреният начин за идентифициране на редове от данни е чрез първичния ключ (или всеки друг уникален идентификатор, понякога известен като алтернативен ключ или ключ кандидат) за реда. Ако нямате първичен ключ или друг уникален идентификатор за реда, затруднявате живота си. Ако е сложен ключ, това „работи“, но може да е неудобно. Може би трябва да помислите за добавяне на колона SERIAL (или колона BIGSERIAL) към таблицата.

Можеш да използваш:

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

или нещо подобно, за да получите ROWID, ако приемете, че можете да идентифицирате точно реда.

При дире стрейт има механизъм за добавяне на физическа колона ROWID към фрагментирана таблица (обикновено това е виртуална колона). След това ще използвате заявката по-горе. Това не е препоръчително, но опцията е налице.

person Jonathan Leffler    schedule 27.11.2010
comment
Ако тръгна по пътя на използване на C код, има ли нещо извън този код, което ще ми трябва? Знам, че C# може да използва DllImport(...) за извършване на повиквания към неуправляем код, но се чудя няма ли C кодът да трябва да има препратка към Informix връзката или Informix командата, която изпълнява? - person myermian; 29.11.2010
comment
@myermian: Не знам е краткият отговор... вероятно ще трябва да компилирате с флаговете за нишки (esql -thread ... в Unix; вероятно същото в Windows), така че sqlca да бъде картографирана към функцията който връща (специфичен за нишка) указател към sqlca структура. Вероятно обаче няма да имате нужда от нищо друго; ще бъде извикан в контекста на нишка и ще (трябва) да ви даде стойността, свързана с вашата нишка. - person Jonathan Leffler; 30.11.2010