SQL Server 存储过程中的条件UNION

6l7fqoea  于 2022-12-03  发布在  其他
关注(0)|答案(4)|浏览(209)

你好!
所以,在一个存储过程中,我想做一个由参数决定的条件并集,我该怎么做呢?
下面是我的“不工作”程序:

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,我想没有并集。
我用一个动态varchar查询完成了这个过程,最后我用一个exec执行查询。但是这显然效率较低,而且你可以用动态查询进行sql注入(这是针对asp.net应用程序的)。我决定改变我所有的存储过程
在IF子句中无法执行并集?
感谢所有的答案没有例外..

lnvxswe2

lnvxswe21#

通常,要执行基于大小写的联合,需要将伪

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)

但是,由于在此特定查询中,数据来自同一个表,只是来自不同的筛选器,因此您应该对筛选器执行OR运算。**注意:***如果使用了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
)
5gfr0r5j

5gfr0r5j2#

您可以使用where子句来选择并集的任一端:

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

在您的示例中,可以完全省略IF语句,因为没有任何地址的ID_ADDRESS为-1。

pcrecxhr

pcrecxhr3#

你能不能把你的查询重写成这样:

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,它将找不到ID,因此不会返回该行。如果它是有效的ID,则它将返回该行沿着第一个查询中返回的行。

bybem2ql

bybem2ql4#

我很好奇,使用一个select语句,然后使用两个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

相关问题