查找SQL Server中是否有包含null的列

查找SQL Server中是否有包含null的列,sql,sql-server,Sql,Sql Server,我是SQL新手,解决这个问题有点困难 我想编写select查询,它返回所有包含空值的行 我在表中有50多列,可以在表中添加一些额外的列,因此我很难编写where条件 我们可以使用的AFAIK为null,但我不想对那么多列重复它 请帮我解决它。如果需要任何其他信息,请告诉我。您可以尝试此动态SQL查询。如果任何列包含空值,此查询将返回行 DECLARE @tb NVARCHAR(255) = N'dbo.[tablename]'; DECLARE @sql NVARCHAR(MAX) = N'S

我是SQL新手,解决这个问题有点困难

我想编写select查询,它返回所有包含空值的行

我在表中有50多列,可以在表中添加一些额外的列,因此我很难编写where条件

我们可以使用的AFAIK为null,但我不想对那么多列重复它


请帮我解决它。如果需要任何其他信息,请告诉我。

您可以尝试此动态SQL查询。如果任何列包含空值,此查询将返回行

DECLARE @tb NVARCHAR(255) = N'dbo.[tablename]';

DECLARE @sql NVARCHAR(MAX) = N'SELECT * FROM ' + @tb
    + ' WHERE 1 = 0';

SELECT @sql += N' OR ' + QUOTENAME(name) + ' IS NULL'
    FROM sys.columns 
    WHERE [object_id] = OBJECT_ID(@tb)
      AND [is_nullable]=1;

EXEC sp_executesql @sql;

除了为什么以及为什么设计一直被忽视的问题之外,还有很多选择

遗憾的是,除非您能够保证其中50+列中的某些列可能为空,否则您将使用复杂的谓词或表扫描

由于这显然无法干净地使用谓词,因此请使用干净的表扫描来测试值,并运行与布尔语句匹配的内部联接

WITH CTE AS (SELECT IIF (col1 IS NULL, 1, (IIF(col2 IS NULL, 1, etc) ) ) as FOUND -- if clears, return 0
FROM TABLEA AS A)

SELECT A.*
FROM CTE A
INNER JOIN TABLEA AS B ON A.ID = B.ID
WHERE A.FOUND = 1
通过这种方式,SQLServer可以相对地处理它,并且谓词是干净的。IIF语句只是将一行值与检查NULL值进行比较,我将测试声明此值的其他方法,以了解函数如何变化,这比在复杂的50行中尝试使用谓词要简单得多!逻辑噩梦


内联函数的关键优势在于,它们可能会被优化,因为它们被设计为粗略地处理数据,而谓词用于关系比较SARG

尝试以下方法:用表替换表名

DECLARE @COLNAME VARCHAR(MAX),@QUERY VARCHAR(MAX),@TABLE VARCHAR(MAX)
DECLARE @TEST TABLE(ID INT)
DECLARE @NULLS TABLE([TABLE] VARCHAR(MAX), [COLUMN] VARCHAR(MAX),[HAS_NULL] VARCHAR(MAX))
SET @TABLE='TABLE_NAME'
DECLARE C CURSOR FOR 
SELECT NAME FROM SYS.ALL_COLUMNS WHERE OBJECT_ID=(SELECT OBJECT_ID FROM SYS.TABLES WHERE NAME=@TABLE)
OPEN C
FETCH NEXT FROM C INTO @COLNAME
WHILE @@FETCH_STATUS=0
BEGIN
SET @QUERY='SELECT COUNT(1) FROM '+@TABLE+' WHERE '+@COLNAME+' IS NULL' 
INSERT INTO @TEST EXEC (@QUERY)
IF(SELECT TOP 1 ID FROM @TEST)>0
BEGIN
INSERT INTO @NULLS VALUES ( @TABLE,@COLNAME,'NULL VALUES')
END
ELSE 
BEGIN
INSERT INTO @NULLS VALUES ( @TABLE,@COLNAME,'NO NULL VALUES')
END
DELETE FROM @TEST
FETCH NEXT FROM C INTO @COLNAME
END
CLOSE C
DEALLOCATE C


SELECT * FROM @NULLS

一种不需要显式列出列的简单方法是

WITH XMLNAMESPACES('http://www.w3.org/2001/XMLSchema-instance' as ns)
SELECT *
FROM   t1 x
WHERE  (SELECT x.*
        FOR xml path('row'), elements xsinil, type
        ).exist('(//*/@ns:nil)') = 1
尽管它确实有完全不必要的转换为XML的开销。

是否要查找所有指定列为空

;WITH tb(ID,col1,col2,col3,col4,col5,col6,col7,col8,col9)AS(
    SELECT 1,1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL UNION
    SELECT 2,NULL,NULL,NULL,NULL,NULL,NULL,3,NULL,NULL UNION
    SELECT 3,1,2,NULL,NULL,NULL,NULL,NULL,NULL,NULL UNION
    SELECT 4,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL 

)
SELECT * FROM tb
WHERE COALESCE(col1,col2,col3,col3,col5,col6,col7,col8,col9) IS NULL
将返回id=4

ID col1 col2 col3 col4 col5 col6 col7 col8 col9 ----------- ----------- ----------- ----------- ----------- ----------- ----------- ----------- ----------- ----------- 4 NULL NULL NULL NULL NULL NULL NULL NULL NULL
您必须给出where子句中的所有列。您必须使用动态SQL自动生成where子句。否则,您就倒霉了——您需要为所有允许空值的列指定它。也就是说,我不确定为什么一个表需要50列,为什么需要检查其中是否有空列;我的猜测是,桌子的设计一开始并不是最优的。这就是设计发挥作用的地方。空值来自哪里?为什么一个未知事件会影响所有50列?如果您不能将NOTNULL强制作为列约束,那么您的表如何实现1NF,更不用说2NF规范化了。这是事实表还是维度表?这个查询回答了什么问题?我知道这可能看起来很陈腐,但在关系理论中,这个查询解决了谜团,而不仅仅是陈述事实。除非您事先知道哪些列可能包含null,或者这是在ETL转换中,否则您的谓词WHERE、ON、have将是奇数。并破坏糟糕的优化器,这可能只是对查询做了一些疯狂的事情。
CREATE TABLE tb(ID INT ,col1 INT ,col2 INT ,col3 INT ,col4 INT ,col5 INT ,col6 INT ,col7 INT ,col8 INT ,col9 INT )
INSERT INTO tb
SELECT 1,1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL UNION
SELECT 2,NULL,NULL,NULL,NULL,NULL,NULL,3,NULL,NULL UNION
SELECT 3,1,2,NULL,NULL,NULL,NULL,NULL,NULL,NULL UNION
SELECT 4,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL 

DECLARE @cols NVARCHAR(max),@sql NVARCHAR(max)
SELECT @cols=ISNULL(@cols+',','')+'('''+c.name+ ''',['+c.name+'])' FROM sys.all_columns AS c WHERE OBJECT_NAME(c.object_id)='tb'
PRINT @cols
SET @sql='
SELECT ID,c.col_title,CASE WHEN c.col_value IS NULL THEN ''NULL NULL'' ELSE ''HAS VALUE'' END  AS COMMENT FROM dbo.tb
CROSS APPLY(VALUES'+@cols+') c(col_title,col_value)'
PRINT @sql
EXEC (@sql)
ID col_title COMMENT ----------- --------- --------- 1 col1 HAS VALUE 1 col2 NULL NULL 1 col3 NULL NULL 1 col4 NULL NULL 1 col5 NULL NULL 1 col6 NULL NULL 1 col7 NULL NULL 1 col8 NULL NULL 1 col9 NULL NULL 1 ID HAS VALUE 2 col1 NULL NULL 2 col2 NULL NULL 2 col3 NULL NULL 2 col4 NULL NULL 2 col5 NULL NULL 2 col6 NULL NULL 2 col7 HAS VALUE 2 col8 NULL NULL 2 col9 NULL NULL 2 ID HAS VALUE 3 col1 HAS VALUE 3 col2 HAS VALUE 3 col3 NULL NULL 3 col4 NULL NULL 3 col5 NULL NULL 3 col6 NULL NULL 3 col7 NULL NULL 3 col8 NULL NULL 3 col9 NULL NULL 3 ID HAS VALUE 4 col1 NULL NULL 4 col2 NULL NULL 4 col3 NULL NULL 4 col4 NULL NULL 4 col5 NULL NULL 4 col6 NULL NULL 4 col7 NULL NULL 4 col8 NULL NULL 4 col9 NULL NULL 4 ID HAS VALUE