Este es un problema que he pasado horas investigando en el pasado. Me parece que es algo que las soluciones modernas RDBMS deberían haber abordado, pero hasta ahora no he encontrado nada que realmente aborde lo que considero una necesidad increíblemente común en cualquier aplicación Web o Windows con un back-end de base de datos.Clasificación dinámica dentro de los procedimientos almacenados de SQL
Hablo de ordenación dinámica. En mi mundo de fantasía, debería ser tan simple como algo así como:
ORDER BY @sortCol1, @sortCol2
Este es el ejemplo canónico dada por SQL novato y Stored Procedure desarrolladores de todo foros a través de Internet. "¿Por qué no es esto posible?" ellos preguntan. Invariablemente, alguien finalmente llega para darles una conferencia acerca de la naturaleza compilada de los procedimientos almacenados, de los planes de ejecución en general, y todo tipo de otras razones por las cuales no es posible poner un parámetro directamente en una cláusula ORDER BY
.
Sé lo que algunos de ustedes ya están pensando: "Deje que el cliente haga la clasificación, entonces". Naturalmente, esto descarga el trabajo de su base de datos. Sin embargo, en nuestro caso, nuestros servidores de bases de datos ni siquiera están empezando a sudar el 99% del tiempo y ni siquiera son multinúcleo o cualquiera de las otras innumerables mejoras a la arquitectura del sistema que ocurren cada 6 meses. Solo por esta razón, hacer que nuestras bases de datos manejen la clasificación no sería un problema. Además, las bases de datos son muy bien en la clasificación. Están optimizados para ello y han tenido años para hacerlo bien, el lenguaje para hacerlo es increíblemente flexible, intuitivo y simple y, sobre todo, cualquier escritor principiante de SQL sabe cómo hacerlo y, lo que es más importante, saben cómo editarlo. hacer cambios, hacer mantenimiento, etc. Cuando sus bases de datos están lejos de ser gravadas y usted simplemente quiere simplificar (y acortar) el tiempo de desarrollo, esto parece una opción obvia.
Luego está el problema de la web. He jugado con JavaScript que hará la ordenación de tablas HTML por el lado del cliente, pero inevitablemente no son lo suficientemente flexibles para mis necesidades y, una vez más, dado que mis bases de datos no son excesivamente exigentes y realmente puedo clasificar realmente , Me cuesta mucho justificar el tiempo que tomaría volver a escribir o rodar mi propio clasificador de JavaScript. Lo mismo ocurre en general con la clasificación del lado del servidor, aunque ya es probablemente preferible a JavaScript. No soy uno que le guste especialmente la sobrecarga de DataSets, así que denígame.
Pero esto trae de vuelta el punto de que no es posible — o más bien, no es fácil. He hecho, con sistemas anteriores, una forma increíble de hackear la clasificación dinámica. No era bonito, ni intuitivo, simple o flexible, y un escritor de SQL principiante se perdería en cuestión de segundos. Ya esto no es tanto una "solución" sino una "complicación".
Los siguientes ejemplos no están destinados para exponer cualquier tipo de mejores prácticas o buen estilo de codificación o nada, ni son indicativos de mis habilidades como programador de T-SQL. Son lo que son y reconozco que son confusos, de mala forma y simplemente piratean.
Pasamos un valor entero como parámetro a un procedimiento almacenado (llamemos simplemente al parámetro "ordenar") y de eso determinamos un grupo de otras variables. Por ejemplo ... digamos que es un género 1 (o por defecto):
DECLARE @sortCol1 AS varchar(20)
DECLARE @sortCol2 AS varchar(20)
DECLARE @dir1 AS varchar(20)
DECLARE @dir2 AS varchar(20)
DECLARE @col1 AS varchar(20)
DECLARE @col2 AS varchar(20)
SET @col1 = 'storagedatetime';
SET @col2 = 'vehicleid';
IF @sort = 1 -- Default sort.
BEGIN
SET @sortCol1 = @col1;
SET @dir1 = 'asc';
SET @sortCol2 = @col2;
SET @dir2 = 'asc';
END
ELSE IF @sort = 2 -- Reversed order default sort.
BEGIN
SET @sortCol1 = @col1;
SET @dir1 = 'desc';
SET @sortCol2 = @col2;
SET @dir2 = 'desc';
END
Ya se puede ver como si declaré más variables @colX para definir otras columnas que podía realmente ser creativo con las columnas para ordenar basado en el valor de "ordenar" ...para usarlo, por lo general termina pareciéndose a la siguiente cláusula increíblemente desordenado:
ORDER BY
CASE @dir1
WHEN 'desc' THEN
CASE @sortCol1
WHEN @col1 THEN [storagedatetime]
WHEN @col2 THEN [vehicleid]
END
END DESC,
CASE @dir1
WHEN 'asc' THEN
CASE @sortCol1
WHEN @col1 THEN [storagedatetime]
WHEN @col2 THEN [vehicleid]
END
END,
CASE @dir2
WHEN 'desc' THEN
CASE @sortCol2
WHEN @col1 THEN [storagedatetime]
WHEN @col2 THEN [vehicleid]
END
END DESC,
CASE @dir2
WHEN 'asc' THEN
CASE @sortCol2
WHEN @col1 THEN [storagedatetime]
WHEN @col2 THEN [vehicleid]
END
END
Obviamente, esto es un ejemplo muy simplificada. Las cosas reales, ya que usualmente tenemos cuatro o cinco columnas para apoyar la clasificación, cada una con una posible segunda columna secundaria o incluso una tercera para ordenar además de eso (por ejemplo, fecha descendente, luego ordenadas de forma secundaria por nombre ascendente) y cada una de clasificación direccional que efectivamente duplica el número de casos. Sí ... se pone peludo muy rápido.
La idea es que uno podría "fácilmente" cambiar los casos de clasificación de modo que vehicleid se clasifique antes de la fecha de almacenamiento ... pero la pseudo-flexibilidad, al menos en este simple ejemplo, realmente termina ahí. Esencialmente, cada caso que falla una prueba (porque nuestro método de clasificación no se aplica a esta vez) representa un valor NULO. Y así terminas con una cláusula que funciona de la siguiente manera:
ORDER BY NULL DESC, NULL, [storagedatetime] DESC, blah blah
Ya entendiste la idea. Funciona porque SQL Server efectivamente ignora valores nulos en orden por cláusulas. Esto es increíblemente difícil de mantener, ya que cualquiera con conocimientos básicos de SQL puede ver. Si he perdido a alguno de ustedes, no se sientan mal. Nos llevó mucho tiempo hacerlo funcionar y aún nos confundimos al tratar de editarlo o crear otros nuevos como este. Afortunadamente, no es necesario cambiar a menudo, de lo contrario, rápidamente "no valdría la pena".
Sin embargo, hizo trabajo.
Mi pregunta es entonces: hay una manera mejor?
Estoy de acuerdo con las soluciones que no sean procedimientos almacenados, ya que me doy cuenta de que puede no ser el camino a seguir. Preferiblemente, me gustaría saber si alguien puede hacerlo mejor dentro del Procedimiento almacenado, pero si no, ¿cómo se las arregla para que el usuario pueda ordenar dinámicamente las tablas de datos (bidireccionalmente también) con ASP.NET?
¡Y gracias por leer (o al menos rozar) una pregunta tan larga!
PS: Alégrate de que no me muestro mi ejemplo de un procedimiento almacenado que apoya la clasificación dinámica, filtrado dinámico/texto-búsqueda de columnas, la paginación a través de ROWNUMBER() OVER, Y try ... catch con la transacción rollbacking en errores ... "del tamaño de un gigante" ni siquiera comienza a describirlos.
Actualización:
- me gustaría evitar SQL dinámico. Analizar una cadena y ejecutar un EXEC en ella derrota el propósito de tener un procedimiento almacenado en primer lugar. A veces me pregunto si los inconvenientes de hacer tal cosa no valdrían la pena, al menos en estos casos especiales de clasificación dinámica. Aún así, siempre me siento sucio cada vez que hago cadenas dinámicas de SQL como esa — como si todavía estuviera viviendo en el mundo ASP clásico.
- Una gran parte de la razón por la que queremos que los procedimientos almacenados en primer lugar sea para security. No llego a hacer un llamado por cuestiones de seguridad, solo sugiero soluciones. Con SQL Server 2005 podemos establecer permisos (por usuario, si es necesario) a nivel de esquema en procedimientos almacenados individuales y luego negar cualquier consulta directamente a las tablas.Criticar los pros y los contras de este enfoque es tal vez para otra pregunta, pero nuevamente no es mi decisión. Solo soy el mono del código principal. :)
Consulte http://stackoverflow.com/questions/3659981/sql-server-dynamic-order-by-with-mixed-datatypes-is-this-a-good-idea también - SQL Server dinámico ORDER BY con tipos de datos mixtos – Lijo
SQL dinámico es la forma LEJANA ... SI [y esta es una gran IF] ... tu capa de acceso a datos es estricta y tu SQL dinámico es generado por un sistema rígidamente programado con reglas RDBMS expresadas en forma perfecta . Una arquitectura de base de ingeniería algorítmica es una cosa de belleza ... – hajikelist