将参数添加到存储过程的SQL where子句column_name

时间:2016-12-27 19:58:38

标签: sql-server stored-procedures parameters

我正在尝试将一些参数添加到where子句来代替column_name和值。我在网上看到的所有内容都给出了存储过程中已有列的值参数的示例,但不是列本身的参数。

这是我到目前为止所做的:

CREATE PROCEDURE [mobile].[p_get_insptn_log_by_date]
    (@SEARCHBY SYSNAME, @SEARCHVALUE NVARCHAR(100))
AS 
    SET NOCOUNT ON

    SELECT 
        [id], [application_name], [login_id], [log_ts],
        [insptn_log_msg_type_code], [log_msg_text], [insptn_log_lvl_code]
    FROM 
        [dbo].[Insptn_log]
    WHERE 
        insptn_log_lvl_code <> 'info' AND
        CASE 
           WHEN @SEARCHBY = 'application_name' 
              THEN application_name = @SEARCHVALUE
           WHEN @SEARCHBY = 'login_id' 
              THEN login_id = @SEARCHVALUE
           WHEN @SEARCHBY = 'log_ts' log_ts < CONVERT(DATETIME, @SEARCHVALUE)
        END

实际上,SQL Server Management Studio抛出一个错误,指出case语句中的第一个=符号和WHEN语句中的第二个CASE下面存在语法错误。

我只是在寻找正确的语法来完成这项任务。任何帮助将不胜感激。

+++++ +++++ EDIT

我之前没有提到,当用户选择“log_ts”作为{{1}时,@SEARCHVALUE的类型必须能够从NVARCHAR转到DATETIME价值。我还为我的MVC应用程序中的Params的DataTypes更新了上面的脚本。

2 个答案:

答案 0 :(得分:2)

这样做更有效率和更流畅的方式就像......

CREATE PROC [mobile].[p_get_insptn_log_by_date]
    @SEARCHBY SYSNAME           = NULL   --<-- Use appropriate data type
  , @SEARCHVALUE NVARCHAR(1000) = NULL   --<-- Use appropriate data length
AS 
BEGIN
    SET NOCOUNT ON;
Declare @Sql NVARCHAR(MAX);

SET @Sql = N'SELECT  [id]
                    ,[application_name]
                    ,[login_id]
                    ,[log_ts]
                    ,[insptn_log_msg_type_code]
                    ,[log_msg_text]
                    ,[insptn_log_lvl_code]
            FROM [dbo].[Insptn_log]
            WHERE insptn_log_lvl_code <> ''info''' 
            + CASE WHEN @SEARCHBY IS NOT NULL AND @SEARCHVALUE IS NOT NULL 
              THEN N' AND ' + QUOTENAME(@SEARCHBY) + N' = @SEARCHVALUE' ELSE N'' END

Exec sp_executesql @Sql
                    ,N'@SEARCHVALUE NVARCHAR(1000)'
                    ,@SEARCHVALUE 
END

使用sp_executesql将允许该过程缓存同一存储过程的参数化执行计划。否则,在where子句中使用这些case statement,您最终可能会得到一个执行计划,该计划可能最适合一组特定参数,但对于任何其他参数集都不是那么好。

还始终专门定义任何varchar / char / nchar / nvarchar变量的长度,否则将其设置为sql server default 1。在cast / convert函数中,默认值为30,但最好自己专门使用正确的长度。

答案 1 :(得分:0)

试试这个

CREATE PROC [mobile].[p_get_insptn_log_by_date](@SEARCHBY VARCHAR(100), @SEARCHVALUE NVARCHAR )

AS 
SET NOCOUNT ON
SELECT [id]
,[application_name]
,[login_id]
,[log_ts]
,[insptn_log_msg_type_code]
,[log_msg_text]
, [insptn_log_lvl_code]
FROM [dbo].[Insptn_log]
WHERE insptn_log_lvl_code <> 'info' and
(( @SEARCHBY = 'application_name' AND  application_name = @SEARCHVALUE)
OR ( @SEARCHBY = 'login_id' AND login_id = @SEARCHVALUE)
OR ( @SEARCHBY = 'log_ts' AND log_ts < @SEARCHVALUE)
)

更好的是,我认为这应该是处理这种情况的更好方法:

CREATE PROC [mobile].[p_get_insptn_log_by_date](@SEARCHBY VARCHAR(100), @SEARCHVALUE NVARCHAR )

AS 
SET NOCOUNT ON

IF (@SEARCHBY = 'application_name')
    BEGIN
    SELECT [id]
    ,[application_name]
    ,[login_id]
    ,[log_ts]
    ,[insptn_log_msg_type_code]
    ,[log_msg_text]
    , [insptn_log_lvl_code]
    FROM [dbo].[Insptn_log]
    WHERE insptn_log_lvl_code <> 'info' and application_name = @SEARCHVALUE
    END
ELSE IF (@SEARCHBY = 'login_id')
    BEGIN
    SELECT [id]
    ,[application_name]
    ,[login_id]
    ,[log_ts]
    ,[insptn_log_msg_type_code]
    ,[log_msg_text]
    , [insptn_log_lvl_code]
    FROM [dbo].[Insptn_log]
    WHERE insptn_log_lvl_code <> 'info' and login_id = @SEARCHVALUE
    END
ELSE IF (@SEARCHBY = 'log_ts')
    BEGIN
    SELECT [id]
    ,[application_name]
    ,[login_id]
    ,[log_ts]
    ,[insptn_log_msg_type_code]
    ,[log_msg_text]
    , [insptn_log_lvl_code]
    FROM [dbo].[Insptn_log]
    WHERE insptn_log_lvl_code <> 'info' and log_ts < @SEARCHVALUE
    END;
相关问题