SQL Server:NOT IN in where 子句不能与 NVARCHAR 一起使用

Posted

技术标签:

【中文标题】SQL Server:NOT IN in where 子句不能与 NVARCHAR 一起使用【英文标题】:SQL Server: NOT IN in where clause not working with NVARCHAR 【发布时间】:2017-01-31 11:30:40 【问题描述】:

我有下表:

DECLARE @P AS TABLE
(
    ID int,
    PID  int,
    PNAME NVARCHAR(30),
    PARENT_PNAME NVARCHAR(30),
    Error int
)

INSERT INTO @P VALUES
(554,1,'AAAA',NULL,0),
(554,2,'BBBB',NULL,0),
(554,3,'CCCC',NULL,0),
(554,4,'DDDD','AAAA',0),
(554,5,'EEEE','AAAA',0),
(554,6,'FFFF',NULL,0),
(554,7,'GGGG',NULL,0),
(554,8,'HHHH',NULL,0),
(554,9,'IIII',NULL,0),
(554,10,'JJJJ',NULL,0),
(554,11,'KKKK',NULL,0);

如果我运行以下查询:

select ID, PID, PNAME, PARENT_PNAME,  Error
from   @P                  
where  PNAME not in (select PARENT_PNAME 
                     from   @P
                     where  PNAME is not null)
       AND PARENT_PNAME IS NOT NULL

我什么也得不到,没有结果。为什么“NOT IN”不起作用?

我需要获取以下两行:

(554,4,'DDDD','AAAA',0)
(554,5,'EEEE','AAAA',0)

【问题讨论】:

附带说明:对于您的示例数据,条件 where PNAME is not null 无效,因为所有 PNAME 都不为空。 NOT IN clause and NULL values的可能重复 Chanukya 的回答是正确的(他是第一个写出正确解决方案的人,所以 +1),他没有解释为什么 NOT IN 条件没有返回结果。原因是PARENT_PNAME 的某些值是空的,所以它们不能在NOT IN 运算符中使用。这将始终返回 false。 我不太确定您要应用的标准是什么 - 返回您提到的两行有不同的标准。 【参考方案1】:
DECLARE @P AS TABLE
(
    ID int,
    PID  int,
    PNAME NVARCHAR(30),
    PARENT_PNAME NVARCHAR(30),
    Error int
)

INSERT INTO @P VALUES
(554,1,'AAAA',NULL,0),
(554,2,'BBBB',NULL,0),
(554,3,'CCCC',NULL,0),
(554,4,'DDDD','AAAA',0),
(554,5,'EEEE','AAAA',0),
(554,6,'FFFF',NULL,0),
(554,7,'GGGG',NULL,0),
(554,8,'HHHH',NULL,0),
(554,9,'IIII',NULL,0),
(554,10,'JJJJ',NULL,0),
(554,11,'KKKK',NULL,0);

select * from @P where PARENT_PNAME is not null

输出

ID  PID PNAME   PARENT_PNAME    Error
554 4   DDDD    AAAA    0
554 5   EEEE    AAAA    0

【讨论】:

【参考方案2】:

您不需要NOT IN 子句。试试看:

SELECT * FROM  @P where PARENT_PNAME is NOT NULL

【讨论】:

【参考方案3】:

您还应该在嵌套查询中添加and PARENT_PNAME is not null

SELECT ID, PID, PNAME, PARENT_PNAME, Error
FROM @P
WHERE PNAME NOT IN (
        SELECT PARENT_PNAME
        FROM @P
        WHERE PNAME IS NOT NULL
            AND PARENT_PNAME IS NOT NULL
        )
    AND PARENT_PNAME IS NOT NULL

这就是你没有得到任何结果的原因。

对于more detailed information have a look here

【讨论】:

【参考方案4】:
select ID, PID, PNAME, PARENT_PNAME,  Error
from   @P                  
where  PNAME<>PARENT_PNAME
       AND PARENT_PNAME IS NOT NULL

当你有空值时不要使用 NotIN 进行比较,使用 NOT Exists

【讨论】:

【参考方案5】:

有多种方法可以获得所需的结果。

--method 1    
select ID, PID, PNAME, PARENT_PNAME,  Error
from   @P P1                 
where EXISTS (select PARENT_PNAME 
                 from   @P P2
                 where  p2.PNAME = p1.PNAME 
                        and P1.PARENT_PNAME is not null)

--query 2
select P1.* 
from @P  P1
where P1.PARENT_PNAME is not null

【讨论】:

以上是关于SQL Server:NOT IN in where 子句不能与 NVARCHAR 一起使用的主要内容,如果未能解决你的问题,请参考以下文章