返回任何列中至少有一个值为null的所有行

时间:2016-03-09 19:12:13

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

我刚刚完成了使用数据加载新表的过程。我目前正在尝试验证数据。我设计数据库的方式确实不应该是NULL的任何值,所以我试图找到所有NULL值的行。

是否有一种快速简便的方法来执行此操作,而不是编写冗长的WHERE子句,并使用OR语句检查每列?

更新:更多细节...... NULL值最初有效,因为有时数据丢失。它只是帮助我找出我需要在其他地方寻找的数据。我的一些表有50多列,因此写出整个WHERE子句并不方便。

3 个答案:

答案 0 :(得分:4)

针对Information_Schema.Columnsdocumentation)编写一个查询,为您的if子句输出SQL。

这里有一些东西让你入门:

select 'OR ([' + TABLE_NAME + '].[' + TABLE_SCHEMA + '].[' + COLUMN_NAME + '] IS NULL)'
from mydatabase.Information_Schema.Columns
order by TABLE_NAME, ORDINAL_POSITION

答案 1 :(得分:1)

短版本答案,使用SET CONCAT_NULL_YIELDS_NULL ON并将整个事物作为字符串打包并检查是否为NULL(一次)。这样任何null都会传播,使整行比较为空。

这里是演示主体的愚蠢示例代码,如果您想将其包装在自动生成模式脚本中(仅检查Nullable列并执行所有适当的转换),由您决定。效率很高,但几乎任何削减方式都需要进行表格扫描。

CREATE TABLE dbo.Example
(
PK INT PRIMARY KEY CLUSTERED IDENTITY(1,1),
A nchar(10) NULL,
B int NULL,
C nvarchar(50) NULL
)  ON [PRIMARY]
GO

INSERT dbo.Example(A, B, C)
VALUES('Your Name', 1, 'Not blank'),
('My Name', 3, NULL),
('His Name', NULL, 'Not blank'),
(NULL, 5, 'It''s blank');

SET CONCAT_NULL_YIELDS_NULL ON 
SELECT E.PK 
FROM dbo.Example E
WHERE (E.A + CONVERT(VARCHAR(32), E.B) + E.C) IS NULL
SET CONCAT_NULL_YIELDS_NULL OFF

答案 2 :(得分:0)

正如评论中所提到的,如果你真的希望列不为null,那么就会对它们加上NOT NULL约束。那说......

这是一种略有不同的方法,使用INFORMATION_SCHEMA

DECLARE @sql NVARCHAR(max) = '';

SELECT @sql = @sql + 'UNION ALL SELECT ''' + cnull.TABLE_NAME + ''' as TableName, ''' 
                                           + cnull.COLUMN_NAME + ''' as NullColumnName, '''
                                           + pk.COLUMN_NAME + ''' as PkColumnName,' +
                                           + 'CAST(' + pk.COLUMN_NAME + ' AS VARCHAR(500)) as PkValue '
                                           + ' FROM ' + cnull.TABLE_SCHEMA + '.' + cnull.TABLE_NAME 
                                           + ' WHERE ' +cnull.COLUMN_NAME + ' IS NULL '
FROM INFORMATION_SCHEMA.COLUMNS cnull
INNER JOIN (SELECT Col.Column_Name, col.TABLE_NAME, col.TABLE_SCHEMA
                from INFORMATION_SCHEMA.TABLE_CONSTRAINTS Tab
                INNER JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE Col 
                ON  Col.Constraint_Name = Tab.Constraint_Name AND Col.Table_Name = Tab.Table_Name
                WHERE CONSTRAINT_TYPE = 'PRIMARY KEY') pk
ON pk.TABLE_NAME = cnull.TABLE_NAME AND cnull.TABLE_SCHEMA = pk.TABLE_SCHEMA
WHERE cnull.IS_NULLABLE = 'YES'

set @sql = SUBSTRING(@sql, 11, LEN(@sql)) -- remove the initial 'UNION ALL '

exec(@sql)

而是一个巨大的where子句,这将告诉您表中的主键,该表中的任何字段为null。请注意,如果您有一些CAST / int / varchar等,我uniqueidentifier所有主键值都可以避免操作数冲突。如果您有PK,不适合VARCHAR(500)您可能还有其他问题......

如果您有任何具有复合主键的表,这可能需要一些调整 - 因为它是,我很确定它只会为键的每个成员输出单独的行而不是连接它们,并且不一定按照你想要的方式将它们组合在一起。

另一个想法只是来自任何表SELECT *并将输出保存为格式(Excel,纯文本csv),您可以轻松搜索字符串NULL