Página principal
Artículos y trucos
Catálogo de productos
Ejemplos y descargas
Mis libros
Cursos de formación
Investigación y desarrollo
Libros recomendados
Mis páginas favoritas
Acerca del autor
 
En colaboración con Amazon
 
Intuitive Sight

¡La dirección, idiota, la dirección...!

El SQL Server de Microsoft no deja de sorprenderme día a día ... casi siempre de forma desagradable. Cuando pensaba que ya no podía encontrar más pretextos para no utilizarlo, he aquí que Microsoft saca un as de la manga y te das cuenta de cuánto puedes odiar a alguien o algo. Qué tristeza, he perdido la poca fe que me quedaba en la naturaleza humana.

Al grano. Para producir el desastre vale lo mismo la versión 6, que la 6.5, la 7 y sospecho que cuando haya una 8, igual. Cree un procedimiento idiota como el siguiente, utilizando SQL Explorer o el SQL Query Tool (rebautizado como SQL Query Analizer en la 7; es como cuando llegas a tu casa de madrugada tras una juerga, no enciendes la luz y los dedos de tus pies descubren que alguien ha cambiado los muebles de lugar):

create procedure ExtremaImbecilidad 
  @a integer, @b integer, @c integer output as
  select @c = @a + @b

Se supone que esta joya de la programación recibe tres parámetros. Los dos primeros son parámetros de entrada; el procedimiento los suma y coloca el resultado en el tercer parámetro, que ha sido declarado como un parámetro de salida.

¡Pobre de mí! Yo pensaba que podía utilizar el procedimiento anterior desde otro procedimiento de esta simple manera:

create procedure OtraIdiotez @v1 integer, @v2 integer as
begin
   /* Declaración de variables locales */
   declare @resultado integer
   /* Llamamos al procedimiento */
   execute ExtremaImbecilidad @v1, @v2, @resultado
   /* Mostrar el resultado en la consola de SQL Server */
   select 'El resultado es: ', @resultado
end

Ahora llame al último procedimiento directamente:

execute OtraIdiotez 1, 2

¿Sabe qué valor se muestra en pantalla? ¡nulo, amigo mío, en vez de 3! La variable @resultado no recibe el valor asignado al parámetro de salida @c, durante la llamada interna a ExtremaImbecilidad.

Para aquellos que no están familiarizados con Transact SQL, es necesario saber que la instrucción select puede utilizarse en dos contextos muy diferentes en este dialecto. Dentro de ExtremaImbecilidad, cada valor mencionado en la cláusula se asigna a una variable local. Este es el equivalente al select/into de Oracle e InterBase. El ejemplo utilizado en OtraIdiotez, sin embargo, no tiene equivalente directo en estos sistemas. Si no hay variables a las que asignar los valores del select, dichos valores se muestran en la propia ventana de SQL Query Analizer, o se ignoran en caso contrario. Esta es una técnica bastante primitiva para depurar procedimientos almacenados. Pero también se utilizan los select libres para programar procedimientos de selección en Transact SQL: procedimientos que devuelven un conjunto de filas como resultado.

La explicación: el tonto compilador de TransactSQL no verifica los prototipos de los procedimientos que llamamos (muy en el estilo de una gente capaz de alumbrar un Visual Basic). Cuando pasamos @resultado, el compilador lo acepta alegremente y mete en la pila el valor de la variable, cuando lo que hace falte meter es su dirección:

   execute ExtremaImbecilidad @v1, @v2, @resultado output

La palabra reservada output funciona en este caso como un operador de referencia, que toma la dirección de la variable precedente y la introduce en la pila.

¿Por qué no había tropezado antes con este problema? Sencillamente porque (gracias a Dios) nunca había tenido que desarrollar ningún programa realmente grande con SQL Server. Y siempre que había programado un procedimiento almacenado con parámetros de salida, terminaba llamando al procedimiento desde Delphi o C++ Builder. De hecho, podía haberme imaginado lo que estaba sucediendo. ¿Se ha dado cuenta de que Delphi es incapaz de adivinar si los parámetros de un procedimiento almacenado de SQL Server son de entrada o de salida? Al parecer, esta información no está disponible en el catálogo de la base de datos.

Por este motivo, desde ayer una nota adorna mi monitor, con un mensaje escrito en letras bien grandes:

¡La dirección, idiota, no te olvides de pasar la dirección!