Как я могу использовать IF ELSE в предложении WHERE на основе строковой переменной?

#sql-server-2008 #stored-procedures

#sql-server-2008 #хранимые процедуры

Вопрос:

У меня есть SP. Возвращает некоторое количество строк. Вот SP:

 ALTER PROCEDURE [dbo].[spGetClients]
  

(
@orderBy varchar(50),
@startAge int,
@endAge int,
@sex char,
@staffId nvarchar(1024),
@statusId nvarchar(1024),
@ethnicityId nvarchar(1024),
@treatmentProviderId nvarchar(1024)
)
AS
BEGIN
SET NOCOUNT ON;

 IF(@orderBy = 'Consumer Name')
BEGIN
    SELECT c.Id, dbo.GetClientFullName(c.FirstName, c.MiddleInit, c.LastName) AS ClientName, 
    c.DateOfBirth, dbo.GetAge(c.DateOfBirth, GETDATE()) AS Age, c.Sex, 
    dbo.GetClientStatus(c.Id, @statusId) AS Status, ca.Address, co.Phone, 
    dbo.GetEthnicity(c.Id, @ethnicityId) AS Ethnicity, dbo.GetDevelopmentalDisabilities(c.Id) AS Disabilities, 
    dbo.GetClientStaffContacts(c.Id, @staffId) AS Staff, dbo.GetClientContacts(c.Id) AS Contact, 
    dbo.GetClientInsuranceProviders(c.Id) AS HealthProvider, 
    dbo.GetClientTreatmentProviders(c.Id, @treatmentProviderId) AS TreatmentProvider
    FROM Client c  
    LEFT OUTER JOIN(        
        SELECT ca.ParentEntityId, ca.Address
        FROM ContactAddress ca
        INNER JOIN EntityName en ON en.Id = ca.EntityNameId AND en.Name = 'Client' 
        INNER JOIN GeneralLookup gl ON ca.glAddressTypeId = gl.Id AND gl.LookupItem = 'Primary'    
    ) ca ON c.Id = ca.ParentEntityId 
    LEFT OUTER JOIN(        
        SELECT co.ParentEntityId, co.ContactData Phone
        FROM ContactOther co
        INNER JOIN EntityName en ON en.Id = co.EntityNameId AND en.Name = 'Client' 
        INNER JOIN GeneralLookup gl ON co.glContactTypeId = gl.Id AND gl.LookupItem = 'Home'    
    ) co ON c.Id = co.ParentEntityId 
    LEFT OUTER JOIN GeneralStatus gs on gs.Id = c.StatusId
    where gs.Name <> 'Deleted' 
    and (dbo.GetAge(c.DateOfBirth, GETDATE()) BETWEEN @startAge and @endAge)
    and ((@sex = 'M' and c.sex = 'M') or (@sex = 'F' and c.Sex = 'F') or (@sex = '' and (c.Sex in ('M', 'F', ''))))
    and dbo.GetClientStaffContacts(c.Id, @staffId) is not null
    and dbo.GetClientStaffContacts(c.Id, @staffId) is not null
    and dbo.GetClientStatus(c.Id, @statusId) is not null 
    and dbo.GetEthnicity(c.Id, @ethnicityId) is not null 
    and dbo.GetClientTreatmentProviders(c.Id, @treatmentProviderId) is not null
    ORDER BY ClientName
END
END
  

UDFS (определяемые пользователем функции) являются dbo.GetClientStaffContacts(c.Id, @StaffID) и другие. Они возвращают некоторые строки, которые также имеют значение null. Вот почему я использую последние 5 операторов в предложении where, чтобы можно было собирать только ненулевые значения. Все работает нормально, но проблема в том, что я хочу эту проверку на ненулевое значение только тогда, когда эти переменные НЕ являются пустой строкой:

 @staffId nvarchar(1024), 
@statusId nvarchar(1024), 
@ethnicityId nvarchar(1024), 
@treatmentProviderId nvarchar(1024)
  

Как я могу решить эту проблему?
Я хочу что-то вроде этого:

If @staffId <> '' then dbo.GetClientStaffContacts(c.Id, @staffId) is not null

Ответ №1:

  AND  ((@staffId = "") OR (dbo.GetClientStaffContacts(c.Id, @staffId) is not null))
  

Комментарии:

1. Я использовал это: AND Case @staffId WHEN '' THEN 1=1 ELSE dbo.GetClientStaffContacts(c.Id, @staffId) is not null END Выдает ошибку Incorrect syntax near '='

2. Извините — Ответ изменен — прошло некоторое время с тех пор, как я писал SQL lol

3. Это решение также работает отлично. Можете ли вы немного объяснить это?

4. Довольно просто, оно будет включать строку, если любое из двух предложений возвращает true. Итак, либо where @staffid = «», либо если StaffID !=»», то он попробует второе предложение и вызовет функцию, проверяющую ненулевой возврат.

Ответ №2:

Вы не можете выполнять логические сравнения в инструкции CASE. Вы должны создать значение из выражения case, и тип каждого возможного созданного значения должен быть одинаковым или конвертируемым:

 CASE @staffId
    WHEN "" THEN 1
    ELSE
       CASE
           WHEN dbo.GetClientStaffContacts(c.Id, @staffId) is not null THEN 1
           ELSE 0
       END
END = 1
  

Какое условие вы могли бы поставить в своем WHERE предложении


Возможны две формы выражения РЕГИСТРА:

  • Простой СЛУЧАЙ (когда вы пытаетесь найти предложение WHEN, равное указанному значению после ключевого слова CASE) — это то, что делает выражение внешнего РЕГИСТРА (пытается найти предложение WHEN, соответствующее @StaffId значению).
  • Искомый РЕГИСТР (когда вы пытаетесь сопоставить предложение WHEN на основе произвольных предикатов) — это то, что делает внутреннее выражение CASE (проверяет, не равно ли возвращаемое функцией значение null)

Вы не можете определить НУЛЕВОЙ / ненулевой статус, используя простое выражение CASE, поскольку NULL не равно NULL (равно и не равно).

Комментарии:

1. Эй, это работает отлично. Большое спасибо. Можете ли вы объяснить это немного подробнее, чем то, что здесь делает второй СЛУЧАЙ?

2. Я отметил ответ на первый, потому что он более простой. Я хотел отметить вашу переменную, но это было бы более полезно для будущих пользователей, ищущих этот вопрос.. Надеюсь, вы не будете возражать 🙂