Algunos agentes de base de datos tienen ciertas limitaciones que impiden poder preparar un statement. En los casos en los que no sea posible por la ubicación del símbolo ? en la sentencia, debe utilizarse en atributo prepare con valor false en la propia variable. El sistema trata de realizar un PreparedStatement para las operaciones SELECT y FOREACH a menos que se indique en el tag el atributo prepare='false'. Este indicador puede ser necesario dado que en muchas ocasiones, el motor no aceptará un ? según la posición en la que se encuentre. Las reglas de parameters markers para cada agente de base de datos son las que determinarán si es posible o no realizar un PreparedStatement.

1 Parameters markers rules

A continuación se muestran algunas de estas reglas para los principales agentes de bases de datos:

IDS:

Parameter markers pueden utilizarse:

Parameter markers no pueden utilizarse:

  • En un select list (SELECT ? no es válido).
  • En un argumento NVL.
  • En un CASE THEN.

ORACLE:

Parameter markers pueden utilizarse:

Parameter markers no pueden utilizarse:

Como cualquier operando de una aritmética sóla o operador de comparación, por ejemplo 'WHERE ? = ?' or 'WHERE ? = (SELECT ? ...)' no son válidas.

DB2:

Parameter markers pueden utilizarse:

  • Como operando de un argumento de una función escalar si éste puede ser especificado como una expresión aritmética y el otro operando es numérico.
  • Como atributos asigandos a CAST.

Parameter markers no pueden utilizarse:

  • En un select list (SELECT ? no es válido) a menos que sea un subquery.
  • Como un operando del operador de concatenación.
  • Como cualquier operando de una aritmética sóla o operador de comparación, por ejemplo 'WHERE ? = ?' or 'WHERE ? = (SELECT ? ...)' no son válidas.
  • Como operador de una resta unitaria.
  • Como operador de una expresión aritmética de fechas.
  • Como operador de un operador de comparación cuando el otro operando es un user-defined type.
  • Al menos uno de los operandos de BETWEEN o IN debe no ser un parameter markerun argumento de una función escalar o definida por el usuario no puede ser especificada sólamente como un parameter marker, por ejemplo INTERGER(?) no es válida.
  • Como primer argumento de las funciones escalares VALUE, COALESCE, MIN, MAX, LAND, LOR, y XOR. Tampoco como primer predicado de la función LIKE.

2 Atributo prepare="false" y text="true"

Para los casos en los que no sea posible preparar el statement y el sistema no pueda determinarlo de forma automática, se debe indicar en la propia variable el atributo prepare con valor false, como por ejemplo:

Copy
SELECT <a/>, b, c, func(<a/>) d
 FROM #table, othertable
WHERE a = <var1/>

Que en mode prepared quedaría:

Copy
SELECT ?, b, c, func(?) d
  FROM mytable, othertable
 WHERE a = ?

No es válido según el agente de base de datos. Para que sea válido debe utlizarse el atributo prepare='false' en las variables correspondientes para solucionar el problema:

Copy
SELECT <a/>, b, c, func(<a/>) d
 FROM #table, othertable
WHERE a = <var1/>

3 Ejemplo

A continuación se muestra un ejemplo en el que la columna a modificar no puede ser 'prepared', ya que se trata de una columna de tipo fecha y se establece como valor el string 'current'. En este caso o bien se hace que toda la sentencia sea no prepared o bien sólo la asignación.

Copy
<update table='gcompedh'>
    <column name='date_updated'>CURRENT</column>
    <where>cabid = <p_cabid/></where>
</update>

Esta sentencia se transforma como:

Copy
UPDATE gcompedh
   SET date_updated = ?
 WHERE cabid = ?

Y se establecen los valores mediante las funciones del driver. Para la columna date_updated de tipo fecha se estable el valor mediante la función que asigna fechas, y como el valor indicado es el string CURRENT, da error. Existen dos soluciones, hacer que toda la sentencia sea 'no prepared' (indicado con el atributo prepared='false' para todo el update) o bien que la asiganacion de la columna no sea prepared (indicado con el atributo text='true' en la propia columna):

Sentencia XSQL Sentencia SQL
<update table='gcompedh' prepare='false'> <column name='date_updated'>CURRENT</column> <where>cabid = <p_cabid/></where> </update> UPDATE gcompedh SET date_updated = current WHERE cabid = 999
Toda la sentencia se hace 'no prepared' con el atributo prepared='false', tanto la asignación de valores como la clásula where.
<update table='gcompedh'> <column name='date_updated' text='true'>CURRENT</column> <where>cabid = <p_cabid/></where> </update> UPDATE gcompedh SET date_updated = current WHERE cabid = ?
Con el atributo text='true' sólo se hace 'no prepared' la asignación del valor, el resto de la sentencia es 'prepared'.