2010-11-24 6 views
1

Dies ist eine Erweiterung einer Frage, die ich vor gefragt: C#: How do I get the ID number of the last row inserted using InformixInformix: Wie die Nummer der letzten Insert-Anweisung erhalten

ich einige Code in C# schreibe Datensätze in die Informix db einfügen .NET Informix verwenden Treiber. Ich konnte die ID der letzten Einfügung erhalten, aber in einigen meiner Tabellen wird das Attribut 'seriell' nicht verwendet. Ich suchte nach einem Befehl ähnlich dem folgenden, aber um rowid statt ID zu bekommen.

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

Und ja, ich erkennen, mit dem Rowid Arbeit gefährlich ist, weil es nicht konstant ist. Ich beabsichtige jedoch, meine Anwendung dazu zu zwingen, die Client-Apps dazu zu zwingen, die Daten zurückzusetzen, wenn die Tabelle so geändert wird, dass die Zeilengruppen neu angeordnet wurden oder dergleichen.

+0

Können Sie die Rowid mit der letzten Einfüge-ID in Ihrer Where-Klausel auswählen? – johnny

+0

Nun, nein ... weil einige Tabellen nicht den 'seriellen' Typ verwenden. So würde es bekommen ‚0‘ zurück in all jenen Fällen. –

Antwort

1

Ein Problem mit ROWID ist, dass es eine 4-Byte-Menge ist, aber der Wert für eine fragmentierte Tabelle ist eine 8-Byte-Menge (nominal FRAGID und ROWID), aber Informix hat FRAGID nie ausgesetzt.

Theoretisch meldet die SQLCA-Datenstruktur die ROWID im sqlca.sqlerrd[5]-Element (unter der Annahme, dass C-style-Indexierung von 0; sqlca.sqlerrd[6] in Informix 4GL von 1 indiziert). Wenn irgendetwas mit DBINFO funktionieren würde, wäre es DBINFO('sqlca.sqlerrd5') sein, aber ich bekomme:

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

also der indirekte Ansatz DBINFO ist nicht auf. In ESQL/C, wo sqlca leicht verfügbar ist, sind die Informationen zur Verfügung zu:

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]: 

Ich bin kein Benutzer von C# oder .NET-Treiber, so dass ich keine Kenntnis davon, ob eine Hintertür gibt es Mechanismus, um an die Informationen zu gelangen. Auch in ODBC, kann es keinen Fronttürmechanismus sein, um es zu bekommen, aber man konnte in C-Code fällt die globale Datenstruktur leicht genug zu lesen:

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

Oder auch:

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

Wenn C# auf DLLs zugreifen kann, die in C geschrieben sind, können Sie das Paket zusammenstellen.

Andernfalls wird die genehmigte Weise Datenzeilen zu identifizieren, ist über den Primärschlüssel (oder eine andere eindeutige Kennung, die manchmal als Alternativen Schlüssel oder Kandidatenschlüssel bekannt) für die Zeile. Wenn Sie keinen Primärschlüssel oder eine andere eindeutige Kennung für die Zeile haben, machen Sie sich das Leben schwer. Wenn es sich um einen zusammengesetzten Schlüssel handelt, "funktioniert" das, könnte aber unbequem sein. Vielleicht müssen Sie eine Tabelle SERIAL (oder BIGSERIAL) hinzufügen.

können Sie verwenden:

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

oder etwas ähnliches, die ROWID zu erhalten, können Sie unter der Annahme, genau die Zeile identifizieren kann.

In dire Geraden gibt es einen Mechanismus ist eine physikalische ROWID Spalte zu einer fragmentierten Tabelle (in der Regel, es ist eine virtuelle Spalte) hinzuzufügen. Sie würden dann die obige Abfrage verwenden. Dies wird nicht empfohlen, aber die Option ist da.

+0

Wenn ich den Weg der Verwendung von C-Code gehe, gibt es etwas, das über diesen Code hinausgeht, den ich benötigen würde? Ich weiß, dass C# DllImport (...) verwenden kann, um unmanaged Code aufzurufen, aber ich frage mich, ob der C-Code nicht einen Verweis auf die Informix-Verbindung oder den Informix-Befehl haben muss, den er ausführt? –

+0

@myermian: Ich weiß nicht, ist die kurze Antwort ... Sie müssten wahrscheinlich mit den Threading-Flags kompilieren (esql-Threads ... unter Unix; wahrscheinlich das gleiche unter Windows), so dass sqlca dem zugeordnet ist Funktion, die einen (Thread-spezifischen) Zeiger auf eine Sqlca-Struktur zurückgibt. Sie würden jedoch wahrscheinlich nichts anderes brauchen; Es würde im Kontext eines Threads aufgerufen werden und würde Ihnen den Wert geben, der mit Ihrem Thread verknüpft ist. –

Verwandte Themen