有没有办法在sql语句中动态构建WHERE子句?
此代码位于存储过程中。我有x个参数,每个参数的默认值是NULL
SELECT *
FROM MyTable m
WHERE
IF(NOT(@Param1 IS NULL))
m.Col1 = @Param1
END IF
AND
IF(NOT(@Param2 IS NULL))
m.Col2 = @Param2
END IF
[编辑:]我正在运行SQL Server 2005。 [编辑:]参数的数量是固定的,但可以有一个NULL值。如果参数具有NULL值,则不应将其包含在WHERE子句中。每个参数也与特定列相关联。
答案 0 :(得分:3)
这不等于以下,没有任何动态行为吗?
SELECT *
FROM MyTable m
WHERE
(@Param1 IS NULL OR m.Col1 = @Param1)
AND
(@Param2 IS NULL OR m.Col2 = @Param2)
或者列本身是否有可能丢失?
答案 1 :(得分:2)
假设SQL Server 2005+语法,因为未指定数据库...强烈建议在解决查询之前阅读:The curse and blessings of dynamic SQL
DECLARE @SQL NVARCHAR(4000)
SET @SQL = N'SELECT m.*
FROM MyTable m
WHERE 1 = 1 '
SET @SQL = @SQL + CASE
WHEN @param1 IS NOT NULL THEN ' AND m.col1 = @param1 '
ELSE ' '
END
SET @SQL = @SQL + CASE
WHEN @param2 IS NOT NULL THEN ' AND m.col2 = @param2 '
ELSE ' '
END
BEGIN
EXEC sp_executesql @SQL,
N'@param1 [replace w/ data type], @param2 [replace w/ data type]'
@param1, @param2
END
答案 2 :(得分:0)
无论您是否使用存储过程,您都可能被迫使用动态sql。在实现这个存储过程之前,请考虑一些事情。
参数本身是动态的吗?你会使用2个参数一个呼叫,10个是下一个吗?如果是这种情况,您将需要创建大量“占位符”存储的proc参数,这些参数可能不会在每次调用时使用。如果定义10个占位符参数然后需要11,该怎么办?这不干净。也许你可以使用某种数组参数....
如果参数是动态的,您将被迫在proc中使用动态SQL。这可以让您了解注入攻击。您必须手动转义存储过程中的所有输入。在proc中使用dymamaic sql会破坏使用procs的主要原因之一。
如果参数是真正动态的,我实际上可能倾向于从代码而不是存储的proc生成sql。为什么?如果从代码生成,则可以使用ADO库来转义输入。
确保你做的事情......
sql =“select * from table where colA = @colA”; // dyanmically生成 SQlCommand.Parameters.add(“@ colA”,valueA);
而不是....
sql =“select * from table where colA =”+ valueA; // dyanmically生成错误的方式
答案 3 :(得分:0)
还要考虑第三件事。如果参数的数据类型是动态的,该怎么办?存储过程开始分崩离析,因为它们是已定义的接口。如果您的操作不符合接口,那么尝试将它们压缩到预先设置的界面将会很难看。
如果您正在制作某种开放式图形查询工具,则会弹出这种情况。大多数情况下,您的数据访问将符合某个界面,但是当它不符合时......存储过程可能不是最佳选择。