#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. Я отметил ответ на первый, потому что он более простой. Я хотел отметить вашу переменную, но это было бы более полезно для будущих пользователей, ищущих этот вопрос.. Надеюсь, вы не будете возражать 🙂