使用 NULL 忽略参数(如果为空)时,存储过程不返回过滤结果 [英] Stored Procedure not returning filtered results when using NULL to ignore parameter if empty

查看:26
本文介绍了使用 NULL 忽略参数(如果为空)时,存储过程不返回过滤结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个查询,用户可以在其中选择他们希望搜索的列(每列在网络上都有一个相应的过滤器).如果参数作为 NULL 传递到数据库中,我已经使用 NULL 方法尝试忽略该参数.将所有字段设为 NULL 会按预期工作并返回所有记录,但在尝试过滤信息时,结果是相同的,并且查询会返回所有内容.

I have a query in which the user can choose which columns they wish to search on (each column has a corresponding filter on the web). I've used the NULL method to try and ignore the parameter if it is passed into the DB as NULL. Having all fields NULL works as expected and returns all records, but when attempting to filter the information the results are the same and the query returns everything.

我似乎无法找出为什么会发生这种情况,它可能是非常小而明显的东西,但我就是看不到它.

I can't seem to find out why this might be happening, it could be something really small and obvious but I just can't see it.

ALTER PROCEDURE [dbo].[GetChatListFilter] 
    @SiteKey int,
    @invited int = NULL,
    @starttime varchar(15),
    @finishtime varchar(15) = NULL,
    @visitor varchar(50) = NULL,
    @wait int = NULL,
    @operators varchar(max) = NULL,
    @department varchar(max) = NULL,
    @skills varchar(max) = NULL,
    @chattime int = NULL,
    @rating int = NULL,
    @email varchar(max) = NULL,
    @message varchar(max) = NULL,
    @dns varchar(max) = NULL,
    @visit varchar(max) = NULL,
    @city varchar(max) = NULL,
    @country varchar(max) = NULL
AS

    SELECT        
        UserChats.Invited, 
        UserChats.StartTime AS Start, 
        UserChats.FinishTime AS Finish, 
        UserChats.VisitorName As Visitor, 
        UserChats.WaitedForSecs AS Wait, 
        UserChats.TakenByUser AS Operator, 
        UserChats.TakenByDept AS [Dept.], 
        dbo.SkillIDsToName(UserChats.SkillIDList) AS Skill,
        UserChats.ChattedForSecs AS [Time], 
        UserChats.Rating AS Rate, 
        UserChats.MessageEmail AS Email, 
        UserChats.MessageText AS [Message], 
        UserChats.VisitorIP AS DNS, 
        UserChats.VisitorVisitNumber AS Visit, 
        VisitDetail.City, 
        VisitDetail.Country
    FROM             
        UserChats 
    INNER JOIN
        VisitDetail ON  UserChats.VisitID =  VisitDetail.VisitID
    WHERE 
        UserChats.SiteKey = @SiteKey AND
        UserChats.Invited = @invited OR @invited is NULL AND
        UserChats.StartTime = @starttime OR @starttime = '01/01/1900' AND
        UserChats.FinishTime = @finishtime OR @finishtime = '01/01/1900' AND
        UserChats.VisitorName = @visitor OR @visitor is NULL AND
        UserChats.WaitedForSecs = @wait OR @wait is NULL AND
        UserChats.TakenByUser = @operators OR @operators is NULL AND
        UserChats.TakenByDept = @department OR @department is NULL AND
        dbo.SkillIDsToName(UserChats.SkillIDList) = @skills OR @skills is NULL AND
        UserChats.ChattedForSecs = @chattime OR @chattime is NULL AND
        UserChats.Rating = @rating OR @rating is NULL AND
        UserChats.MessageEmail = @email OR @email is NULL AND
        UserChats.MessageText = @message OR @message is NULL AND
        UserChats.VisitorIP = @dns OR @dns is NULL AND
        UserChats.VisitorVisitNumber = @visit OR @visit is NULL AND
        VisitDetail.City = @city OR @city is NULL AND
        VisitDetail.Country = @country or @country is NULL

推荐答案

正如我上面所说的,我可能会在这里使用动态代码,因为您的查询包含很多 OR 语句.我已经像这样重写了你的程序.请留下评论或想法.

As I told above, I perhaps would go for dynamic code here, since your query contains a lot of OR statements. I've rewritten your procedure like that. Please leave a comment or ideas.

我能想到的所有记录都没有回来 - 你硬编码了 @starttime@finishtime,只需处理它们.我尝试在这段代码中做到这一点,但是在没有示例数据的情况下很难.

What I can think of all records not comming back - you hardcoded @starttime and @finishtime, just deal with them. I tried to do it in this code, but it's quite hard when there's no sample data.

ALTER PROCEDURE [dbo].[GetChatListFilter]
(
    @SiteKey INT
    , @invited INT = NULL
    , @starttime VARCHAR(15)
    , @finishtime VARCHAR(15) = NULL
    , @visitor VARCHAR(50) = NULL
    , @wait INT = NULL
    , @operators VARCHAR(MAX) = NULL
    , @department VARCHAR(MAX) = NULL
    , @skills VARCHAR(MAX) = NULL
    , @chattime INT = NULL
    , @rating INT = NULL
    , @email VARCHAR(MAX) = NULL
    , @message VARCHAR(MAX) = NULL
    , @dns VARCHAR(MAX) = NULL
    , @visit VARCHAR(MAX) = NULL
    , @city VARCHAR(MAX) = NULL
    , @country VARCHAR(MAX) = NULL
)
AS
BEGIN
    SET NOCOUNT ON;
    BEGIN TRY
        DECLARE @SQL NVARCHAR(MAX)
            , @SQLParams NVARCHAR(MAX);

        SET @SQL = N'
            SELECT UC.Invited
                , UC.StartTime AS Start
                , UC.FinishTime AS Finish
                , UC.VisitorName AS Visitor
                , UC.WaitedForSecs AS Wait
                , UC.TakenByUser AS Operator
                , UC.TakenByDept AS [Dept.]
                , dbo.SkillIDsToName(UC.SkillIDList) AS Skill
                , UC.ChattedForSecs AS [Time]
                , UC.Rating AS Rate
                , UC.MessageEmail AS Email
                , UC.MessageText AS [Message]
                , UC.VisitorIP AS DNS
                , UC.VisitorVisitNumber AS Visit
                , VD.City
                , VD.Country
            FROM dbo.UserChats AS UC
            INNER JOIN dbo.VisitDetail AS VD
                ON UC.VisitID = VD.VisitID
            WHERE UC.SiteKey = @p0';

        IF NULLIF(@invited, '') IS NOT NULL                 SET @SQL += N' AND UC.Invited = @p1';
        IF NULLIF(@starttime, '01/01/1900') IS NOT NULL     SET @SQL += N' AND UC.StartTime = @p2';
        IF NULLIF(@finishtime, '01/01/1900') IS NOT NULL    SET @SQL += N' AND UC.FinishTime = @p3';
        IF NULLIF(@visitor, '') IS NOT NULL                 SET @SQL += N' AND UC.VisitorName = @p4';
        IF NULLIF(@wait, '') IS NOT NULL                    SET @SQL += N' AND UC.WaitedForSecs = @p5';
        IF NULLIF(@operators, '') IS NOT NULL               SET @SQL += N' AND UC.TakenByUser = @p6';
        IF NULLIF(@department, '') IS NOT NULL              SET @SQL += N' AND UC.TakenByDept = @p7';
        IF NULLIF(@skills, '') IS NOT NULL                  SET @SQL += N' AND dbo.SkillIDsToName = @p8';
        IF NULLIF(@chattime, '') IS NOT NULL                SET @SQL += N' AND UC.ChattedForSecs = @p9';
        IF NULLIF(@rating, '') IS NOT NULL                  SET @SQL += N' AND UC.Rating = @p10';
        IF NULLIF(@email, '') IS NOT NULL                   SET @SQL += N' AND UC.MessageEmail = @p11';
        IF NULLIF(@message, '') IS NOT NULL                 SET @SQL += N' AND UC.MessageText = @p12';
        IF NULLIF(@dns, '') IS NOT NULL                     SET @SQL += N' AND UC.VisitorIP = @p13';
        IF NULLIF(@visit, '') IS NOT NULL                   SET @SQL += N' AND UC.VisitorVisitNumber @p14';
        IF NULLIF(@city, '') IS NOT NULL                    SET @SQL += N' AND VD.City = @p15';
        IF NULLIF(@country, '') IS NOT NULL                 SET @SQL += N' AND VD.Country = @p16';

        SET @SQLParams = N'
              @p0 INT
            , @p1 INT
            , @p2 VARCHAR(15)
            , @p3 VARCHAR(15)
            , @p4 VARCHAR(50)
            , @p5 INT
            , @p6 VARCHAR(MAX)
            , @p7 VARCHAR(MAX)
            , @p8 VARCHAR(MAX)
            , @p9 INT
            , @p10 INT
            , @p11 VARCHAR(MAX)
            , @p12 VARCHAR(MAX)
            , @p13 VARCHAR(MAX)
            , @p14 VARCHAR(MAX)
            , @p15 VARCHAR(MAX)
            , @p16 VARCHAR(MAX)';

        EXECUTE sp_executesql @SQL
            , @SQLParams
            , @p0 = @SiteKey
            , @p1 = @invited
            , @p2 = @starttime
            , @p3 = @finishtime
            , @p4 = @visitor
            , @p5 = @wait
            , @p6 = @operators
            , @p7 = @department
            , @p8 = @skills
            , @p9 = @chattime
            , @p10 = @rating
            , @p11 = @email
            , @p12 = @message
            , @p13 = @dns
            , @p14 = @visit
            , @p15 = @city
            , @p16 = @country;
    END TRY
    BEGIN CATCH
        SELECT ERROR_MESSAGE();
    END CATCH
END

这篇关于使用 NULL 忽略参数(如果为空)时,存储过程不返回过滤结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆