2016-12-02 3 views
3

Я новичок в SQL, у меня возникли трудности с решением этой проблемы.Найти, если любые столбцы, содержащие нуль в SQL Server

Я хочу написать запрос выбора, который возвращает все те строки, которые имеют в нем нулевое значение.

У меня есть более 50 столбцов на столе и может быть добавлен дополнительный столбец, и из-за этого мне трудно писать, где это условие.

AFAIK мы можем использовать is null, но я не хочу повторять его для этих столбцов.

Пожалуйста, помогите мне решить проблему. Сообщите мне, нужна ли какая-либо дополнительная информация.

+2

вы * у * дать все столбцы в выражении WHERE , – GurV

+0

Вам нужно будет использовать динамический SQL для генерации предложения where автоматически. В противном случае вам не повезло - вам нужно указать его для всех столбцов, которые допускают null. Тем не менее, я не уверен, почему стол будет когда-либо понадобиться 50 столбцов и почему вам нужно будет проверить, является ли какой-либо из них нулевым; я предполагаю, что дизайн таблицы не является оптимальным в первую очередь. – ZLK

+1

Здесь дизайн вступает в игру. Откуда берутся нулевые значения? Почему неизвестно влияет на все 50 столбцов? Если вы не можете принудительно использовать NOT NULL в качестве ограничения столбца, как ваша таблица даже делает 1NF, не говоря уже о 2NF (нормализация). Это таблица фактов или измерений? Какие вопросы ответили на этот вопрос? –

ответ

3

Вы можете попробовать этот динамический 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; 
+0

И уничтожьте плохой оптимизатор, который, скорее всего, сделает что-то безумное с запросом. –

+0

@dreamer Добро пожаловать :) – Bharat

0

Помимо Whys и почему-был-дизайн так пренебрегали-до, теперь вопросы, нет целый ряд альтернатив.

К сожалению, если вы не можете гарантировать, что некоторые из этих 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 

Таким образом SQL Server можно лечить реляционные и ваш предикат чист. Оператор IIF просто сравнивает значения строк с проверкой на значение NULL (я бы проверил альтернативные способы объявления этого, чтобы узнать, как могут функционировать функции), что значительно менее сложно, чем пытаться использовать предикат в сложном 50! Логический кошмар.

Ключевое преимущество для встроенной функции является то, что они, вероятно, будет оптимизировано сонцем они были разработаны для решения рекурсивно с данными, в то время как ваш предикат для реляционных сравнений (SARGS)

0

Попробуйте это: заменить table_name с вашим таблица

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 [email protected]) 
OPEN C 
FETCH NEXT FROM C INTO @COLNAME 
WHILE @@FETCH_STATUS=0 
BEGIN 
SET @QUERY='SELECT COUNT(1) FROM '[email protected]+' WHERE '[email protected]+' 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 
3

простой способ (в том, что она не требует перечисления столбцов в явном виде) является

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. http://rextester.com/VTV64079

0

Вы хотите, чтобы весь указанный столбец был равен нулю?

;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 

возвратит идентификатор = 4

 
ID   col1  col2  col3  col4  col5  col6  col7  col8  col9 
----------- ----------- ----------- ----------- ----------- ----------- ----------- ----------- ----------- ----------- 
4   NULL  NULL  NULL  NULL  NULL  NULL  NULL  NULL  NULL 

Чтобы проверить, какой столбец NULL с динамическим satement:

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'[email protected]+') 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 
Смежные вопросы