mbi*_*gun 13 c# sql sql-server ado.net stored-procedures
如何以编程方式将搜索条件添加到SQL存储过程?在我的应用程序(C#)中我正在使用存储过程(SQL Server 2008R2)
ALTER PROCEDURE [dbo].[PROC001]
@userID varchar(20),
@password varchar(20)
AS
SELECT * FROM tUsers WHERE RTRIM(Name) = @userID AND RTRIM(Password) = @password
Run Code Online (Sandbox Code Playgroud)
我希望通过更多条件扩展此查询,现在我不知道有多少条件将使用此查询,因为程序执行... 2,3,6或20.我想以编程方式添加这些条件,如:
SELECT * FROM tUsers WHERE RTRIM(Name) = @userID AND RTRIM(Password) = @password
AND Field2 = '1' AND Field3 = '0' OR Field4 <> '8' AND Field5 < '100' ....
Run Code Online (Sandbox Code Playgroud)
是否可以动态地向存储过程发送条件?
Mah*_*mal 17
你可以只在sql中执行此操作,如下所示:
SELECT *
FROM tUsers
WHERE 1 = 1
AND (@userID IS NULL OR RTRIM(Name) = @userID )
AND (@password IS NULL OR RTRIM(Password) = @password)
AND (@field2 IS NULL OR Field2 = @field2)
....
Run Code Online (Sandbox Code Playgroud)
如果任何参数传递给具有NULL值的存储过程,则将忽略整个条件.
请注意:我添加WHERE 1 = 1了以便在没有参数传递给查询的情况下使查询工作,并且在这种情况下alll将返回结果集,因为1 = 1始终为true.
编辑 - 如果可能,基于LINQ的ORM的首选项
如果您不需要在ADO中执行此操作,更好的解决方案是使用ORM,它最终将构建参数化的ad-hoc sql.这是两全其美的 - 您可以获得动态查询的灵活性,没有冗余过滤器来扰乱优化器,查询计划本身是可缓存的,并且您可以免受注入攻击等恶意攻击.基于Linq的ORM查询便于阅读:
// Build up a non-materialized IQueryable<>
var usersQuery = db.Users;
if (!string.IsNullOrEmpty(userID))
{
usersQuery = usersQuery.Where(u => u.Name == userId);
}
// Of course, you wouldn't dream of storing passwords in cleartext.
if (!string.IsNullOrEmpty(anotherField))
{
usersQuery = usersQuery.Where(u => u.AnotherColumn == anotherField);
}
...
// Materialize (and execute) the query
var filteredUsers = usersQuery.ToList();
Run Code Online (Sandbox Code Playgroud)
对于复杂查询,您可能需要查看PredicateBuilder
ADO /手动查询构建
您可以使用sp_executesql以下方式动态构建SQL.如果您参数化变量,那么您应该安全地处理SQL注入和转义引号等问题.
CREATE PROCEDURE [dbo].[PROC001]
@userID varchar(20),
@pwdHash varchar(20),
@optionalParam1 NVARCHAR(50) = NULL -- Other optional parameters
AS
BEGIN
SET NOCOUNT ON
DECLARE @SQL NVARCHAR(MAX)
-- Mandatory / Static part of the Query here.
-- Cleartext passwords are verboten, and RTRIM is redundant in filters
SET @SQL = N'SELECT * FROM tUsers WHERE Name = @userID AND PwdHash = @pwdHash'
IF @OptionalParam1 IS NOT NULL
BEGIN
SET @SQL = @SQL + N' AND AnotherField = @OptionalParam1'
END
EXEC sp_executesql @SQL,
N'@userID varchar(20),
@pwdHash varchar(20),
@optionalParam1 NVARCHAR(50)'
,@userID = @userID
,@pwdHash = @pwdHash
,@optionalParam1 = @optionalParam1
END
Run Code Online (Sandbox Code Playgroud)
Re,为什么是WHERE (@x IS NULL OR @x = Column)个坏主意?
(摘自我的评论)
虽然"可选参数"模式可以很好地用作"瑞士军刀",用于在小型表格上查询可选过滤器的多种排列,但遗憾的是,对于大型表格,这会导致针对所有过滤器排列的单个查询计划查询,由于参数嗅探问题,可能导致查询性能较差以及可选参数的某些排列.如果可能,您应该完全消除冗余过滤器.
Re:为什么在谓词中应用函数是一个坏主意
例如
WHERE SomeFunction(Column) = @someParameter
Run Code Online (Sandbox Code Playgroud)
在谓词中使用函数经常会使RDBMS使用索引失去资格("不可思考").
在这种情况下,RTRIM由于Sql服务器在比较期间忽略尾随空格,因此是不必要的.
| 归档时间: |
|
| 查看次数: |
29458 次 |
| 最近记录: |