Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Aplikace, které používají pole parametrů, sváže pole s parametry v příkazu SQL. Existují dva styly vazeb:
Přiřaďte pole ke každému parametru. Každá datová struktura (pole) obsahuje všechna data pro jeden parametr. To se nazývá svazování po sloupcích, protože svazuje sloupec hodnot pro jeden parametr.
Definujte strukturu pro uložení dat parametrů pro celou sadu parametrů a vytvořte vazbu na pole těchto struktur. Každá datová struktura obsahuje data pro jeden příkaz SQL. Tomu se říká vazba po řádcích , protože váže řádek parametrů.
Stejně jako když aplikace sváže jednotlivé proměnné na parametry, volá SQLBindParameter k vytvoření vazby polí na parametry. Jediným rozdílem je, že předané adresy jsou maticové adresy, nikoli adresy s jednou proměnnou. Aplikace nastaví atribut příkazu SQL_ATTR_PARAM_BIND_TYPE tak, aby určil, jestli používá sloupcovou vazbu (výchozí) nebo řádkovou vazbu. Zda použít vazby podle sloupců nebo řádků, je z velké části otázkou preferování aplikace. V závislosti na tom, jak procesor přistupuje k paměti, může být řádkové spojování rychlejší. Rozdíl je však pravděpodobně zanedbatelný s výjimkou velmi velkého počtu řádků parametrů.
Column-Wise vazba
Při použití vazby podle sloupců aplikace vytvoří vazbu jednoho nebo dvou polí na každý parametr, pro který se mají data poskytnout. První pole obsahuje datové hodnoty a druhé pole obsahuje vyrovnávací paměti pro délky a indikátory. Každé pole obsahuje tolik prvků, kolik má parametr hodnoty.
Vazby podle sloupců jsou výchozí. Aplikace se také může změnit z řádkové vazby na sloupcovou vazbu nastavením atributu příkazu SQL_ATTR_PARAM_BIND_TYPE. Následující obrázek ukazuje, jak probíhá vazba podle sloupců.
.
Následující kód například vytvoří vazbu 10 elementů na parametry pro sloupce PartID, Description a Price a spustí příkaz pro vložení 10 řádků. Používá vázání po sloupcích.
#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 Vazba
Při použití vazby pro řádky definuje aplikace strukturu pro každou sadu parametrů. Struktura obsahuje jeden nebo dva prvky pro každý parametr. První prvek obsahuje hodnotu parametru a druhý prvek obsahuje vyrovnávací paměť pro délku/indikátor. Aplikace pak přidělí pole těchto struktur, které obsahuje tolik prvků, kolik jsou hodnoty pro každý parametr.
Pomocí atributu SQL_ATTR_PARAM_BIND_TYPE příkazu aplikace deklaruje velikost struktury ovladači. Aplikace sváže adresy parametrů v první struktuře pole. Ovladač tedy může vypočítat adresu dat pro určitý řádek a sloupec jako
Address = Bound Address + ((Row Number - 1) * Structure Size) + Offset
kde jsou řádky očíslovány od 1 do velikosti sady parametrů. Posun, pokud je definován, je hodnota, na kterou odkazuje atribut příkazu SQL_ATTR_PARAM_BIND_OFFSET_PTR. Následující obrázek znázorňuje, jak funguje vazba podle řádků. Parametry lze umístit do struktury v libovolném pořadí, ale jsou zobrazeny v sekvenčním pořadí pro přehlednost.
.
Následující kód vytvoří strukturu s prvky pro hodnoty, které mají být uloženy ve sloupcích PartID, Description a Price. Poté přidělí desetiprvkové pole těchto struktur a přiřadí jej k parametrům pro sloupce PartID, Description a Price pomocí řádkového mapování. Potom spustí příkaz, který vloží 10 řádků.
#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;
}