2016-12-02 9 views
3

SQLの新機能です。この問題を解決するにはいくつかの問題があります。SQL Serverにnullを含む列があるかどうかを確認します。

null値を持つすべての行を返すselectクエリを作成します。

私はテーブルに50個以上のカラムを持っています。それに何か余分なカラムを追加することができます。そのため、どこに条件を書くのが難しくなります。

AFAIK私たちはis nullを使用することができますが、その多くの列については繰り返しません。

私はそれを解決するのを手伝ってください。追加情報が必要な場合はお知らせください。

+2

あなたは* where句のすべての列を与えることを*しています。 – GurV

+0

動的SQLを使用してwhere句を自動的に生成する必要があります。それ以外の場合は、不運になります。ヌルを許可するすべての列に対して指定する必要があります。つまり、なぜテーブルに50列が必要なのかわかりませんし、なぜそれらがnullであるかどうかを確認する必要があるのはなぜですか。私の推測では、テーブルのデザインは最初は最適ではないということです。 – ZLK

+1

これはデザインが活躍する場所です。ヌル値はどこから来ますか?未知数が50列すべてに影響するのはなぜですか?列制約としてNOT NULLを適用できなかった場合、2NF(正規化)はもちろんのこと、テーブルはどのようにして1NFを作成しますか?ファクト表またはディメンション表ですか?この質問からどのような質問に答えましたか? –

答えて

3

この動的SQLクエリを試すことができます。この問合せは、NULL値を含む列があればrowを戻します。

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

なぜ、なぜデザインがそんなに無視されていたのかという質問以外に、いくつかの選択肢があります。

悲しいことに、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の文は、1行の値とNULLの値のチェックとを比較するだけです(複雑な方法を知るためにこれを宣言する別の方法をテストします)。論理的な悪夢。

インライン関数への重要な利点は、彼らはあなたの述語は、リレーショナル比較(探索引数)のためであるのに対し、彼らは、データを走り書き対処するために設計されたsonceを最適化する可能性が高いということです

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

指定する列がすべてnullであることを確認しますか?

;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 

戻ります列がダイナミックsatementとNULLである= 4

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

を確認するにはID:

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 
関連する問題