Dela via


Postuppsättning: Deklarera en klass för en fördefinierad fråga (ODBC)

Anmärkning

MFC ODBC-konsumentguiden är inte tillgänglig i Visual Studio 2019 och senare. Du kan fortfarande skapa en konsument manuellt.

Det här avsnittet gäller för MFC ODBC-klasserna.

Det här avsnittet beskriver hur du skapar en postuppsättningsklass för en fördefinierad fråga (kallas ibland för en lagrad procedur, som i Microsoft SQL Server).

Anmärkning

Det här avsnittet gäller för objekt som härleds från CRecordset där massradhämtning inte har implementerats. Om masshämtning av rader används, är processen väldigt lik. Information om skillnaderna mellan postuppsättningar som implementerar massradhämtning och de som inte gör det finns i Recordset: Fetching Records in Bulk (ODBC).

Med vissa databashanteringssystem (DBMS) kan du skapa en fördefinierad fråga och anropa den från dina program som en funktion. Sökfrågan har ett namn, kan ta parametrar och kan eventuellt returnera poster. Proceduren i det här avsnittet beskriver hur du anropar en fördefinierad fråga som returnerar poster (och kanske tar parametrar).

Databasklasserna stöder inte uppdatering av fördefinierade frågor. Skillnaden mellan en fördefinierad fråga för en ögonblicksbild och en fördefinierad dynasetfråga handlar inte om möjlighet till uppdatering, utan om huruvida ändringar gjorda av andra användare (eller andra postuppsättningar i ditt program) visas i din postuppsättning.

Tips/Råd

Du behöver inget dataset för att anropa en fördefinierad fråga som inte returnerar poster. Förbered SQL-instruktionen enligt beskrivningen nedan, men kör den genom att anropa CDatabase medlemsfunktionen ExecuteSQL.

Du kan skapa en enskild recordset-klass för att hantera att anropa en fördefinierad fråga, men du måste utföra en del av arbetet själv. Guiderna stöder inte att skapa en klass specifikt för detta ändamål.

Skapa en klass för att anropa en fördefinierad fråga (lagrad procedur)

  1. Använd MFC ODBC-konsumentguiden från Lägg till klass för att skapa en postuppsättningsklass för tabellen som bidrar med flest kolumner returnerade av frågan. Detta ger dig ett försprång.

  2. Lägg till fältdatamedlemmar manuellt för alla kolumner i tabeller som frågan returnerar men som guiden inte skapade åt dig.

    Om frågan till exempel returnerar tre kolumner var från två ytterligare tabeller lägger du till sex fältdatamedlemmar (av lämpliga datatyper) i klassen.

  3. Lägg till RFX-funktionsanrop manuellt i funktionen DoFieldExchange-medlem i klassen, en som motsvarar datatypen för varje tillagd fältdatamedlem.

    Immediately before these RFX calls, call <MSHelp:link keywords="_mfc_CFieldExchange.3a3a.SetFieldType" TABINDEX="0">SetFieldType</MSHelp:link>, as shown here:
    pFX->SetFieldType( CFieldExchange::outputColumn );
    

    Anmärkning

    Du måste känna till datatyperna och ordningen på kolumner som returneras i resultatuppsättningen. Ordningen för RFX-funktionsanrop i DoFieldExchange måste matcha ordningen på resultatuppsättningskolumnerna.

  4. Lägg till initieringar manuellt för de nya fältdatamedlemmarna i konstruktorn för postuppsättningsklassen.

    Du måste också öka initieringsvärdet för m_nFields datamedlem. Guiden skriver initieringen, men den täcker bara de fältdatamedlemmar som läggs till åt dig. Till exempel:

    m_nFields += 6;
    

    Vissa datatyper bör inte initieras här, till exempel CLongBinary bytematriser.

  5. Om frågan tar parametrar lägger du till en parameterdatamedlem för varje parameter, ett RFX-funktionsanrop för varje och en initiering för var och en.

  6. Du måste öka m_nParams för varje tillagd parameter, precis som för m_nFields tillagda fält i steg 4 i den här proceduren. Mer information finns i Recordset: Parameterizing a Recordset (ODBC).

  7. Skriv en SQL-instruktionssträng manuellt med följande formulär:

    {CALL proc-name [(? [, ?]...)]}
    

    där CALL är ett ODBC-nyckelord, proc-name är namnet på frågan så som det är känt i datakällan, och "?" objekten är platshållare för de parametervärden som du anger till postuppsättning vid körning (om några). Följande exempel förbereder en platshållare för en parameter:

    CString mySQL = "{CALL Delinquent_Accts (?)}";
    
  8. I koden som öppnar postuppsättningen anger du värdena för postuppsättningens parameterdatamedlemmar och anropar sedan Open medlemsfunktionen och skickar SQL-strängen för parametern lpszSQL. I stället ersätter du strängen som returneras av GetDefaultSQL-medlemsfunktionen i din klass.

I följande exempel visas proceduren för att anropa en fördefinierad fråga med namnet Delinquent_Accts, som tar en parameter för ett försäljningsdistriktsnummer. Den här frågan returnerar tre kolumner: Acct_No, L_Name, Phone. Alla kolumner kommer från tabellen Kunder.

Följande datamängd anger fältdata för kolumnerna som frågan returnerar och en parameter för det försäljningsdistriktsnummer som begärs vid körning.

class CDelinquents : public CRecordset
{
// Field/Param Data
    LONG m_lAcct_No;
    CString m_strL_Name;
    CString m_strPhone;
    LONG m_lDistParam;
    // ...
};

Den här klassdeklarationen är så trollkarlen skriver den, förutom m_lDistParam-medlemmen som läggs till manuellt. Andra medlemmar visas inte här.

I nästa exempel visas initieringarna för datamedlemmarna i CDelinquents konstruktorn.

CDelinquents::CDelinquents(CDatabase* pdb)
   : CRecordset(pdb)
{
    // Wizard-generated params:
    m_lAcct_No = 0;
    m_strL_Name = "";
    m_strPhone = "";
    m_nFields = 3;
    // User-defined params:
    m_nParams = 1;
    m_lDistParam = 0;
}

Observera initieringarna för m_nFields och m_nParams. Guiden initierar m_nFields; du initierar m_nParams.

I nästa exempel visas RFX-funktionerna i CDelinquents::DoFieldExchange:

void CDelinquents::DoFieldExchange(CFieldExchange* pFX)
{
    pFX->SetFieldType(CFieldExchange::outputColumn);
    RFX_Long(pFX, "Acct_No", m_lAcct_No);
    RFX_Text(pFX, "L_Name", m_strL_Name);
    RFX_Text(pFX, "Phone", m_strPhone);
    pFX->SetFieldType(CFieldExchange::param);
    RFX_Long(pFX, "Dist_No", m_lDistParam);
}

Förutom att utföra RFX-anrop för de tre returnerade kolumnerna, hanterar den här koden bindningen av den parameter du skickar under körning. Parametern är nyckelad till Dist_No kolumnen (distriktsnummer).

I exemplet nedan visar hur du ställer in SQL-strängen och hur du använder den för att öppna datamängden.

// Construct a CDelinquents recordset object
CDelinquents rsDel( NULL );
CString strSQL = "{CALL Delinquent_Accts (?)}"
// Specify a parameter value (obtained earlier from the user)
rsDel.m_lDistParam = lDistrict;
// Open the recordset and run the query
if( rsDel.Open( CRecordset::snapshot, strSQL ) )
    // Use the recordset ...

Den här koden konstruerar en ögonblicksbild, skickar den en parameter som hämtades tidigare från användaren och anropar den fördefinierade frågan. När sökfrågan körs returneras poster för det angivna försäljningsdistriktet. Varje post innehåller kolumner för kontonumret, kundens efternamn och kundens telefonnummer.

Tips/Råd

Du kanske vill hantera ett returvärde (utdataparameter) från en lagrad procedur. Mer information och ett exempel finns i CFieldExchange::SetFieldType.

Se även

Postuppsättning (ODBC)
Postuppsättning: Fråga om en postuppsättning (ODBC)
Postuppsättning: Deklarera en klass för en tabell (ODBC)
Recordset: Utföra en join (ODBC)