简体   繁体   English

SQL Server:动态where子句

[英]SQL Server: Dynamic where-clause

Problem: 问题:

Ajax suggest-search on [ n ] ingredients in recipes. Ajax建议 - 在食谱中搜索[ n ]成分。 That is: match recipes against multiple ingredients. 那就是:匹配多种成分的配方。

For instance: SELECT Recipes using "flower", "salt" would produce: "Pizza", "Bread", "Saltwater" and so forth. 例如: SELECT Recipes using "flower", "salt"将产生: "Pizza", "Bread", "Saltwater"等等。

Tables: 表:

Ingredients [
    IngredientsID INT [PK],
    IngredientsName VARCHAR
]

Recipes [
    RecipesID INT [PK],
    RecipesName VARCHAR
]

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

Query: 查询:

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

I am currently constructing my query using ASP.NET C# because of the dynamic nature of the WHERE clause. 我正在使用ASP.NET C#构建我的查询,因为WHERE子句的动态特性。

I bites that I have to construct the query in my code-layer instead of using a stored procedure/pure SQL, which in theory should be much faster. 我咬了一下,我必须在我的代码层中构建查询,而不是使用存储过程/纯SQL,理论上应该更快。

Have you guys got any thoughts on how I would move all of the logic from my code-layer to pure SQL, or at least how I can optimize the performance of what I'm doing? 你有没有想过如何将我的代码层中的所有逻辑移动到纯SQL,或者至少我如何优化我正在做的事情的性能?

I am thinking along the lines of temporary tables: 我正在考虑临时表:

Step one : SELECT IngredientsID FROM Ingredients and INSERT INTO temp-table 第一步SELECT IngredientsID FROM IngredientsINSERT INTO temp-table

Step two : SELECT RecipesName FROM Recipes joined with IngredientsRecipes joined with temp-table.IngredientsID 第二步SELECT RecipesName FROM RecipesIngredientsRecipes加入了temp-table.IngredientsID

You have two options. 你有两个选择。 If you're using SQL Server 2008 (or Oracle) you can pass in a table value parameter . 如果您使用的是SQL Server 2008(或Oracle),则可以传入表值参数

If you're using SQL Server 2005, you can use XML to simulate this capability 如果您使用的是SQL Server 2005,则可以使用XML来模拟此功能

If you're using something earlier than 2005, you need to concatenate the ids in a single string and create a UDF to parse them. 如果你使用的是早于2005的东西,你需要在一个字符串中连接id并创建一个UDF来解析它们。

You could at least parametrize the where clausule to avoid SQL injection, something alike: 你至少可以参数化where clausule以避免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]));
        }
    }
}

Depending on how you are processing the input ingredients I think this current method has some sql injection risks. 根据您处理输入成分的方式,我认为当前的方法存在一些SQL注入风险。

You could append the ingrediant name to the join conditions which may be quicker. 您可以将配线名称附加到可能更快的连接条件。

You could also hash combinations of ingredients for receipes for a quick lookup. 您还可以对配方的成分进行哈希处理,以便快速查找。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM