Teilen über


Hartcodierte SQL-Anweisungen

Anwendungen, die eine feste Aufgabe ausführen, enthalten in der Regel hartcodierte SQL-Anweisungen. Ein Bestelleintragssystem kann z. B. den folgenden Aufruf verwenden, um offene Verkaufsaufträge auflisten zu können:

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

Es gibt mehrere Vorteile für hartcodierte SQL-Anweisungen: Sie können getestet werden, wenn die Anwendung geschrieben wird; sie sind einfacher zu implementieren als anweisungen, die zur Laufzeit erstellt wurden; und sie vereinfachen die Anwendung.

Die Verwendung von Anweisungsparametern und die Vorbereitung von Anweisungen bieten noch bessere Möglichkeiten, hartcodierte SQL-Anweisungen zu verwenden. Angenommen, die Tabelle "Parts" enthält die Spalten "PartID", "Beschreibung" und "Preis". Eine Möglichkeit zum Einfügen einer neuen Zeile in diese Tabelle wäre das Erstellen und Ausführen einer INSERT-Anweisung :

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

Eine noch bessere Möglichkeit besteht darin, eine hartcodierte parametrisierte Anweisung zu verwenden. Dies hat zwei Vorteile gegenüber einer Anweisung mit hartcodierten Datenwerten. Zunächst ist es einfacher, eine parametrisierte Anweisung zu erstellen, da die Datenwerte in ihren systemeigenen Typen gesendet werden können, z. B. ganze Zahlen und Gleitkommazahlen, anstatt sie in Zeichenfolgen zu konvertieren. Zweitens kann eine solche Anweisung mehr als einmal verwendet werden, indem sie die Parameterwerte ändern und erneut ausführen; es ist nicht erforderlich, sie neu zu erstellen.

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

Vorausgesetzt, diese Anweisung soll mehrmals ausgeführt werden, kann sie für eine noch höhere Effizienz vorbereitet werden:

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

Vielleicht ist die effizienteste Möglichkeit, die Anweisung zu verwenden, um eine Prozedur zu erstellen, die die Anweisung enthält, wie im folgenden Codebeispiel gezeigt. Da die Prozedur zur Entwicklungszeit erstellt und in der Datenquelle gespeichert ist, muss sie nicht zur Laufzeit vorbereitet werden. Ein Nachteil dieser Methode besteht darin, dass die Syntax für die Erstellung von Prozeduren DBMS-spezifische und Prozeduren separat für jedes DBMS erstellt werden muss, auf dem die Anwendung ausgeführt werden soll.

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

Weitere Informationen zu Parametern, vorbereiteten Anweisungen und Prozeduren finden Sie unter Ausführen einer Anweisung.