TSQL Where子句基于临时表数据

时间:2017-01-11 16:03:01

标签: sql-server tsql stored-procedures sql-server-2012

我正在使用一个直接的SQL查询,并试图找出处理where子句的最佳方法。

基本上,创建了两个临时表,如果传递给存储过程的XML字符串中有数据,则会填充这些表。

我的where子句需要检查这些临时表中的数据,如果没有数据,它会忽略它们,就像它们不存在一样,并获取所有数据。

    -- Create temp tables to hold our XML filter criteria
    DECLARE @users AS TABLE (QID VARCHAR(10))
    DECLARE @dls   AS TABLE (dlName VARCHAR(50))

    -- Insert our XML filters
    IF @xml.exist('/root/data/users') > 0
    BEGIN
        INSERT INTO @users( QID )
        SELECT ParamValues.x1.value('QID[1]', 'varchar(10)')
        FROM   @xml.nodes('/root/data/users/user') AS ParamValues(x1)
    END
    IF @xml.exist('/root/data/dls') > 0
    BEGIN
        INSERT INTO @dls( dlName )
        SELECT ParamValues.x1.value('dlName[1]', 'varchar(50)')
        FROM   @xml.nodes('/root/data/dld/dl') AS ParamValues(x1)
    END

    -- Fetch our document details based on the XML provided
    SELECT d.documentID ,
           d.sopID ,
           d.documentName ,
           d.folderLocation ,
           d.userGroup ,
           d.notes 
    FROM dbo.Documents AS d
    LEFT JOIN dbo.DocumentContacts AS dc
    ON dc.documentID = d.documentID
    LEFT JOIN dbo.DocumentContactsDLs AS dl
    ON dl.documentID = d.documentID
    -- How can I make these two logic checks work only if there is data, otherwise, include everything.
    WHERE dc.QID IN (SELECT QID FROM @users)
    AND dl.DL IN (SELECT dlName FROM @dls)

    FOR    XML PATH ('data'), ELEMENTS, TYPE, ROOT('root');

在上面的查询中,我只是在它们中有数据的情况下尝试使用临时表中的数据,否则,它需要像where语句那样表示该特定值并且包括记录,无论如何。

示例:如果只有@users有数据,则会忽略AND dl.DL IN (SELECT dlName FROM @dls)并获取所有内容,无论这些已加入记录的DL列中的内容是什么。

2 个答案:

答案 0 :(得分:0)

使用NOT EXISTS检查variable表中是否存在任何记录。这是一种方式

WHERE  ( dc.QID IN (SELECT QID FROM @users)
          OR NOT EXISTS (SELECT 1 FROM @users) )
       AND ( dl.DL IN (SELECT dlName FROM @dls)
              OR NOT EXISTS (SELECT 1 FROM @dls) ) 

答案 1 :(得分:0)

试试这个。但请注意,我没有机会正确测试它,我相信你想首先检查@users中的值,如果该表中没有记录,那么你想检查@dls中的条目。此外,如果这两个表中都没有条目,那么您希望跳过这两个表。

DECLARE @fl bit = 0
SELECT @fl = CASE WHEN EXISTS (SELECT 1 FROM @users) THEN 
 1
WHEN EXISTS (SELECT 1 FROM @dls) THEN  
2
ELSE 
0
END

WHERE  (    (dc.QID IN (SELECT QID FROM @users) AND @fl = 1)
        OR 
            (dl.DL IN (SELECT dlName FROM @dls) AND @fl = 2)
        OR  (1=1 AND @fl = 0)
        )