硬式編碼的 SQL 陳述式
執行固定工作的應用程式通常包含硬式編碼的 SQL 陳述式。 例如,訂單輸入系統可能會使用下列呼叫來列出未完成的銷售訂單:
SQLExecDirect(hstmt, "SELECT OrderID FROM Orders WHERE Status = 'OPEN'", SQL_NTS);
硬式編碼 SQL 陳述式有數個優點:可以在撰寫應用程式時進行測試;相較於在執行時間建構的陳述式,它們更容易實作;它們簡化了應用程式。
使用陳述式參數及準備陳述式,提供更妥善的方式來使用硬式編碼的 SQL 陳述式。 例如,假設 [組件] 資料表包含 PartID、Description 和 Price 資料行。 將新資料列插入此資料表的其中一種方式是建構和執行 INSERT 陳述式:
#define DESC_LEN 51
#define STATEMENT_LEN 51
SQLUINTEGER PartID;
SQLCHAR Desc[DESC_LEN], Statement[STATEMENT_LEN];
SQLREAL Price;
// Set part ID, description, and price.
GetNewValues(&PartID, Desc, &Price);
// Build INSERT statement.
sprintf_s(Statement, 100, "INSERT INTO Parts (PartID, Description, Price) "
"VALUES (%d, '%s', %f)", PartID, Desc, Price);
// Execute the statement.
SQLExecDirect(hstmt, Statement, SQL_NTS);
更好的方法是使用硬式編碼的參數化陳述式。 相較於硬式編碼資料值的陳述式,這麼做具有兩個優點。 首先,建構參數化陳述式比較容易,因為資料值可以其原生類型傳送 (例如整數和浮點數),而不是將其轉換成字串。 其次,只要變更參數值並重新執行,就可以重複使用這類陳述式,而不需要加以重建。
#define DESC_LEN 51
SQLCHAR * Statement = "INSERT INTO Parts (PartID, Description, Price) "
"VALUES (?, ?, ?)";
SQLUINTEGER PartID;
SQLCHAR Desc[DESC_LEN];
SQLREAL Price;
SQLINTEGER PartIDInd = 0, DescLenOrInd = SQL_NTS, PriceInd = 0;
// Bind the parameters.
SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_ULONG, SQL_INTEGER, 5, 0,
&PartID, 0, &PartIDInd);
SQLBindParameter(hstmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, DESC_LEN - 1, 0,
Desc, sizeof(Desc), &DescLenOrInd);
SQLBindParameter(hstmt, 3, SQL_PARAM_INPUT, SQL_C_FLOAT, SQL_REAL, 7, 0,
&Price, 0, &PriceInd);
// Set part ID, description, and price.
GetNewValues(&PartID, Desc, &Price);
// Execute the statement.
SQLExecDirect(hstmt, Statement, SQL_NTS);
假設此陳述式會執行多次以上,就可以將其備妥以達成更高的效率:
#define DESC_LEN 51
SQLCHAR *Statement = "INSERT INTO Parts (PartID, Description, Price) "
"VALUES (?, ?, ?)";
SQLUINTEGER PartID;
SQLCHAR Desc[DESC_LEN];
SQLREAL Price;
SQLINTEGER PartIDInd = 0, DescLenOrInd = SQL_NTS, PriceInd = 0;
// Prepare the INSERT statement.
SQLPrepare(hstmt, Statement, SQL_NTS);
// Bind the parameters.
SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_ULONG, SQL_INTEGER, 5, 0,
&PartID, 0, &PartIDInd);
SQLBindParameter(hstmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, DESC_LEN - 1, 0,
Desc, sizeof(Desc), &DescLenOrInd);
SQLBindParameter(hstmt, 3, SQL_PARAM_INPUT, SQL_C_FLOAT, SQL_REAL, 7, 0,
&Price, 0, &PriceInd);
// Loop to continually get new values and insert them.
while (GetNewValues(&PartID, Desc, &Price))
SQLExecute(hstmt);
使用陳述式最有效率的方式可能是建構包含該陳述式的程序,如下列程式碼範例所示。 因為程序是在開發期間建構,並儲存在資料來源上,所以不需要在執行階段準備。 這個方法的缺點是建立程序的語法是 DBMS 特定,而且必須針對要執行應用程式的每個 DBMS 個別建構程序。
#define DESC_LEN 51
SQLUINTEGER PartID;
SQLCHAR Desc[DESC_LEN];
SQLREAL Price;
SQLINTEGER PartIDInd = 0, DescLenOrInd = SQL_NTS, PriceInd = 0;
// Bind the parameters.
SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_ULONG, SQL_INTEGER, 5, 0,
&PartID, 0, &PartIDInd);
SQLBindParameter(hstmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, DESC_LEN - 1, 0,
Desc, sizeof(Desc), &DescLenOrInd);
SQLBindParameter(hstmt, 3, SQL_PARAM_INPUT, SQL_C_FLOAT, SQL_REAL, 7, 0,
&Price, 0, &PriceInd);
// Loop to continually get new values and insert them.
while (GetNewValues(&PartID, Desc, &Price))
SQLExecDirect(hstmt, "{call InsertPart(?, ?, ?)}", SQL_NTS);
如需參數、備妥陳述式和程序的詳細資訊,請參閱執行陳述式。