在存储过程命令中构建动态 where 子句
Building a dynamic where clause in a stored procedure command
我有一个存储过程,其中的参数如下所示
Create Procedure [dbo].[myStoredProcedure]
@TaskId int = 0
, @FileName varchar(200) =''
, @DataDtFrom smalldatetime = '01/01/1900'
, @DataDtTo smalldatetime = '01/01/1900'
, @OFFSET INT = 0
, @FETCH INT = 2000
, @WhereClauseString varchar(5000) = ''
SELECT
DataDt
,EffDt
,LoanNumber
,UploadDate
,UploadedFileName
FROM dbo.myFileTable u
WHERE
(@DataDtTo = '01/01/1900' or DataDt between @DataDtFrom and @DataDtTo)
and (@TaskId = 0 or TaskId = @TaskId)
and (@FileName = '' or UploadedFileName like '%' + @FileName + '%')
**Where ??? = @WhereClauseString**
ORDER BY u.UploadDate
OFFSET @OFFSET ROWS
FETCH NEXT @FETCH ROWS ONLY
我用 C# 初始化这个
var whereClauseString = "LoanNum in(111,222,444) and TaskId in (123,456,789)";
using (var conn = new MyEntities().Database.Connection)
{
conn.Open();
var cmd = conn.CreateCommand();
cmd.CommandTimeout = 1800;
cmd.CommandText = model.UploadStoredProcedure;
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.Parameters.Add(new System.Data.SqlClient.SqlParameter("@TaskId", Convert.ToInt64(model.TaskId)));
cmd.Parameters.Add(new System.Data.SqlClient.SqlParameter("@FileName", model.FileName ?? string.Empty));
cmd.Parameters.Add(new System.Data.SqlClient.SqlParameter("@DataDtFrom", DateTime.Parse(model.adjFromDataDt.ToShortDateString()) <= DateTime.Parse(basicDate.ToShortDateString()) ? basicDate : model.adjFromDataDt.Date));
cmd.Parameters.Add(new System.Data.SqlClient.SqlParameter("@DataDtTo", DateTime.Parse(model.adjToDataDt.ToShortDateString()) <= DateTime.Parse(basicDate.ToShortDateString()) ? basicDate : model.adjToDataDt.Date));
cmd.Parameters.Add(new System.Data.SqlClient.SqlParameter("@OFFSET", model.Page));
cmd.Parameters.Add(new System.Data.SqlClient.SqlParameter("@FETCH", model.PageSize));
**Dynamic Where clause** -->> System.Data.SqlClient.SqlParameter("@WhereClause", whereClauseString));
var da = new System.Data.SqlClient.SqlDataAdapter((System.Data.SqlClient.SqlCommand)cmd);
da.Fill(ds);
}
我的问题是可以构建一个动态的 where 子句并将其传递给存储过程并对 where 子句中引用的列进行排序吗?
我如何知道我需要存储过程中的哪些列在 where 子句中被引用?
这个存储过程和Entity Framework可以实现这样的事情吗?
无论如何,如果您的数据库远离使用 SQL 注入的外部攻击,您仍然可以考虑基于 Dinamic SQL 的简单解决方案,通常这种方式可以快速解决非常复杂的问题,否则:
CREATE Procedure [dbo].[myStoredProcedure]
@TaskId int = 0
, @FileName varchar(200) =''
, @DataDtFrom smalldatetime = '01/01/1900'
, @DataDtTo smalldatetime = '01/01/1900'
, @OFFSET INT = 0
, @FETCH INT = 2000
, @WhereClauseString varchar(5000) = ''
AS
BEGIN
DECLARE @SQL AS NVARCHAR(MAX);
SELECT @SQL = '
SELECT
DataDt
,EffDt
,LoanNumber
,UploadDate
,UploadedFileName
FROM dbo.myFileTable u
WHERE
('''+CONVERT(CHAR(10), @DataDtTo, 112)+''' = ''01/01/1900'' or DataDt between '''+CONVERT(CHAR(10), @DataDtFrom, 112)+''' and '''+CONVERT(CHAR(10), @DataDtTo, 112)+''')
and ('+CONVERT(CHAR(10), @TaskId)+' = 0 or TaskId = '+CONVERT(CHAR(10), @TaskId)+')
and ('+RTRIM(CONVERT(CHAR(100), @FileName))+' = '''' or UploadedFileName like ''%'+RTRIM(CONVERT(CHAR(100), @FileName))+'%'')
' +CONVERT(CHAR(100), @WhereClauseString)+'
ORDER BY u.UploadDate
OFFSET '+CONVERT(CHAR(10), @OFFSET)+' ROWS
FETCH NEXT '+CONVERT(CHAR(10), @FETCH)+' ROWS ONLY;
'
PRINT @SQL;
EXEC sp_ExecuteSQL @SQL;
END;
我有一个存储过程,其中的参数如下所示
Create Procedure [dbo].[myStoredProcedure]
@TaskId int = 0
, @FileName varchar(200) =''
, @DataDtFrom smalldatetime = '01/01/1900'
, @DataDtTo smalldatetime = '01/01/1900'
, @OFFSET INT = 0
, @FETCH INT = 2000
, @WhereClauseString varchar(5000) = ''
SELECT
DataDt
,EffDt
,LoanNumber
,UploadDate
,UploadedFileName
FROM dbo.myFileTable u
WHERE
(@DataDtTo = '01/01/1900' or DataDt between @DataDtFrom and @DataDtTo)
and (@TaskId = 0 or TaskId = @TaskId)
and (@FileName = '' or UploadedFileName like '%' + @FileName + '%')
**Where ??? = @WhereClauseString**
ORDER BY u.UploadDate
OFFSET @OFFSET ROWS
FETCH NEXT @FETCH ROWS ONLY
我用 C# 初始化这个
var whereClauseString = "LoanNum in(111,222,444) and TaskId in (123,456,789)";
using (var conn = new MyEntities().Database.Connection)
{
conn.Open();
var cmd = conn.CreateCommand();
cmd.CommandTimeout = 1800;
cmd.CommandText = model.UploadStoredProcedure;
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.Parameters.Add(new System.Data.SqlClient.SqlParameter("@TaskId", Convert.ToInt64(model.TaskId)));
cmd.Parameters.Add(new System.Data.SqlClient.SqlParameter("@FileName", model.FileName ?? string.Empty));
cmd.Parameters.Add(new System.Data.SqlClient.SqlParameter("@DataDtFrom", DateTime.Parse(model.adjFromDataDt.ToShortDateString()) <= DateTime.Parse(basicDate.ToShortDateString()) ? basicDate : model.adjFromDataDt.Date));
cmd.Parameters.Add(new System.Data.SqlClient.SqlParameter("@DataDtTo", DateTime.Parse(model.adjToDataDt.ToShortDateString()) <= DateTime.Parse(basicDate.ToShortDateString()) ? basicDate : model.adjToDataDt.Date));
cmd.Parameters.Add(new System.Data.SqlClient.SqlParameter("@OFFSET", model.Page));
cmd.Parameters.Add(new System.Data.SqlClient.SqlParameter("@FETCH", model.PageSize));
**Dynamic Where clause** -->> System.Data.SqlClient.SqlParameter("@WhereClause", whereClauseString));
var da = new System.Data.SqlClient.SqlDataAdapter((System.Data.SqlClient.SqlCommand)cmd);
da.Fill(ds);
}
我的问题是可以构建一个动态的 where 子句并将其传递给存储过程并对 where 子句中引用的列进行排序吗? 我如何知道我需要存储过程中的哪些列在 where 子句中被引用?
这个存储过程和Entity Framework可以实现这样的事情吗?
无论如何,如果您的数据库远离使用 SQL 注入的外部攻击,您仍然可以考虑基于 Dinamic SQL 的简单解决方案,通常这种方式可以快速解决非常复杂的问题,否则:
CREATE Procedure [dbo].[myStoredProcedure]
@TaskId int = 0
, @FileName varchar(200) =''
, @DataDtFrom smalldatetime = '01/01/1900'
, @DataDtTo smalldatetime = '01/01/1900'
, @OFFSET INT = 0
, @FETCH INT = 2000
, @WhereClauseString varchar(5000) = ''
AS
BEGIN
DECLARE @SQL AS NVARCHAR(MAX);
SELECT @SQL = '
SELECT
DataDt
,EffDt
,LoanNumber
,UploadDate
,UploadedFileName
FROM dbo.myFileTable u
WHERE
('''+CONVERT(CHAR(10), @DataDtTo, 112)+''' = ''01/01/1900'' or DataDt between '''+CONVERT(CHAR(10), @DataDtFrom, 112)+''' and '''+CONVERT(CHAR(10), @DataDtTo, 112)+''')
and ('+CONVERT(CHAR(10), @TaskId)+' = 0 or TaskId = '+CONVERT(CHAR(10), @TaskId)+')
and ('+RTRIM(CONVERT(CHAR(100), @FileName))+' = '''' or UploadedFileName like ''%'+RTRIM(CONVERT(CHAR(100), @FileName))+'%'')
' +CONVERT(CHAR(100), @WhereClauseString)+'
ORDER BY u.UploadDate
OFFSET '+CONVERT(CHAR(10), @OFFSET)+' ROWS
FETCH NEXT '+CONVERT(CHAR(10), @FETCH)+' ROWS ONLY;
'
PRINT @SQL;
EXEC sp_ExecuteSQL @SQL;
END;