2008-10-02 6 views
0

Я нахожусь на SQL Server 2005, и я получаю сообщение об ошибке, которое, я уверен, не должен получать.Подзапрос в предложении IN(), вызывающем ошибку

Msg 512, Level 16, State 1, Procedure spGetSavedSearchesByAdminUser, Line 8 Subquery 
returned more than 1 value. This is not permitted when the subquery 
follows =, !=, <, <= , >, >= or when the subquery is used as an expression. 

Я следую пример # B на this MSDN ссылку.

Мой сохраненный код proc выглядит следующим образом. Я могу упростить его ради этого поста, если вы запрашиваете так:

ALTER PROCEDURE [dbo].[spGetSavedSearchesByAdminUser] 
    @strUserName varchar(50) 
    ,@bitQuickSearch bit = 0 
AS 

BEGIN 

    SELECT [intSearchID] ,strSearchTypeCode ,[strSearchName] 
    FROM [tblAdminSearches] 

    WHERE 
     strUserName = @strUserName 
     AND 
     strSearchTypeCode 
      IN (
       CASE @bitQuickSearch 
       WHEN 1 THEN 'Quick' 
       ELSE (SELECT strSearchTypeCode FROM tblAdvanceSearchTypes) 
       END 
      ) 

    ORDER BY strSearchName 
END 

Я проверил нет несоответствия типов данных между результирующим из подзапроса и strSearchTypeCode подзапрос результат сравнивается с.

Я не вижу причин, почему это не должно работать. Если у вас есть какие-либо подсказки, пожалуйста, дайте мне знать.

ответ

4

Try переставляя запрос таким образом, что логическое выражение происходит внутри подвыборки, например,

ALTER PROCEDURE [dbo].[spGetSavedSearchesByAdminUser] 
    @strUserName varchar(50) 
    ,@bitQuickSearch bit = 0 
AS 

BEGIN 

    SELECT [intSearchID] ,strSearchTypeCode ,[strSearchName] 
    FROM [tblAdminSearches] 

    WHERE 
     strUserName = @strUserName 
     AND 
     strSearchTypeCode 
       IN (SELECT strSearchTypeCode FROM tblAdvanceSearchTypes where @bitQuickSearch=0 
        UNION 
        SELECT 'Quick' AS strSearchTypeCode WHERE @bitQuickSearch=1) 

    ORDER BY strSearchName 
END 
+0

Я бы сделал это UNION ALL, так как даже если у вас есть обманы, это не имеет особого значения в предложении IN. – 2008-10-02 16:47:05

2

Я не знаю, что вы можете использовать оператор CASE внутри предложения IN таким образом. Я хотел бы предложить, что перезапись бит на:

WHERE strUserName = @strUserName AND (
    (@bitQuickSearch = 1 AND strSearchTypeCode = 'Quick') 
    OR 
    (strSearchTypeCode IN (SELECT strSearchTypeCode FROM tblAdvanceSearchTypes)) 
) 

или, если вам действительно нравится стиль, который вы получили там:

WHERE strUserName = @strUserName 
    AND strSearchTypeCode IN (
     SELECT CASE @bitQuickSearch WHEN 1 THEN 'Quick' ELSE strSearchTypeCode END 
     FROM tblAdvanceSearchTypes 
    ) 

В общем, SQL должен быть умным, чтобы достаточно умны, чтобы оптимизировать на таблицу if @bitQuickSearch = 1. Но я бы точно проверял план запроса (доверяю, но проверяю).

2

Мне кажется, что это SELECT:

SELECT strSearchTypeCode FROM tblAdvanceSearchTypes 

возвращает несколько строк, и это ваша проблема. Вы можете переписать его, чтобы быть:

SELECT TOP 1 strSearchTypeCode FROM tblAdvanceSearchTypes