pasar un operando como un parámetro sql

Actualmente estoy trabajando en una aplicación asp.net que tiene el servidor sql 2008 como backend. Quiero darle al usuario la capacidad de especificar lo que quiere filtrar en la declaración SQL. En la interfaz, les doy la opción de seleccionar lo siguiente como un menú desplegable: igual a mayor que menor que, etc.

Quiero pasar esto como un parámetro en la consulta sql que se ejecutará. ¿Cómo puedo lograr esto de la mejor manera?

por ejemplo;

Select amount, deduction, month from loan where amount @operant 10000;

el @operand son los valores devueltos del menú desplegable anterior, que es = < > <= >=

preguntado el 22 de mayo de 12 a las 14:05

¿Cuál es el tipo de datos de Amount? -

3 Respuestas

Suponiendo que todos los números enteros positivos < 2 mil millones, esta solución evita consultas múltiples y SQL dinámico. OPTION (RECOMPILE) ayuda a frustrar el rastreo de parámetros, pero esto puede no ser necesario según el tamaño de la tabla, la configuración de parámetros y la configuración de "optimizar para carga de trabajo ad hoc".

WHERE [Amount] BETWEEN 
CASE WHEN @operand LIKE '<%' THEN 0
     WHEN @operand = '>' THEN @operant + 1
     ELSE @operant END
AND
CASE WHEN @operand LIKE '>%' THEN 2147483647
     WHEN @operand = '<' THEN @operant - 1
     ELSE @operant END
OPTION (RECOMPILE);

contestado el 22 de mayo de 12 a las 15:05

@buckley ¿Por qué es divertido? Si las partes de la consulta que no podemos ver son extremadamente complejas, ¿crees que es mejor repetir la consulta completa 5 veces? El SQL dinámico también se vuelve menos deseable en ese caso porque es mucho menos mantenible (principalmente por la legibilidad, pero también particularmente si hay otros parámetros en la consulta que tampoco podemos ver). Es solo una opción. No tiene que gustarte, pero tampoco tienes que reírte. - Aarón Bertrand

Ups, pensé que estabas siendo gracioso, sin intención de hacer daño de mi parte. Cambiaré al modo profesional entonces y no te compraré el almuerzo ya que tengo que mantener eso. (Tenga en cuenta que ahora estoy tratando de ser gracioso). Esta consulta no comunica la intención del programador que la escribió originalmente. El código debe transmitir la intención y no tratar de ser inteligente. Y estás siendo inteligente aquí. El sql dinámico solo se diferencia del normal en que debe reemplazar las comillas simples por 2 de ellas y hacer algunas concatenaciones/introducir marcadores de posición. Si está de acuerdo en que esta es la única diferencia, diferimos en gusto. - Buckley

Clever es subjetivo y si evita algunas de las otras limitaciones, y son peores, no creo que deban descartarse. Si bien estoy a favor de crear código autodocumentado, tampoco existe una ley que prohíba agregar comentarios si algo es intencionalmente poco intuitivo. Otra vez no dije "YO, ESTO DE AQUI ES MEJOR EN TODOS LOS CASOS!!!" Solo lo ofrezco como una opción alternativa. Muchas soluciones "inteligentes" siguen siendo la mejor solución, incluso si un novato absoluto no lo entiende a primera vista. El objetivo principal de su código suele ser el rendimiento/mantenibilidad, no necesariamente en ese orden.- Aarón Bertrand

Y no, las comillas simples y los marcadores de posición/concatenación no son la única diferencia. Con SQL dinámico, pierde la codificación de colores en el editor, así como IntelliSense visual y de tiempo de ejecución. ¿Alguna vez ha intentado depurar una instrucción SQL dinámica de 500 líneas, también conocida como "el mar rojo"? - Aarón Bertrand

Wow eso es muy creativo. Rescata SARGability que pensé que era imposible. - usr

Escribiría algunas declaraciones "SI". El código no es muy corto, pero debe ser rápido.

IF(@operand = '=')
Select..
ELSE IF(@operand = '>=')
Select..
...

Además, diría que Top (@someRowCount) podría ser una gran idea.

contestado el 22 de mayo de 12 a las 14:05

Eso es lo que menciono al enumerar todas las combinaciones posibles. Si el escenario del OP sigue siendo tan simple como este, es factible (5 variaciones) pero no escala. Desde mi experiencia como desarrollador, también diría que violas un poco el principio DRY, pero dado que es tan local, el mantenedor probablemente no se olvide de ajustar un cambio a 5 en lugar de 1 lugar. Aún así, no es óptimo IMO - Buckley

Por qué TOP ser una gran idea? El OP no ha indicado que solo quieren @someRowCount filas Si hay 10,000 XNUMX filas que coinciden con los criterios, ¿por qué solo mostrar un subconjunto? - Aarón Bertrand

Buena idea de @AaronBertrand en caso de que la tabla tenga millones de filas. Por lo general, al usuario no le importan más filas de las que puede ver en una página. tener" - Janis

Ese es un detalle de implementación completamente diferente y en realidad cambia el significado y el resultado de la consulta. - Aarón Bertrand

Necesitas sql dinámico para este escenario

Para tu ejemplo esto puede ser

DECLARE @sql AS nvarchar(max) -- Use max if you can, if you set 
  -- this to a specific size then your assignment later can be 
  -- truncated when maintained and still be valid.

SET @sql = 'Select amount, deduction, month from dbo.loan where amount ' 
  + @operand + ' 10000'

EXEC sp_executesql @sql

actualización 1

Hay 2 formas de ejecutar sql dinámico: Exec() y sp_executesql

Lea los comentarios por los que se prefiere sp_executesql (aún así, ¡cuidado con las inyecciones de sql!)

También prefijo la tabla con el dbo para que el plan de ejecución se pueda almacenar en caché entre diferentes usuarios

Más información en el artículo impresionante en http://www.sommarskog.se/dynamic_sql.html#queryplans

contestado el 22 de mayo de 12 a las 15:05

Una cosa a tener en cuenta cuando donig sql dinámico es "inyección de sql". Hay mucha información en la red al respecto. Para evitar una inyección, es mejor que haga coincidir @operand con los valores que espera y, si es inesperado, no lo ejecute: Buckley

no es muy eficiente... y riesgos de seguridad. - Janis

@Janis Tiene un riesgo de seguridad que todo dba/dev debe tener en cuenta. La otra alternativa, enumerar todas las combinaciones posibles de consulta, es factible aquí debido a la variación limitada, pero aún es engorrosa y no es mejor que sql dinámico. ¿Por qué crees que no es eficiente? ¿Crees que el plan de ejecución no está en caché? - Buckley

y otra cosa a tener en cuenta son los derechos de usuario. Si usa "Exec (..)", entonces las cadenas de propiedad no funcionan y el usuario debe tener acceso a las tablas base o el procedimiento debe estar firmado o alguna otra opción (hay al menos uno más). - Janis

@Janis sus comentarios de seguridad son legítimos. No estoy de acuerdo con la afirmación vaga de "no muy eficiente". - Aarón Bertrand

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.