Megosztás:


Paramétertömbök kötése

A paramétertömböket használó alkalmazások az SQL-utasítás paramétereihez kötik a tömböket. Két kötési stílus létezik:

  • Minden paraméterhez egy tömböt kössön. Minden adatstruktúra (tömb) egyetlen paraméter összes adatát tartalmazza. Ezt oszlopalapú kötésnek nevezik, mert egyetlen paraméterhez egy értékoszlopot köt össze.

  • Definiáljon egy struktúrát, amely egy teljes paramétercsoport paraméteradatait tárolja, és összefűz egy tömböt ezekből a struktúrákból. Minden adatstruktúra egyetlen SQL-utasítás adatait tartalmazza. Ezt sorszintű kötésnek nevezik, mert egy sor paramétert köt össze.

Amikor az alkalmazás egyetlen változót köt a paraméterekhez, meghívja az SQLBindParametert , hogy a tömböket paraméterekhez kösse. Az egyetlen különbség az, hogy az átadott címek tömbcímek, nem egyváltozós címek. Az alkalmazás beállítja a SQL_ATTR_PARAM_BIND_TYPE utasításattribútumot annak meghatározására, hogy oszlopalapú (alapértelmezett) vagy sorszintű kötést használ-e. Az, hogy oszloponkénti vagy soronkénti kötést használ-e, nagyrészt az alkalmazás preferenciája alapján dől el. Attól függően, hogy a processzor hogyan fér hozzá a memóriához, a sorszintű kötés gyorsabb lehet. A különbség azonban valószínűleg elhanyagolható, kivéve a nagyon nagy számú paramétersort.

Column-Wise kötés

Oszlopalapú kötés használatakor egy alkalmazás egy vagy két tömböt köt minden olyan paraméterhez, amelyhez adatokat kell megadni. Az első tömb tartalmazza az adatértékeket, a második pedig a hossz-/mutatópuffereket. Minden tömb annyi elemet tartalmaz, amennyit a paraméter értéke tartalmaz.

Az oszlopalapú kötés az alapértelmezett. Az alkalmazás a SQL_ATTR_PARAM_BIND_TYPE utasításattribútum beállításával sorszintű kötésről oszlopszintű kötésre is válthat. Az alábbi ábra az oszlopalapú kötés működését mutatja be.

Az oszlopalapú kötés működése

Az alábbi kód például 10 elemű tömböket köt a PartID, a Description és a Price oszlopok paramétereihez, és végrehajt egy utasítást, amely 10 sort szúr be. Oszlopszintű kötést használ.

#define DESC_LEN 51  
#define ARRAY_SIZE 10  
  
SQLCHAR *      Statement = "INSERT INTO Parts (PartID, Description,  Price) "  
                                                "VALUES (?, ?, ?)";  
SQLUINTEGER    PartIDArray[ARRAY_SIZE];  
SQLCHAR        DescArray[ARRAY_SIZE][DESC_LEN];  
SQLREAL        PriceArray[ARRAY_SIZE];  
SQLINTEGER     PartIDIndArray[ARRAY_SIZE], DescLenOrIndArray[ARRAY_SIZE],  
               PriceIndArray[ARRAY_SIZE];  
SQLUSMALLINT   i, ParamStatusArray[ARRAY_SIZE];  
SQLULEN ParamsProcessed;  
  
memset(DescLenOrIndArray, 0, sizeof(DescLenOrIndArray));  
memset(PartIDIndArray, 0, sizeof(PartIDIndArray));  
memset(PriceIndArray, 0, sizeof(PriceIndArray));  
  
// Set the SQL_ATTR_PARAM_BIND_TYPE statement attribute to use  
// column-wise binding.  
SQLSetStmtAttr(hstmt, SQL_ATTR_PARAM_BIND_TYPE, SQL_PARAM_BIND_BY_COLUMN, 0);  
  
// Specify the number of elements in each parameter array.  
SQLSetStmtAttr(hstmt, SQL_ATTR_PARAMSET_SIZE, ARRAY_SIZE, 0);  
  
// Specify an array in which to return the status of each set of  
// parameters.  
SQLSetStmtAttr(hstmt, SQL_ATTR_PARAM_STATUS_PTR, ParamStatusArray, 0);  
  
// Specify an SQLUINTEGER value in which to return the number of sets of  
// parameters processed.  
SQLSetStmtAttr(hstmt, SQL_ATTR_PARAMS_PROCESSED_PTR, &ParamsProcessed, 0);  
  
// Bind the parameters in column-wise fashion.  
SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_ULONG, SQL_INTEGER, 5, 0,  
                  PartIDArray, 0, PartIDIndArray);  
SQLBindParameter(hstmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, DESC_LEN - 1, 0,  
                  DescArray, DESC_LEN, DescLenOrIndArray);  
SQLBindParameter(hstmt, 3, SQL_PARAM_INPUT, SQL_C_FLOAT, SQL_REAL, 7, 0,  
                  PriceArray, 0, PriceIndArray);  
  
// Set part ID, description, and price.  
for (i = 0; i < ARRAY_SIZE; i++) {  
   GetNewValues(&PartIDArray[i], DescArray[i], &PriceArray[i]);  
   PartIDIndArray[i] = 0;  
   DescLenOrIndArray[i] = SQL_NTS;  
   PriceIndArray[i] = 0;  
}  
  
// Execute the statement.  
SQLExecDirect(hstmt, Statement, SQL_NTS);  
  
// Check to see which sets of parameters were processed successfully.  
for (i = 0; i < ParamsProcessed; i++) {  
   printf("Parameter Set  Status\n");  
   printf("-------------  -------------\n");  
   switch (ParamStatusArray[i]) {  
      case SQL_PARAM_SUCCESS:  
      case SQL_PARAM_SUCCESS_WITH_INFO:  
         printf("%13d  Success\n", i);  
         break;  
  
      case SQL_PARAM_ERROR:  
         printf("%13d  Error\n", i);  
         break;  
  
      case SQL_PARAM_UNUSED:  
         printf("%13d  Not processed\n", i);  
         break;  
  
      case SQL_PARAM_DIAG_UNAVAILABLE:  
         printf("%13d  Unknown\n", i);  
         break;  
  
   }  
}  

Row-Wise kötés

Sorszintű kötés használatakor az alkalmazás minden paramétercsoporthoz definiál egy struktúrát. A struktúra minden paraméterhez egy vagy két elemet tartalmaz. Az első elem tartalmazza a paraméter értékét, a második pedig a hossz/mutató pufferét. Az alkalmazás ezután lefoglal egy tömböt ezekből a struktúrákból, amelyek annyi elemet tartalmaznak, amennyit az egyes paraméterek értékei tartalmaznak.

Az alkalmazás a SQL_ATTR_PARAM_BIND_TYPE utasítás attribútummal deklarálja a struktúra méretét az illesztőnek. Az alkalmazás a tömb első szerkezetében köti össze a paraméterek címét. Így az illesztő kiszámíthatja egy adott sor és oszlop adatainak címét a következő módon:

Address = Bound Address + ((Row Number - 1) * Structure Size) + Offset  

ahol a sorok száma 1 és a paraméterkészlet mérete között van megadva. Ha meg van adva, az eltolás azon érték, amelyre az SQL_ATTR_PARAM_BIND_OFFSET_PTR utasítás attribútuma mutat. Az alábbi ábra a sorszintű kötés működését mutatja be. A paraméterek bármilyen sorrendben elhelyezhetők a struktúrában, de az egyértelműség érdekében szekvenciális sorrendben jelennek meg.

Bemutatja, hogyan működik a sorszintű kötés

Az alábbi kód létrehoz egy struktúrát a PartID, a Description és az Price oszlopban tárolandó értékek elemeivel. Ezután lefoglal egy 10 elemből álló tömböt ezekből a struktúrákból, és sorszintű kötéssel a PartID, a Description és az Price oszlop paramétereihez köti. Ezután végrehajt egy utasítást 10 sor beszúrásához.

#define DESC_LEN 51  
#define ARRAY_SIZE 10  
  
typedef tagPartStruct {  
   SQLREAL       Price;  
   SQLUINTEGER   PartID;  
   SQLCHAR       Desc[DESC_LEN];  
   SQLINTEGER    PriceInd;  
   SQLINTEGER    PartIDInd;  
   SQLINTEGER    DescLenOrInd;  
} PartStruct;  
  
PartStruct PartArray[ARRAY_SIZE];  
SQLCHAR *      Statement = "INSERT INTO Parts (PartID, Description,  
                Price) "  
               "VALUES (?, ?, ?)";  
SQLUSMALLINT   i, ParamStatusArray[ARRAY_SIZE];  
SQLULEN ParamsProcessed;  
  
// Set the SQL_ATTR_PARAM_BIND_TYPE statement attribute to use  
// column-wise binding.  
SQLSetStmtAttr(hstmt, SQL_ATTR_PARAM_BIND_TYPE, sizeof(PartStruct), 0);  
  
// Specify the number of elements in each parameter array.  
SQLSetStmtAttr(hstmt, SQL_ATTR_PARAMSET_SIZE, ARRAY_SIZE, 0);  
  
// Specify an array in which to return the status of each set of  
// parameters.  
SQLSetStmtAttr(hstmt, SQL_ATTR_PARAM_STATUS_PTR, ParamStatusArray, 0);  
  
// Specify an SQLUINTEGER value in which to return the number of sets of  
// parameters processed.  
SQLSetStmtAttr(hstmt, SQL_ATTR_PARAMS_PROCESSED_PTR, &ParamsProcessed, 0);  
  
// Bind the parameters in row-wise fashion.  
SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_ULONG, SQL_INTEGER, 5, 0,  
                  &PartArray[0].PartID, 0, &PartArray[0].PartIDInd);  
SQLBindParameter(hstmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, DESC_LEN - 1, 0,  
                  PartArray[0].Desc, DESC_LEN, &PartArray[0].DescLenOrInd);  
SQLBindParameter(hstmt, 3, SQL_PARAM_INPUT, SQL_C_FLOAT, SQL_REAL, 7, 0,  
                  &PartArray[0].Price, 0, &PartArray[0].PriceInd);  
  
// Set part ID, description, and price.  
for (i = 0; i < ARRAY_SIZE; i++) {  
   GetNewValues(&PartArray[i].PartID, PartArray[i].Desc, &PartArray[i].Price);  
   PartArray[0].PartIDInd = 0;  
   PartArray[0].DescLenOrInd = SQL_NTS;  
   PartArray[0].PriceInd = 0;  
}  
  
// Execute the statement.  
SQLExecDirect(hstmt, Statement, SQL_NTS);  
  
// Check to see which sets of parameters were processed successfully.  
for (i = 0; i < ParamsProcessed; i++) {  
   printf("Parameter Set  Status\n");  
   printf("-------------  -------------\n");  
   switch (ParamStatusArray[i]) {  
      case SQL_PARAM_SUCCESS:  
      case SQL_PARAM_SUCCESS_WITH_INFO:  
         printf("%13d  Success\n", i);  
         break;  
  
      case SQL_PARAM_ERROR:  
         printf("%13d  Error\n", i);  
         break;  
  
      case SQL_PARAM_UNUSED:  
         printf("%13d  Not processed\n", i);  
         break;  
  
      case SQL_PARAM_DIAG_UNAVAILABLE:  
         printf("%13d  Unknown\n", i);  
         break;  
  
   }