2011-01-20 49 views
6

Bonjour!UNION có điều kiện trong thủ tục được lưu trữ

Vì vậy, trong quy trình được lưu trữ, tôi muốn thực hiện một công đoàn có điều kiện do một tham số quyết định. Tôi có thể làm như thế nào?

Dưới đây là tôi "không hoạt động" thủ tục:

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 

Vì vậy, nếu @ObligedId est = a -1 Tôi muốn không có UNION.

Tôi đã thực hiện điều này với truy vấn varchar động, ở phần cuối tôi đã thực hiện truy vấn với một exec. Nhưng nó có vẻ kém hiệu quả và bạn có thể làm cho tiêm sql (Nó là dành cho ứng dụng asp.net) với các truy vấn động. Tôi quyết định thay đổi tất cả các thủ tục đã lưu của mình

Không thể thực hiện một liên minh trong mệnh đề IF?

Cảm ơn tất cả những câu trả lời mà không ngoại lệ ..

+0

Là '-1' giá trị dữ liệu hợp lệ cho' ADRESSES.ID_ADRESS'? Nếu không, bạn chỉ có thể thực hiện 'UNION'. Ngoài ra, "Địa chỉ" có hai "d" s :) – AakashM

+2

"adresse" bằng tiếng Pháp .. ok để làm công đoàn nhưng tôi muốn hiểu làm thế nào tôi có thể làm điều đó nếu -1 là một ID hợp lệ – bAN

Trả lời

17

Thông thường để làm một trường hợp dựa đoàn, bạn chuyển đổi các giả

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

vào

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 

Đối với truy vấn của bạn, điều đó trở thành

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) 

Tuy nhiên, vì trong cụ này truy vấn, dữ liệu từ cùng một bảng chỉ các bộ lọc khác nhau, bạn sẽ HOẶC các bộ lọc thay thế. Lưu ý:nếu bạn đã sử dụng UNION ALL, nó không thể được giảm theo cách này vì có thể trùng lặp mà UNION ALL bảo tồn. Đối với UNION (mà loại bỏ bản sao anyway), OR giảm chỉ hoạt động tốt

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

Giá trị gắn cờ rằng điều này có riêng của nó các vấn đề. Tôi đang tạo ra các mệnh đề WHERE dựa trên việc so sánh một tham số với một giá trị cố định vì chúng vẫn chứa chi phí.Tôi đã tìm thấy rằng SQL Server không cần thiết phải "cắt ngắn" truy vấn, do đó, trong này thay vào đó nó vẫn sẽ xử lý dữ liệu dựa trên "ID_ADDRESS = @ObligedId" bất kể giá trị của @ObligedId. Điều này có thể thêm một chi phí hiệu suất khá khó chịu. –

+1

@Chris có một cái nhìn ở đây cho một cuộc thảo luận về điều đó: http://www.sommarskog.se/dyn-search-2008.html và http://www.sommarskog.se/dyn-search-2005.html#OR_ISNULL – RichardTheKiwi

0

Bạn có thể sử dụng một điều khoản where để lựa chọn một trong hai đầu của đoàn:

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

Trong ví dụ của bạn, bạn có thể bỏ qua các tuyên bố IF hoàn toàn, vì không có địa chỉ nào có ID_ADDRESS là -1.

1

Không thể bạn chỉ cần viết lại truy vấn của bạn như thế này:

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 

Nếu @obligedid bằng -1 nó sẽ không tìm thấy Id và ở đó sẽ không trả lại hàng. Nếu đó là id hợp lệ thì nó sẽ trả về hàng cùng với các hàng được trả về trong truy vấn đầu tiên.

0

tôi tò mò muốn nó không hoạt động để sử dụng một lựa chọn và sau đó sử dụng hai nơi báo cáo nhưng tách chúng bằng một hoặc như

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 không đọc câu trả lời cho đến nay rõ ràng – Andrew

Các vấn đề liên quan