2010-11-24 2 views
1

Это продолжение вопроса, я спросил раньше: C#: How do I get the ID number of the last row inserted using InformixInformix: Как получить ROWID заявления последней вставки

Я пишу код в C# для вставки записей в Informix БД с использованием .NET Informix Водитель. Мне удалось получить идентификатор последней вставки, но в некоторых моих таблицах атрибут «serial» не используется. Я искал команду, похожую на следующую, но чтобы получить rowid вместо id.

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

И да, я понимаю, работа с ROWID опасна, поскольку она не является постоянным. Тем не менее, я планирую заставить приложение заставить клиентские приложения сбросить данные, если таблица изменена таким образом, что ряды были перегруппированы или что-то подобное.

+0

Можете ли вы выбрать rowid, используя последний идентификатор вставки в своем предложении where? – johnny 2010-11-24 19:48:50

+0

Ну, нет ... потому что в некоторых таблицах не используется тип «serial». Таким образом, он будет получать «0» во всех этих случаях. – 2010-11-24 20:41:00

ответ

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 во фрагментированную таблицу (обычно это виртуальный столбец). Затем вы должны использовать запрос выше. Это не рекомендуется, но опция есть.

Смежные вопросы