Cansado de lidiar con el armado de instrucciones de SQL con argumentos variables, se me ocurrió hacer una función para manejarlo. Originalmente se llamaba ArmaSql, estaba en Visual Basic, lo que me tocaba en ese momento y funcionaba sobre MS-SQL. La versión más reciente está en PHP y funciona sobre MySql y como la puse en algún foro en inglés por ahí, se llama BuildSql(). Con muy pocos cambios se puede adaptar a cualquier otra base de datos, pero no me ha tocado hacerlo.

Creo que lo más molesto es el manejo de las fechas y los cadenas nulos. Andar dando vuelta a las fechas para que queden bien en el formato aceptado por la base de datos y manejar la alternativa de que tanto una fecha o una cadena pueda ser nulo siempre me dio dolor de cabeza, pues me ha ocurrido de insertar inadvertidamente el texto 'null' en lugar del valor null (sin comillas).

Hice entonces esta función que es una suerte de sprintf() orientado a SQL. El problema que se me presentaba con sprintf() era el de los valores en null, especialmente cadenas de caracteres y fechas, pues en el string de formato de sprintf() ya ponía las comillas y si la variable estaba en null, terminaba escribiendo el texto 'null' en la base de datos. sprintf() no sabe que cuando el valor es null no debe incluir las comillas. Yo uso mucho el valor null en la base de datos, significa `no sé´ o `no hay´, indica la falta de un dato. Otros prefieren usar un valor convenido para indicar lo mismo, por ejemplo, cadenas vacías o importes en cero o negativos o alguna otra convención arbitraria que, en mi opinión es innecesaria pues SQL ya tiene previsto el valor null para eso. Es por ello que el null me preocupa tanto.

Entonces, al igual que sprintf(), la función BuildSql() acepta un primer argumento que es el modelo de la instrucción de SQL a armar y luego una cantidad variable de argumentos cuyos valores serán insertados en la primer cadena con el formato que le corresponda a cada uno. El lugar de inserción de los valores va indicado por un signo de interrogación seguido de varios modificadores, según se indica:

?[nn][m]t

Donde:

nn: opcional, indica la posición del argumento dentro de la lista de argumentos. El argumento 0 es el modelo de la instrucción misma y no tiene sentido usarlo. Si no se indica los argumentos se irán insertando secuencialmente según aparecen. Cuando se indica el número de argumento a usar, el puntero secuencial de argumentos no se incrementa.

m: opcional, puede ser una de dos opciones:

m: el argumento es obligatorio (en inglés: mandatory) el argumento no puede ser null. Dará error si lo fuera.
n: convertir a null si el argumento fuera 0 o una cadena vacía.

t: este es el único modificador obligatorio e indica el tipo del argumento, que puede ser cualquiera de los siguientes:

s: string
i: integer
f: float
d: date, datetime, timestamp
t: time
b: boolean
p: prefijo

Todos estos modificadores pueden darse tanto en mayúsculas como en minúsculas. Lo mínimo requerido es el signo de interrogación seguido de una descripción del tipo de datos. En el caso de que el tipo de dato requiriera encerrar el valor entre comillas, la función las proveerá. No hay previsión para insertar un signo de interrogación en la salida pues, como es un carácter inválido en SQL, no tiene sentido, pero no hay problema en que cualquiera de los argumentos lo contenga.

El tipo de datos `p` es especial en cuanto a que no representa un argumento sino el contenido de la variable $table_prefix. Dependiendo del servicio contratado con un proveedor de internet, es posible disponer de ilimitadas bases de datos o un número limitado, en ocasiones una sola. En ese caso, es necesario llamar a cada tabla con un prefijo que indique a qué aplicación corresponde. El modificador p permite agregar automáticamente ese prefijo, tomándola de la variable global $table_prefix (un nombre arbitrario que puede cambiarse a gusto) supuestamente leído de la configuración de la aplicación.

La función está comentada en el fuente e incluye un ejemplo.

Esta función se complementa con ReadSqlDate(), más abajo en el mismo fuente que permite convertir una fecha, fecha-hora o timestamp al formato interno de PHP. Yo nunca he usado el tipo de dato time de SQL, por lo que no he previsto una función equivalente para ese tipo de dato. Vale la pena que advierta a quien quiera hacerlo que la función mktime(), cuando no se le dan los argumentos mes, día y año, no los supone cero sino que toma los valores actuales, por lo que al convertirlo, se deberá usar:

mktime($hora,$minuto,$segundos) - $mktime(0,0,0)

y no simplemente:

mktime($hora,$minuto,$segundos)