2011-01-20 22 views
6

Bonjour!UNION condizionale in stored procedure

Quindi, in una procedura memorizzata vorrei fare un unione condizionale decisa da un parametro. Come posso farlo?

Qui è il mio "non funziona" Procedura:

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 

Quindi, se @ObligedId est = a -1 Vorrei non ha il sindacato.

Ho fatto questo con una query dinamica varchar, alla fine stavo eseguendo la query con un exec. Ma è apparentemente meno efficiente e puoi fare sql injection (è per l'applicazione asp.net) con query dinamiche. Ho deciso di modificare tutte le mie stored procedure

Non è possibile fare un sindacato in una clausola IF?

Grazie per tutte le risposte senza eccezioni ..

+0

'' '' un valore di dati valido per 'ADRESSES.ID_ADRESS'? Se non lo è, puoi sempre fare l'UNION'. Inoltre, "Indirizzo" ha due "d" s :) – AakashM

+2

"indirizzo" in francese .. ok per fare l'unione ma voglio capire come posso farlo se -1 è un ID valido – bAN

risposta

17

Normalmente per fare un caso un'unione basata, di trasformare lo pseudo

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

in

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 

Per la tua ricerca, che diventa

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) 

Tuttavia, dal momento che in questo specifico query, i dati provengono dalla stessa tabella solo filtri diversi, altrimenti si dovrebbero usare i filtri. Nota:se si è utilizzato UNION ALL, non è possibile ridurlo in questo modo a causa di possibili duplicati che UNION ALL conserva. Per UNION (che elimina i duplicati in ogni caso), il o la riduzione funziona bene

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

Segnalando che questo ha il suo i problemi. Sto progettando le clausole WHERE basate sul confronto di un parametro con un valore fisso in quanto questi contengono ancora un sovraccarico.Ho scoperto che SQL Server non richiede query "short-cut", quindi in questo caso elaborerà comunque i dati in base a "ID_ADDRESS = @ObligedId" indipendentemente dal valore di @ObligedId. Questo può aggiungere un overhead delle prestazioni piuttosto brutto. –

+1

@Chris dare un'occhiata qui per una discussione su questo: http://www.sommarskog.se/dyn-search-2008.html e http://www.sommarskog.se/dyn-search-2005.html#OR_ISNULL – RichardTheKiwi

0

Si potrebbe utilizzare una clausola where di scegliere una delle estremità del sindacato:

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

Nel tuo esempio, si potrebbe omettere la dichiarazione IF del tutto, dal momento che nessun indirizzo avrà ID_ADDRESS di -1.

1

Impossibile basta riscrivere la query come questa:

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 

Se @obligedid è pari a -1 non troverà l'Id e là per non restituirà la riga. Se è id valido, restituirà la riga insieme alle righe restituite nella prima query.

0

Sono curioso che non avrebbe funzionato per usare una selezione e quindi utilizzare i due in cui affermazioni, ma separati loro da una o come

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 
+0

lol non ha letto le risposte date finora chiaramente – Andrew