为什么我的存储过程不适用于给定的参数?

时间:2015-12-28 16:46:20

标签: sql sql-server sql-server-2008 tsql sql-server-2012

我有一个需要3个参数的存储过程。 CaseNo, DateFrom, DateTo。我已经写过它应该在这些场景中返回记录的方式。

  1. 仅传递CaseNo
  2. 仅传递日期范围
  3. 传递1& 2
  4. 它适用于日期范围,但不适用于CaseNo,即它返回每个caseNo的记录不仅通过CaseNo,例如如果我通过Case-02,那么它会返回Case-01,Case-03,Case-04等的记录。为什么

    ALTER PROCEDURE [dbo].[Reportcaseandhearingsbycasenoanddates] 
        @CaseNo VARCHAR(20), 
        @DateFrom DATE, 
        @DateTo DATE 
    AS 
    BEGIN 
        SELECT 
            cases.pk_cases_caseid, 
            cases.casetitle, 
            cases.casepetitioner, 
            cases.caseno, 
            cases.caseletterby, 
            cases.caseentrydatetime, 
            casehearings.pk_casehearings_id, 
            casehearings.responder, 
            casehearings.supervisor, 
            casehearings.judge, 
            casehearings.isopeningdate, 
            casehearings.isopeningclosingdate, 
            CONVERT(VARCHAR, casehearings.closingdate, 106) AS ClosingDate, 
            CONVERT(VARCHAR, casehearings.reopeningdate, 106) AS ReOpeningDate, 
            CONVERT(VARCHAR, casehearings.openingdate, 106) AS OpeningDate, 
            casehearings.isconveyed, 
            casehearings.isclosingdate, 
            CONVERT(VARCHAR, casehearings.hearingdate, 106) AS HearingDate, 
            casehearings.fk_concernedoffices_casehearings_concernedofficeid, 
            casehearings.courtorder, 
            casehearings.caseremarks, 
            concernedoffices.concernedofficename, 
            courts.courtname, 
            CONVERT(VARCHAR, casehearings.generaldate, 106) AS GeneralDate, 
            casehearings.ishearingdate 
        FROM   
            cases 
        LEFT JOIN 
            casehearings ON cases.pk_cases_caseid = casehearings.fk_cases_casehearings_caseid 
        LEFT JOIN 
            concernedoffices ON concernedoffices.pk_concernedoffices_id = casehearings.fk_concernedoffices_casehearings_concernedofficeid 
        LEFT JOIN 
            courts ON courts.pk_courts_courtid = casehearings.fk_courts_casehearings_courtid 
        INNER JOIN 
            web_users ON web_users.userid = cases.fk_webusers_cases_userid 
        WHERE  
            cases.caseno LIKE '%' + @CaseNo + '%' 
            OR (casehearings.generaldate >= @DateFrom 
                AND casehearings.generaldate <= @DateTo) 
    END 
    

    我已离开加入,因为有时表可能包含可能不存在的值。

5 个答案:

答案 0 :(得分:1)

我认为这是你正在寻找的东西:

...
(cases.caseno LIKE '%' + @CaseNo + '%' or @CaseNo is NULL) and
(casehearings.generaldate >= @DateFrom or @DateFrom is NULL) AND 
(casehearings.generaldate <= @DateTo or @DateTo is NULL)

这种SQL的问题在于它永远不会使用任何索引。如果您有大量数据,则应该有两种不同的情况(可能是单独的过程)或使用动态SQL并使用sp_executesql执行它

答案 1 :(得分:0)

我相信这就是你要找的东西

  .....
       LEFT JOIN casehearings 
              ON cases.pk_cases_caseid = 
                 casehearings.fk_cases_casehearings_caseid 
                 AND (( casehearings.generaldate >= @DateFrom 
                       AND casehearings.generaldate <= @DateTo 
                       AND @DateFrom <> '' 
                       AND @DateTo <> '' ) or (@DateFrom = '' and @DateTo = '' ))
 .....
WHERE  ( cases.caseno LIKE '%' + @CaseNo + '%' 
         AND @CaseNo <> '' ) 
   OR  ( userID = @userID
         AND @CaseNo <> '' ) 

您的查询中有两个错误

空字符串将转换为1900-01-01,因此您将获得所有记录,因为日期出现在OR条件中。

如果您在filter条款中保留正确的表WhereLeft Outer Join将隐式转换为INNER JOIN,请将filter's移至ON }子句

答案 2 :(得分:0)

也许这个?

Where Cases.CaseNo like '%'+ @CaseNo +'%' OR
         ( CaseHearings.GeneralDate >= @DateFrom
         AND CaseHearings.GeneralDate <= @DateTo)

它的OR条件..只要日期范围是正确的..你会得到所有合适的案例..

更新答案

WHERE 

 CASE WHEN  @CaseNo <> '' AND @DateFrom <> '' AND @DateTo <> '' AND 
          CaseHearings.GeneralDate >= @DateFrom
          AND CaseHearings.GeneralDate <= @DateTo 
          AND cases.caseno LIKE '%' + @CaseNo + '%' 
         THEN 1
      WHEN @CaseNO = '' AND  @DateFrom <> '' AND @DateTo <> '' AND
           CaseHearings.GeneralDate >= @DateFrom
           AND CaseHearings.GeneralDate <= @DateTo 
         THEN 1
      WHEN @CaseNO <> '' AND  @DateFrom = '' AND @DateTo = '' AND
          AND cases.caseno LIKE '%' + @CaseNo + '%' 
         THEN 1
      ELSE 0 END = 1  

答案 3 :(得分:0)

问题是因为您正在过滤WHERE子句中的日期,但该表是LEFT JOIN的右侧。这导致LEFT JOIN表现为INNER JOIN,并且由于您没有传递日期,因此条件失败。

您应该将其移至ON的{​​{1}}子句。此外,您应该为date或caseno为LEFT JOIN时添加条件:

NULL

答案 4 :(得分:0)

感谢社区帮助我。我尝试了@ VR46的建议,并进行了位编辑,并且有效。

Select      Cases.pk_Cases_CaseID, Cases.CaseTitle, Cases.CasePetitioner, Cases.CaseNo, Cases.CaseLetterBy, Cases.CaseEntryDateTime,
            CaseHearings.pk_CaseHearings_ID, CaseHearings.Responder, CaseHearings.Supervisor, CaseHearings.Judge, CaseHearings.IsOpeningDate,
            CaseHearings.IsOpeningClosingDate, Convert(varchar, CaseHearings.ClosingDate, 106) as ClosingDate, Convert(varchar, CaseHearings.ReOpeningDate, 106) as ReOpeningDate , 
            Convert(varchar, CaseHearings.OpeningDate, 106) as OpeningDate , CaseHearings.IsConveyed, 
            CaseHearings.IsClosingDate, Convert(varchar, CaseHearings.HearingDate, 106) as HearingDate, CaseHearings.fk_ConcernedOffices_CaseHearings_ConcernedOfficeID, CaseHearings.CourtOrder, 
            CaseHearings.CaseRemarks, ConcernedOffices.ConcernedOfficeName, Courts.CourtName, Convert(varchar,CaseHearings.GeneralDate, 106) as GeneralDate, CaseHearings.IsHearingDate 
From        Cases
left Join   CaseHearings        ON  Cases.pk_Cases_CaseID= CaseHearings.fk_Cases_CaseHearings_CaseID
                                AND ((@DateFrom ='' And @DateTo ='')
                                    OR (CaseHearings.GeneralDate >= @DateFrom
                                        AND CaseHearings.GeneralDate <= @DateTo
                                        )
                                    )
left Join   ConcernedOffices    ON  ConcernedOffices.pk_ConcernedOffices_ID= CaseHearings.fk_ConcernedOffices_CaseHearings_ConcernedOfficeID
left Join   Courts              ON  Courts.pk_Courts_CourtID= CaseHearings.fk_Courts_CaseHearings_CourtID
Inner Join  Web_Users           ON  Web_Users.UserID= Cases.fk_WebUsers_Cases_UserID
Where (@CaseNo ='' Or (@CaseNo!='' And Cases.CaseNo like '%'+ @CaseNo +'%')) AND Web_Users.UserID=@UserID