SQL Server:动态 where 子句

Posted

技术标签:

【中文标题】SQL Server:动态 where 子句【英文标题】:SQL Server: Dynamic where-clause 【发布时间】:2010-09-13 18:13:33 【问题描述】:

问题:

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

由于WHERE 子句的动态特性,我目前正在使用 ASP.NET C# 构建查询。

我不得不在我的代码层中构建查询,而不是使用存储过程/纯 SQL,理论上应该更快。

你们对我如何将所有逻辑从我的代码层转移到纯 SQL 或至少如何优化我正在做的事情的性能有任何想法吗?

我正在考虑临时表:

第一步SELECT IngredientsID FROM IngredientsINSERT INTO temp-table

第二步SELECT RecipesName FROM Recipes加入IngredientsRecipes加入temp-table.IngredientsID

【问题讨论】:

【参考方案1】:

你至少可以参数化 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 ("@Param0", i);
            command.Parameters.Add (new SqlParameter ("Param" + i, parameters [i]));
        
    

【讨论】:

是的。我正在处理潜在的注射。迈克布朗想出了一个天才。但是感谢您的努力。【参考方案2】:

你有两个选择。如果您使用的是 SQL Server 2008(或 Oracle),则可以传入 table value parameter。

如果您使用的是 SQL Server 2005,则可以使用XML to simulate this capability

如果您使用的是 2005 年之前的版本,则需要将 id 连接到一个字符串中并创建一个 UDF 来解析它们。

【讨论】:

【参考方案3】:

根据您处理输入成分的方式,我认为当前的方法存在一些 sql 注入风险。

您可以将成分名称附加到可能更快的连接条件中。

您还可以对收据的成分组合进行哈希处理,以便快速查找。

【讨论】:

我同意。脚本注入问题也是我关心的问题之一。你能详细说明一下“拥有”吗? 如果您让用户从可能的成分列表中进行选择,即成分表中的那个,您可以在 where 语句中以编程方式使用这些 ID,并且不会出现注入问题。 例如如果您通过附加单词 salt water flour 来处理 MD5 或 SHA1 哈希,您将获得一个值(您的哈希)。然后,在您的查找中,您可以只查找与此匹配的项目。当您比较一个值而不是一个列表时,它会更快。 那只会给他一个精确的匹配。示例查询的逻辑暗示他想要包含任何成分的食谱。既然您提到了它,但一个技巧是为您的值使用位掩码。

以上是关于SQL Server:动态 where 子句的主要内容,如果未能解决你的问题,请参考以下文章

如何强制 SQL Server 在 WHERE 子句之前处理 CONTAINS 子句?

动态 SQL WHERE 子句生成

动态sql中的where子句

如何在sql中创建动态where子句?

在 SQL 中动态构建 WHERE 子句,无需硬解析即可执行

从搜索表单动态构建 WHERE 子句时如何防止 SQL 注入?