SQL Server: динамическое предложение where - PullRequest
5 голосов
/ 28 сентября 2008

Проблема:

Ajax предложить-поиск по [ n ] ингредиентам в рецептах. То есть: совмещать рецепты с несколькими ингредиентами.

Например: SELECT Recipes using "flower", "salt" будет производить: "Pizza", "Bread", "Saltwater" и т. Д.

Таблицы:

Ingredients [
    IngredientsID INT [PK],
    IngredientsName VARCHAR
]

Recipes [
    RecipesID INT [PK],
    RecipesName VARCHAR
]

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

Запрос:

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

В настоящее время я создаю свой запрос с использованием ASP.NET C # из-за динамической природы предложения WHERE.

Я жалею, что мне нужно создать запрос в моем уровне кода вместо использования хранимой процедуры / чистого SQL, что в теории должно быть намного быстрее.

Ребята, вы не задумывались над тем, как перевести всю логику с уровня кода на чистый SQL или, по крайней мере, как я могу оптимизировать производительность того, что я делаю?

Я думаю о временных таблицах:

Шаг первый : SELECT IngredientsID FROM Ingredients и INSERT INTO temp-table

Шаг второй : SELECT RecipesName FROM Recipes соединен с IngredientsRecipes соединен с temp-table.IngredientsID

Ответы [ 3 ]

7 голосов
/ 28 сентября 2008

У вас есть два варианта. Если вы используете SQL Server 2008 (или Oracle), вы можете передать параметр табличного значения .

Если вы используете SQL Server 2005, вы можете использовать XML для имитации этой возможности

Если вы используете что-то ранее 2005 года, вам нужно объединить идентификаторы в одну строку и создать UDF для их анализа.

3 голосов
/ 28 сентября 2008

Можно хотя бы параметризовать условие where, чтобы избежать внедрения SQL, что-то похожее:

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]));
        }
    }
}
2 голосов
/ 28 сентября 2008

В зависимости от того, как вы обрабатываете входные ингредиенты, я думаю, что этот текущий метод имеет некоторые риски инъекции sql.

Вы можете добавить имя ингредиента к условиям соединения, что может быть быстрее.

Вы также можете хэшировать комбинации ингредиентов для рецептов для быстрого поиска.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...