Share via


Ejecución preparada ODBC

La ejecución preparada es una manera eficaz de ejecutar una instrucción más de una vez. La instrucción se compila, o se prepara, primero en un plan de acceso. A continuación, el plan de acceso se ejecuta una o varias veces. Para obtener más información sobre los planes de acceso, consulte Procesamiento de una instrucción SQL.

Las aplicaciones verticales y personalizadas suelen usar la ejecución preparada para ejecutar repetidamente la misma instrucción SQL parametrizada. Por ejemplo, el código siguiente prepara una instrucción para actualizar los precios de diferentes piezas. A continuación, ejecuta la instrucción varias veces con valores de parámetros diferentes cada vez.

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

La ejecución preparada es más rápida que la ejecución directa de instrucciones que se ejecutan más de una vez, principalmente porque la instrucción se compila solo una vez; en cambio, las instrucciones ejecutadas directamente se compilan cada vez que se ejecutan. La ejecución preparada también puede proporcionar una reducción del tráfico de red porque el controlador puede enviar un identificador de plan de acceso al origen de datos cada vez que se ejecute la instrucción, en lugar de una instrucción SQL completa, si el origen de datos admite identificadores de planes de acceso.

La aplicación puede recuperar los metadatos del conjunto de resultados después de preparar la instrucción y antes de que se ejecute. Sin embargo, la devolución de metadatos para instrucciones preparadas y no ejecutadas es costosa para algunos controladores y debe evitarse mediante aplicaciones interoperables si es posible. Para obtener más información, consulte Metadatos del conjunto de resultados.

La ejecución preparada no se debe utilizar para las instrucciones que se ejecutan una sola vez. Para estas instrucciones, es ligeramente más lenta que la ejecución directa porque requiere una llamada de función de ODBC adicional.

Importante

Confirmar o revertir una transacción, ya sea llamando explícitamente a SQLEndTran o trabajando en modo de confirmación automática, hace que algunos orígenes de datos eliminen los planes de acceso de todas las instrucciones de una conexión. Para obtener más información, consulte las opciones de SQL_CURSOR_COMMIT_BEHAVIOR y SQL_CURSOR_ROLLBACK_BEHAVIOR en la descripción de la función SQLGetInfo.

Para preparar y ejecutar una instrucción, la aplicación:

  1. Llama a SQLPrepare y pasa una cadena que contiene la instrucción SQL.

  2. Establece los valores de los parámetros. Realmente los parámetros se pueden establecer antes o después de preparar la instrucción. Para obtener más información, consulte Parámetros de instrucciones más adelante en esta sección.

  3. Llama a SQLExecute y realiza cualquier procesamiento adicional necesario, como capturar datos.

  4. Repite los pasos 2 y 3 según sea necesario.

  5. Cuando se llama a SQLPrepare, el controlador:

    • Modifica la instrucción SQL para usar la gramática de SQL del origen de datos sin analizar la instrucción. Esto incluye reemplazar las secuencias de escape descritas en Secuencias de escape en ODBC. La aplicación puede recuperar la forma modificada de una instrucción SQL mediante una llamada a SQLNativeSql. Las secuencias de escape no se reemplazan si se establece el atributo de instrucción SQL_ATTR_NOSCAN.

    • Envía la instrucción al origen de datos para su preparación.

    • Almacena el identificador del plan de acceso devuelto para su posterior ejecución (si la preparación se realizó correctamente) o devuelve errores (si se produjo un error de preparación). Los errores incluyen errores sintácticos, como SQLSTATE 42000 (Error de sintaxis o infracción de acceso) y errores semánticos, como SQLSTATE 42S02 (Tabla básica o vista no encontrada).

      Nota:

      Algunos controladores no devuelven errores en este momento, sino que los devuelven cuando se ejecuta la instrucción o cuando se llama a las funciones de catálogo. Por lo tanto, puede parecer que SQLPrepare ha tenido éxito cuando, de hecho, ha fallado.

  6. Cuando se llama a SQLPrepare, el controlador:

    • Recupera los valores de los parámetros actuales y los convierte según sea necesario. Para obtener más información, consulte Parámetros de instrucciones más adelante en esta sección.

    • Envía el identificador del plan de acceso y los valores de los parámetros convertidos al origen de datos.

    • Devuelve los errores. Por lo general, se trata de errores en tiempo de ejecución, como SQLSTATE 24000 (Estado de cursor no válido). Sin embargo, algunos controladores devuelven errores sintácticos y semánticos en este momento.

Si el origen de datos no admite la preparación de instrucciones, el controlador debe emularla en la medida de lo posible. Por ejemplo, el controlador podría no hacer nada cuando se llama a SQLPrepare y, a continuación, realizar la ejecución directa de la instrucción cuando se llama a SQLExecute.

Si el origen de datos admite la comprobación de sintaxis sin ejecución, el controlador podría enviar la instrucción para comprobar cuándo se llama a SQLPrepare y enviar la instrucción para su ejecución cuando se llama a SQLExecute.

Si el controlador no puede emular la preparación de instrucciones, almacena la instrucción cuando se llama a SQLPrepare y la envía para su ejecución cuando se llama a SQLExecute.

Dado que la preparación de instrucciones emulada no es perfecta, SQLExecute puede devolver los errores devueltos normalmente por SQLPrepare.