Запрос на основе набора для поиска всех столбцов в таблице, которые содержат хотя бы одно нулевое значение - PullRequest
0 голосов
/ 17 ноября 2011

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

USE QC_TEST

DECLARE @colName nvarchar(100)
DECLARE @nullCols nvarchar(max)

SELECT @colName = c.name, @nullCols = COALESCE(@nullCols+', ','')+@colName
FROM sys.tables AS t
    JOIN sys.columns AS c
        ON t.object_id = c.object_id
WHERE t.name = 'myTable' 
AND 
EXISTS(SELECT * FROM myTable WHERE c.name IS NULL)

SELECT @colName, @nullCols

Приведенный выше код в настоящее время возвращает все столбцы в myTable. Если я изменю предложение EXISTS на NOT EXISTS, столбцы не будут возвращены. Результатом должна быть строка имен столбцов, разделенных запятыми, которые содержат как минимум 1 нулевое значение.

Спасибо за вашу помощь

Ответы [ 3 ]

2 голосов
/ 17 ноября 2011

Вы можете получить результат таким образом

declare @sql varchar(max), @t varchar(max);
set @t = 'your_table';
select @sql = (select stuff(
    (select 
            '] is null union select ''' + c.name + 
            ''' from ' + @t + ' where [' + c.name
        from
            (select
                    c.name
                from sys.tables AS t
                inner join sys.columns AS c
                    ON t.object_id = c.object_id
                where
                    t.name = @t
            ) as c
        for xml path('')
    ), 1, 16, '' ) + '] is null' )
;
exec(@sql);

Но я не знаю, что вы действительно считаете это лучше.

0 голосов
/ 17 ноября 2011

это немного нетрадиционно, но попробуйте это:

--set up test table
--the BEGIN TRY and ALTERs allow you to rerun entire script over and over again
BEGIN TRY
    CREATE TABLE YourTable (PK int not null primary key, RowValue1 int null, RowValue2 varchar(5) null, RowValue3 datetime)
END TRY
BEGIN CATCH END CATCH
delete YourTable
ALTER TABLE YourTable ALTER COLUMN RowValue1 int  NULL
ALTER TABLE YourTable ALTER COLUMN RowValue2 varchar(5)  NULL
ALTER TABLE YourTable ALTER COLUMN RowValue3 datetime  NULL

--setup test data
INSERT INTO YourTable VALUES  (1,1111,'AAAA',GETDATE())
INSERT INTO YourTable VALUES  (2,2222,'BBBB',GETDATE())
INSERT INTO YourTable VALUES  (3,3333,'CCCC',GETDATE())
INSERT INTO YourTable VALUES  (4,NULL,'DDDD',GETDATE())
INSERT INTO YourTable VALUES  (5,5555,'EEEE',NULL)

--determine null columns
DECLARE @BadColumns  varchar(50)

BEGIN TRY
    ALTER TABLE YourTable ALTER COLUMN RowValue1 int NOT NULL
END TRY
BEGIN CATCH
    SET @BadColumns=ISNULL(@BadColumns+', ','')+'RowValue1'
END CATCH    
----------------------------------
BEGIN TRY
    ALTER TABLE YourTable ALTER COLUMN RowValue2 varchar(5) NOT NULL
END TRY
BEGIN CATCH
    SET @BadColumns=ISNULL(@BadColumns+', ','')+'RowValue2'
END CATCH  
----------------------------------
BEGIN TRY
    ALTER TABLE YourTable ALTER COLUMN RowValue3 datetime NOT NULL
END TRY
BEGIN CATCH
    SET @BadColumns=ISNULL(@BadColumns+', ','')+'RowValue3'
END CATCH  

--report null columns
SELECT @BadColumns AS [Columns having NULLs]

ВЫВОД:

Columns having NULLs
--------------------------------------------------
RowValue1, RowValue3

(1 row(s) affected)

если вам нужно быть динамичным, потому что вы не знаете имен столбцов, вы можете встроить подобную команду в строку и затем выполнить ее.

0 голосов
/ 17 ноября 2011

Ваш код не работает, потому что подзапрос EXISTS просто проверяет имя вашего столбца, не равно NULL, чего не может быть. Подзапрос не раскрывает "WHERE c.name IS NULL" в "WHERE MyColumnName IS NULL", он просто видит, что c.name = 'MyColumnName' не является нулевым и всегда возвращает false.

Подход с использованием курсора, вероятно, работает путем построения отдельного строкового запроса для каждого столбца и последующего исключения строки.

Вы можете отменить поворот таблицы и искать пустые значения в этом наборе результатов, т.е.

WITH myTable_unpvt AS (
    SELECT ContactID, FieldName, FieldValue
    FROM 
       (SELECT ContactID
            , cast(Forename as sql_variant) Forename
            , cast(Surname as sql_variant) Surname
            , cast(Extn as sql_variant) Extn
            , cast(Email as sql_variant) Email
            , cast(Age as sql_variant) Age
       FROM myTable) p
    UNPIVOT
       (FieldValue FOR FieldName IN 
          (Forename, Surname, Extn, Email, Age)
    ) AS myTable_unpvt
)

SELECT DISTINCT FieldName FROM myTable_unpvt WHERE FieldValue IS NULL
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...