2008-09-27 24 views
5

Problema:SQL Server: dinámico, donde cláusula

Ajax-sugerir búsqueda en [n] ingredientes en recetas. Es decir: combinar recetas contra múltiples ingredientes.

Por ejemplo: SELECT Recipes using "flower", "salt" produciría: "Pizza", "Bread", "Saltwater" y así sucesivamente.

Tablas:

Ingredients [ 
    IngredientsID INT [PK], 
    IngredientsName VARCHAR 
] 

Recipes [ 
    RecipesID INT [PK], 
    RecipesName VARCHAR 
] 

IngredientsRecipes [ 
    IngredientsRecipesID INT [PK], 
    IngredientsID INT, 
    RecipesID INT 
] 

consulta:

SELECT 
    Recipes.RecipesID, 
    Recipes.RecipesName, 
    Ingredients.IngredientsID, 
    Ingredients.IngredientsName 
FROM 
    IngredientsRecipes 

    INNER JOIN Ingredients 
    ON IngredientsRecipes.IngredientsID = Ingredients.IngredientsID 

    INNER JOIN Recipes 
    ON IngredientsRecipes.RecipesID = Recipes.RecipesID 
WHERE 
    Ingredients.IngredientsName IN ('salt', 'water', 'flower') 

Actualmente estoy construyendo mi consulta utilizando ASP.NET C#, debido a la naturaleza dinámica de la cláusula WHERE.

Muerdo que tengo que construir la consulta en mi capa de código en lugar de usar un procedimiento almacenado/SQL puro, que en teoría debería ser mucho más rápido.

¿Tienen alguna idea de cómo movería toda la lógica de mi capa de código a SQL puro, o al menos cómo puedo optimizar el rendimiento de lo que estoy haciendo?

estoy pensando en la línea de tablas temporales:

paso uno: SELECT IngredientsID FROM Ingredients y INSERT INTO temp-table

dos pasos: SELECT RecipesName FROM Recipes se unieron a IngredientsRecipes unido a temp-table.IngredientsID

Respuesta

7

Usted tiene dos opciones. Si está utilizando SQL Server 2008 (u Oracle) puede pasar un table value parameter.

Si está utilizando SQL Server 2005, puede utilizar XML to simulate this capability

Si está utilizando una versión anterior a 2005, lo que necesita para concatenar los identificadores en una sola cadena y crear una UDF para analizarlos.

+0

Awesome news, Mike. ¡Gracias un montón! :) – roosteronacid

2

Dependiendo de cómo se están procesando los ingredientes de entrada. Creo que este método actual tiene algunos riesgos de inyección de sql.

Puede agregar el nombre de ingrediant a las condiciones de unión que pueden ser más rápidas.

También puede combinar combinaciones de ingredientes para recetas para una búsqueda rápida.

+0

estoy de acuerdo. Los problemas de inyección de scripts también son una de mis preocupaciones. ¿Podrías dar más detalles sobre "hasing"? Si tiene – roosteronacid

+0

al usuario elegir entre una lista de posibles ingredientes, las de uno en su mesa de ingredientes, se puede usar esos identificadores de programmaticly, en su estado de cuenta dónde y sin problema de inyección. – Brettski

+0

P.E. Si procesa un hash MD5 o SHA1 agregando las palabras harina de agua salada obtendrá un valor (su hash).En su búsqueda, podría simplemente buscar este artículo que coincida con esto. Como está comparando un valor en lugar de una lista, sería más rápido. – alexmac

3

Al menos podrías parametrizar la clausula donde para evitar la inyección de SQL, algo parecido:

using System.Data; 
using System.Data.SqlClient; 
using System.Text; 

class Foo 
{ 
    public static void Main() 
    { 
     string[] parameters = {"salt", "water", "flower"}; 
     SqlConnection connection = new SqlConnection(); 
     SqlCommand command = connection.CreateCommand(); 
     StringBuilder where = new StringBuilder(); 
     for (int i = 0; i < parametes.Length; i++) 
     { 
      if (i != 0) 
       where.Append (","); 
      where.AppendFormat ("@Param{0}", i); 
      command.Parameters.Add (new SqlParameter ("Param" + i, parameters [i])); 
     } 
    } 
} 
+0

Sí. Me estaba encargando de posibles inyecciones. Mike Brown tuvo un golpe de genio. Pero gracias por tu esfuerzo amigo. – roosteronacid