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:
SELECT <a/>, b, c, func(<a/>) d FROM #table, othertable WHERE a = <var1/>
Que en mode prepared quedaría:
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:
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.
<update table='gcompedh'> <column name='date_updated'>CURRENT</column> <where>cabid = <p_cabid/></where> </update>
Esta sentencia se transforma como:
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'. |