我正在尝试将一些参数添加到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更新了上面的脚本。
答案 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;