2008-09-27 12 views
5

Problem:SQL Server: Dynamiczne gdzie klauzula

Ajax sugerują-szukaj w [n] składniki receptur. To znaczy: dopasuj przepisy do wielu składników.

Na przykład: SELECT Recipes using "flower", "salt" będzie produkować: "Pizza", "Bread", "Saltwater" i tak dalej.

Stoły:

Ingredients [ 
    IngredientsID INT [PK], 
    IngredientsName VARCHAR 
] 

Recipes [ 
    RecipesID INT [PK], 
    RecipesName VARCHAR 
] 

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

zapytania:

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') 

Jestem obecnie buduje mojej kwerendy przy użyciu ASP.NET C# ze względu na dynamiczny charakter klauzuli WHERE.

Ugryź, że muszę skonstruować zapytanie w mojej warstwie kodu, zamiast używać procedury składowanej/czystego SQL, która teoretycznie powinna być znacznie szybsza.

Czy macie jakieś przemyślenia na temat tego, jak przenieść całą logikę z mojej warstwy kodu do czystego SQL, a przynajmniej jak mogę zoptymalizować wydajność tego, co robię?

myślę wzdłuż linii tabel tymczasowych:

Krok pierwszy: SELECT IngredientsID FROM Ingredients i INSERT INTO temp-table

Krok drugi: SELECT RecipesName FROM Recipes połączone z IngredientsRecipes połączone z temp-table.IngredientsID

Odpowiedz

7

Masz dwie opcje. Jeśli używasz programu SQL Server 2008 (lub Oracle), możesz przekazać numer table value parameter.

Jeśli używasz SQL Server 2005, można użyć XML to simulate this capability

Jeśli używasz coś wcześniej niż 2005, trzeba złączyć identyfikatory w jednym ciągu i tworzyć UDF je analizować.

+0

Niesamowita wiadomość, Mike. Wielkie dzięki! :) – roosteronacid

2

w zależności od sposobu przetwarzają składniki wejściowe Myślę, że ta obecna metoda ma pewne ryzyko wtrysku sql.

Możesz dodać nazwę ingrediant do warunków łączenia, które mogą być szybsze.

Można również użyć kombinacji składników dla recept do szybkiego wyszukiwania.

+0

zgadzam. Problemy z wtłaczaniem skryptów są również jedną z moich obaw. Czy mógłbyś rozwinąć temat "hasing"? – roosteronacid

+0

Jeśli użytkownik wybierze z listy możliwych składników, swój w tabeli składników, można programowo używać tych identyfikatorów, w swoim oświadczeniu where i bez problemu z iniekcją. – Brettski

+0

E.g. Jeśli przetworzysz sumę kontrolną MD5 lub SHA1, dołączając słowa mąka z mąki słonej, otrzymasz jedną wartość (twój skrót).Podczas wyszukiwania możesz po prostu wyszukać ten element pasujący do tego. Porównując jedną wartość zamiast listy, będzie to szybsze. – alexmac

3

Można przynajmniej parametryzują gdzie clausule uniknąć SQL injection, coś alike:

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

Tak. Dbałem o potencjalne zastrzyki. Mike Brown wpadł na pomysł geniuszu. Ale dzięki za twój wysiłek kolego. – roosteronacid