已准备的执行 ODBC

准备好的执行是多次执行语句的有效方法。 该语句首先被编译或准备到访问计划中。 然后,稍后将访问计划执行一次或多次。 有关访问计划的详细信息,请参阅处理 SQL 语句

垂直和自定义应用程序通常使用准备好的执行来重复执行相同的参数化 SQL 语句。 例如,以下代码准备一个语句来更新不同部件的价格。 然后,它每次使用不同的参数值多次执行该语句。

SQLREAL       Price;  
SQLUINTEGER   PartID;  
SQLINTEGER    PartIDInd = 0, PriceInd = 0;  
  
// Prepare a statement to update salaries in the Employees table.  
SQLPrepare(hstmt, "UPDATE Parts SET Price = ? WHERE PartID = ?", SQL_NTS);  
  
// Bind Price to the parameter for the Price column and PartID to  
// the parameter for the PartID column.  
SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_FLOAT, SQL_REAL, 7, 0,  
                  &Price, 0, &PriceInd);  
SQLBindParameter(hstmt, 2, SQL_PARAM_INPUT, SQL_C_ULONG, SQL_INTEGER, 10, 0,  
                  &PartID, 0, &PartIDInd);  
  
// Repeatedly execute the statement.  
while (GetPrice(&PartID, &Price)) {  
   SQLExecute(hstmt);  
}  

对于需要执行一次以上的语句,准备好的执行要比直接执行更快速。这主要是因为准备好的执行仅需编译一次语句,直接执行的语句在每次执行时都需要编译。 准备好的执行还可以减少网络流量,因为如果数据源支持访问计划标识符,驱动程序在每次执行语句时都可以向数据源发送访问计划标识符,而不是整个 SQL 语句。

应用程序可以在准备好语句之后和执行语句之前检索结果集的元数据。 但是,为准备好的未执行语句返回元数据对于某些驱动程序来说很昂贵,如果可能,应通过可互操作的应用程序来避免。 有关详细信息,请参阅结果集元数据

不应对执行一次的语句使用准备好的执行。 对于此类语句,它比直接执行略慢,因为它需要额外的 ODBC 函数调用。

重要

通过显式调用 SQLEndTran 或在自动提交模式下工作,提交或回滚事务会导致某些数据源删除连接上所有语句的访问计划。 有关详细信息,请参阅 SQLGetInfo 函数说明中的 SQL_CURSOR_COMMIT_BEHAVIOR 和 SQL_CURSOR_ROLLBACK_BEHAVIOR 选项。

要准备和执行语句,应用程序可执行以下操作:

  1. 调用 SQLPrepare 并将其传递给包含 SQL 语句的字符串。

  2. 设置任何参数的值。 参数实际上可以在准备语句之前或之后设置。 有关详细信息,请参见本部分后面的语句参数

  3. 调用 SQLExecute 并执行必要的任何其他处理,例如提取数据。

  4. 根据需要重复步骤 2 和步骤 3。

  5. 调用 SQLPrepare 时,驱动程序将执行以下操作:

    • 修改 SQL 语句以使用数据源的 SQL 语法,而无需分析语句。 这包括替换 ODBC 中的转义序列中讨论的转义序列。 应用程序可以通过调用 SQLNativeSql 来检索 SQL 语句的修改形式。 如果设置了 SQL_ATTR_NOSCAN 语句属性,则不会替换转义序列。

    • 将语句发送到数据源进行准备。

    • 存储返回的访问计划标识符以供以后执行(如果准备成功)或返回任何错误(如果准备失败)。 错误包括 SQLSTATE 42000 之类的语法错误(语法错误或访问冲突)和 SQLSTATE 42S02 之类的语义错误(找不到基表或视图)。

      注意

      有些驱动程序此时不会返回错误,而是在执行语句时或调用目录函数时返回错误。 因此,当 SQLPrepare 实际上失败时,似乎显示已经成功。

  6. 调用 SQLExecute 时,驱动程序将执行以下操作:

    • 检索当前参数值,并根据需要对其进行转换。 有关详细信息,请参见本部分后面的语句参数

    • 将访问计划标识符和已转换的参数值发送到数据源。

    • 将返回任何错误。 这些通常是运行时错误,例如 SQLSTATE 24000(游标状态无效)。 但是,有些驱动程序此时会返回语法和语义错误。

如果数据源不支持语句准备,驱动程序必须尽可能模拟它。 例如,调用 SQLPrepare 时,驱动程序可能不执行任何操作,然后在调用 SQLExecute 时执行语句的直接执行。

如果数据源支持在不执行的情况下进行语法检查,驱动程序可能会提交语句,以便在调用 SQLPrepare 时进行检查,并在调用 SQLExecute 时提交语句以供执行。

如果驱动程序无法模拟语句准备,则会在调用 SQLPrepare 时存储该语句,并在调用 SQLExecute 时提交该语句以供执行。

由于模拟语句准备并不完美,因此 SQLExecute 可以返回 SQLPrepare 正常返回的任何错误。