Udostępnij przez


instrukcje Hard-Coded SQL

Aplikacje wykonujące stałe zadanie zwykle zawierają zakodowane na stałe instrukcje SQL. Na przykład system wprowadzania zamówień może użyć następującego wywołania, aby wyświetlić listę otwartych zamówień sprzedaży:

SQLExecDirect(hstmt, "SELECT OrderID FROM Orders WHERE Status = 'OPEN'", SQL_NTS);  

Istnieje kilka zalet zakodowanych instrukcji SQL: można je przetestować podczas pisania aplikacji; są prostsze do zaimplementowania niż instrukcje skonstruowane w czasie wykonywania; i upraszczają aplikację.

Używanie parametrów i przygotowywanie instrukcji zapewnia jeszcze lepsze sposoby korzystania z wbudowanych instrukcji SQL. Załóżmy na przykład, że tabela Parts zawiera kolumny PartID, Description i Price. Jednym ze sposobów wstawienia nowego wiersza do tej tabeli jest konstruowanie i wykonywanie instrukcji 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);  

Jeszcze lepszym sposobem jest użycie zakodowanej, sparametryzowanej instrukcji. Ma to dwie zalety w stosunku do instrukcji z zakodowanymi wartościami danych. Po pierwsze łatwiej jest skonstruować instrukcję sparametryzowaną, ponieważ wartości danych można wysyłać w typach natywnych, takich jak liczby całkowite i liczby zmiennoprzecinkowe, zamiast konwertować je na ciągi. Po drugie, takie oświadczenie można używać więcej niż raz, zmieniając wartości parametrów i wykonując je ponownie; nie ma potrzeby jego ponownego kompilowania.

#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);  

Zakładając, że ta instrukcja ma być wykonywana więcej niż raz, można ją przygotować do jeszcze większej wydajności:

#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);  

Być może najbardziej efektywnym sposobem użycia instrukcji jest utworzenie procedury zawierającej instrukcję, jak pokazano w poniższym przykładzie kodu. Ponieważ procedura jest konstruowana w czasie programowania i przechowywana w źródle danych, nie musi być przygotowana w czasie wykonywania. Wadą tej metody jest to, że składnia tworzenia procedur jest specyficzna dla systemu DBMS, a procedury muszą być konstruowane oddzielnie dla każdego systemu DBMS, na którym ma być uruchamiana aplikacja.

#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);  

Aby uzyskać więcej informacji na temat parametrów, przygotowanych instrukcji i procedur, zobacz Wykonywanie instrukcji.