Условное UNION в хранимой процедуре - PullRequest
10 голосов
/ 20 января 2011

Bonjour!

Итак, в хранимой процедуре я хотел бы сделать условное объединение, определяемое параметром.Как я могу это сделать?

Вот моя процедура "не работает":

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO


CREATE PROCEDURE [dbo].[spp_GetAdressesList]

    @OnlyLinked   bit         = 1,    
    @ObligedId    int         = -1 
AS 
BEGIN

    SELECT 
       [ID_ADRESS]
      ,[ID_ENT]
      ,[VOI_ADRESS]
      ,[NUM_ADRESS]
      ,[BTE_ADRESS]
      ,[CP_ADRESS]
      ,[VIL_ADRESS]

    FROM [ADRESSES]
    WHERE  
    (

        (VIL_ADRESS != 'NC' AND VIL_ADRESS != '--')
        AND
        (@OnlyLinked = 0 OR ID_ENT is not null)

    )

    IF (@ObligedId != -1)
    BEGIN
        UNION
            SELECT 
               [ID_ADRESS]
              ,[ID_ENT]
              ,[VOI_ADRESS]
              ,[NUM_ADRESS]
              ,[BTE_ADRESS]
              ,[CP_ADRESS]
              ,[VIL_ADRESS]

            FROM [ADRESSES]
            WHERE  
            ID_ADRESS = @ObligedId
    END

END

Так что если @ObligedId est = a -1, я бы хотел, чтобыUNION.

Я сделал это с помощью динамического запроса varchar, в конце я выполнял запрос с помощью exec.Но это, очевидно, менее эффективно, и вы можете сделать SQL инъекцию (это для приложения asp.net) с динамическими запросами.Я решил изменить все свои хранимые процедуры

Невозможно выполнить объединение в предложении IF?

Спасибо за все ответы без исключений ..

Ответы [ 4 ]

23 голосов
/ 20 января 2011

Обычно, чтобы выполнить объединение на основе регистра, вы преобразуете псевдо

select 1 AS A
IF @b!=-1 then
    union all
    select 2 as B
END IF

в

select 1 AS A
    union all
    select 2 as B WHERE @b!=-1  -- the condition covers the entire select
             -- because it is a variable test, SQL Server does it first and
             -- aborts the entire part of the union if not true

Для вашего запроса, который становится

SELECT 
   [ID_ADRESS],[ID_ENT],[VOI_ADRESS],[NUM_ADRESS],[BTE_ADRESS]
  ,[CP_ADRESS],[VIL_ADRESS]
FROM [ADRESSES]
WHERE  
(
    (VIL_ADRESS != 'NC' AND VIL_ADRESS != '--')
    AND
    (@OnlyLinked = 0 OR ID_ENT is not null)
)
    UNION
        SELECT 
           [ID_ADRESS],[ID_ENT],[VOI_ADRESS],[NUM_ADRESS],[BTE_ADRESS]
          ,[CP_ADRESS],[VIL_ADRESS]
        FROM [ADRESSES]
        WHERE  
        ID_ADRESS = @ObligedId
        AND (@ObligedId != -1)

ОднакоТак как в этом конкретном запросе данные из одной и той же таблицы просто разные фильтры, вы бы ИЛИ фильтры вместо этого. Примечание: , если вы использовали UNION ALL, его нельзя уменьшить таким образом из-за возможных дубликатов, которые сохраняет UNION ALL.Для UNION (который в любом случае удаляет дубликаты) сокращение OR работает просто отлично

SELECT 
   [ID_ADRESS],[ID_ENT],[VOI_ADRESS],[NUM_ADRESS],[BTE_ADRESS]
  ,[CP_ADRESS],[VIL_ADRESS]
FROM [ADRESSES]
WHERE  
(
    (VIL_ADRESS != 'NC' AND VIL_ADRESS != '--')
    AND
    (@OnlyLinked = 0 OR ID_ENT is not null)
)
OR
(
    ID_ADRESS = @ObligedId
    AND (@ObligedId != -1)   -- include this
)
1 голос
/ 20 января 2011

Не могли бы вы просто переписать ваш запрос следующим образом:

SELECT 
   [ID_ADRESS]
  ,[ID_ENT]
  ,[VOI_ADRESS]
  ,[NUM_ADRESS]
  ,[BTE_ADRESS]
  ,[CP_ADRESS]
  ,[VIL_ADRESS]

FROM [ADRESSES]
WHERE  
(

    (VIL_ADRESS != 'NC' AND VIL_ADRESS != '--')
    AND
    (@OnlyLinked = 0 OR ID_ENT is not null)

)
Or ID_ADRESS = @ObligedId

Если @obligedid равно -1, он не найдет идентификатор и там не вернет строку. Если это действительный идентификатор, он вернет строку вместе со строками, возвращенными в первом запросе.

1 голос
/ 20 января 2011

Вы можете использовать предложение where для выбора любого конца объединения:

select col1, col2 from TableA where @Param = 1
UNION ALL
select col1, col2 from TableB where @Param = 2

В вашем примере вы можете полностью опустить оператор IF, поскольку ни один адрес не будет иметь ID_ADDRESS -1.

0 голосов
/ 20 января 2011

Мне любопытно, не получилось бы использовать один выбор, а затем использовать два оператора where, но разделить их символом или как

 SELECT [ID_ADRESS],
       [ID_ENT],
       [VOI_ADRESS],
       [NUM_ADRESS],
       [BTE_ADRESS],
       [CP_ADRESS],
       [VIL_ADRESS]      
FROM [ADRESSES]     
WHERE       
(          
  (VIL_ADRESS != 'NC' AND VIL_ADRESS != '--')         
AND         
  (@OnlyLinked = 0 OR ID_ENT is not null)      
) OR ID_ADRESS =-1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...