2016-04-15 23 views
0

Ich schreibe einen C++ Code, der irgendwann die ID der zuletzt eingefügten Zeile bekommen muss.Oracle OCI bekomme ID der zuletzt eingefügten Zeile

Basierend auf this link here habe ich diesen Code, aber es ist nur Müll (ungültige Zeichen) Rückkehr:

std::string sql = "INSERT INTO MYTABLE (FIELD_A, FIELD_B) VALUES (10, 20)"; 

    OCIStmt *stmthp; 
    int sts = OCIHandleAlloc((dvoid *) envhp, (dvoid **) &stmthp, OCI_HTYPE_STMT, (size_t) 0, (dvoid **) 0); 
    CheckOracleError(sts); 

    sts = OCIStmtPrepare(stmthp, errhp, (const OraText *) sql.c_str(), (ub4) sql.size(), (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT); 
    CheckOracleError(sts); 

    sts = OCIStmtExecute(svchp, stmthp, errhp, (ub4) 1, (ub4) 0, (CONST OCISnapshot *) NULL, (OCISnapshot *) NULL, OCI_COMMIT_ON_SUCCESS); 

    if (sts != OCI_NO_DATA && sts != OCI_SUCCESS) 
     CheckOracleError(sts); 


    OraText rowID[19]; // Extra char for null termination. 
    ub2 size = 18; 
    OCIRowid *pRowID; 
    std::memset(rowID, 0, 19); // Set to all nulls so that string will be null terminated. 
    OCIDescriptorAlloc(envhp, (void**)&pRowID, OCI_DTYPE_ROWID, 0, NULL); 
    OCIAttrGet(stmthp, OCI_HTYPE_STMT, pRowID, 0, OCI_ATTR_ROWID, errhp); 
    OCIRowidToChar(pRowID, rowID, &size, errhp); 

    OCIHandleFree(stmthp, OCI_HTYPE_STMT); 

Irgendwelche Ideen auf, wie man es beheben?

+1

'ROWID' ist eine [Pseudospalte von Oracle generiert] (https://docs.oracle.com/cd/B19306_01/server.102/b14200/pseudocolumns008.htm) und ist ** NICHT ** ein Primärschlüssel für die Tabelle, wie sie geändert werden kann, wenn die Daten gelöscht und neu eingegeben werden oder wenn die Zeilenbewegung aktiviert ist. Sie sollten einen Primärschlüssel für Ihre Tabelle haben, der vorzugsweise von einer Sequenz generiert wird, oder in 12c eine Identitätsspalte. – MT0

+0

Hummm. Ich habe es .... Eigentlich ** ICH HABE ** einen Primärschlüssel namens * ID *, die von einer Sequenz generiert wird. Ich muss diese ID aus der letzten eingefügten Zeile holen, nicht die ROWID .... Wie soll ich das machen? – Mendes

Antwort

2

Wenn Sie eine Tabelle:

CREATE TABLE mytable (
    ID  INT PRIMARY KEY, 
    FIELD_A INT, 
    FIELD_B INT 
); 

Sie eine Sequenz erstellen:

CREATE SEQUENCE mytable__id__seq; 

Dann können Sie alle Einsätze über ein Verfahren tun (und ein Paket zu einer Gruppe können alle Funktionen zum Erstellen/Lesen/Aktualisieren/Löschen zusammen an einer Stelle), dann können Sie RETURNING .. INTO .. innerhalb des Pakets verwenden und den Wert aus einer out-Variablen erhalten:

CREATE OR REPLACE PACKAGE mytable_pkg 
AS 
    PROCEDURE add(
    i_field_a IN MYTABLE.FIELD_A%TYPE, 
    i_field_b IN MYTABLE.FIELD_B%TYPE, 
    o_id  OUT MYTABLE.ID%TYPE 
); 

    -- PROCEDURE edit(...); 
    -- PROCEDURE del(...); 
END mytable_pkg; 
/


CREATE OR REPLACE PACKAGE BODY mytable_pkg 
AS 
    PROCEDURE add(
    i_field_a IN MYTABLE.FIELD_A%TYPE, 
    i_field_b IN MYTABLE.FIELD_B%TYPE, 
    o_id  OUT MYTABLE.ID%TYPE 
) 
    AS 
    BEGIN 
    INSERT INTO mytable (
     id, 
     field_a, 
     field_b 
    ) VALUES (
     mytable__id__seq.NEXTVAL, 
     i_field_a, 
     i_field_b 
    ) 
    RETURNING id INTO o_id; 
    END add; 

    -- PROCEDURE edit(...); 
    -- PROCEDURE del(...); 
END mytable_pkg; 
/

Dann können Sie die gespeicherte Prozedur mit OCI aufrufen und nur den gebundenen Wert aus dem out-Parameter verwenden. Es gibt viele Beispiele (d. H. here und here), auf die Sie sich beziehen können.

+0

Wann/wie planen Sie, diese ID zu verwenden? Beachten Sie, dass jeder Wert, der für eine PK (oder irgendetwas anderes) verwendet wird, (1) für andere Sitzungen erst nach COMMIT angezeigt wird und (2) für immer verloren geht, wenn die einfügende Transaktion zurückgesetzt wird. – EdStevens