2016-12-27 104 views
0

我正在尝试向where子句中添加几个参数来代替column_name和value。我在网上看到的所有内容都给出了存储过程中列的值的参数示例,但不是列本身。将参数添加到存储过程的SQL 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中抛出一个错误的情况下语句中的第=标志,并在第二WHEN下,说有一个语法错误CASE声明。

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

+++++编辑+++++

我以前没有提及的是,@SEARCHVALUE的类型必须能够从NVARCHARDATETIME当用户选择“log_ts”作为@SEARCHBY值。我还更新了上面的脚本,用于从我的MVC应用程序进入的参数的DataTypes。

+1

您的@SEARCHBY不能是CHAR(它长于1个字符)。 – DVT

回答

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将允许该过程缓存paramet为同样的存储过程提出了执行计划。否则,在您的Where子句中,这些case statement可能会以一个执行计划结束,这对于特定的一组参数可能是最好的,但对其他任何参数都不是那么好。

还总是专门定义任何varchar/char/nchar/nvarchar变量的长度,否则将其设置为sqlserver默认值为1。在转换/转换功能中,默认值为30,但最好是自己专门使用正确的长度。

+0

因此,SEARCHBY参数将是用户在我创建的应用程序中以字符串形式选择的列的名称。我仍然想使用SYSNAME类型的参数? – tCoe

+2

@tCoe'SYSNAME'是专门为存储SQL Server对象名称(表,列,视图等)而创建的数据类型。是的,这将是您的案例中'@ SEARCHBY'变量的最佳数据类型。 –

+0

一旦我清理了应用程序端,这个工作就完美了。谢谢。 – tCoe

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; 
+0

您建议的两种解决方案都会有一些严重的性能问题:S –

+0

@ M.Ali请注意详细说明吗? – DVT

+0

创建一个表,添加大约一百万行并为其创建一个类似的存储过程,传递不同的值并查看过程是如何运行的,然后使用sp_recompile命令在每次执行前重新编译执行计划,并查看同一过程如何运行相同的值你之前通过了,但没有重新编译它。 –