Instruções SQL embutidas em código
Os aplicativos que executam uma tarefa fixa geralmente contêm instruções SQL embutidas em código. Por exemplo, um sistema de entrada de ordem pode usar a seguinte chamada para listar ordens de venda abertas:
SQLExecDirect(hstmt, "SELECT OrderID FROM Orders WHERE Status = 'OPEN'", SQL_NTS);
Há várias vantagens em instruções SQL embutidas em código: elas podem ser testadas quando o aplicativo é gravado; elas são mais simples de implementar do que instruções construídas em tempo de execução; e elas simplificam o aplicativo.
O uso de parâmetros de instrução e a preparação de instruções fornecem maneiras ainda melhores de usar instruções SQL embutidas em código. Por exemplo, suponha que a tabela Parts contenha as colunas PartID, Description e Price. Uma maneira de inserir uma nova linha nesta tabela seria construir e executar uma instrução 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);
Uma maneira ainda melhor é usar uma instrução embutida em código e parametrizada. Isso tem duas vantagens em relação a uma instrução com valores de dados embutidos em código. Primeiro, é mais fácil construir uma instrução parametrizada porque os valores de dados podem ser enviados em seus tipos nativos, como números de ponto flutuante e inteiros, em vez de convertê-los em cadeias de caracteres. Em segundo lugar, tal instrução pode ser usada mais de uma vez simplesmente alterando os valores dos parâmetros e executando-a novamente; não há necessidade de reconstruí-la.
#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);
Supondo que essa instrução deva ser executada mais de uma vez, ela pode ser preparada para uma eficiência ainda maior:
#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);
Talvez a maneira mais eficiente de usar a instrução seja construir um procedimento contendo a instrução, conforme mostrado no exemplo de código a seguir. Como o procedimento é construído em tempo de desenvolvimento e armazenado na fonte de dados, ele não precisa ser preparado em tempo de execução. Uma desvantagem desse método é que a sintaxe para criar procedimentos é específica do DBMS e os procedimentos devem ser construídos separadamente para cada DBMS no qual o aplicativo deve ser executado.
#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);
Para obter mais informações sobre parâmetros, instruções preparadas e procedimentos, confira Executar uma instrução.