ビュー列をNOTNULLにする方法


84

列をtrueまたはfalseのみにするビューを作成しようとしています。しかし、私が何をしても、SQL Server(2008)は、私のビット列がどういうわけかnullになる可能性があると信じているようです。

「ステータス」列が「製品」というテーブルがありますINT, NULL。ビューでは、Product.Status列が3に等しい場合はBIT列をtrueに設定し、それ以外の場合はビットフィールドをfalseに設定して、Productの各行の行を返します。

SQLの例

SELECT CAST( CASE ISNULL(Status, 0)  
               WHEN 3 THEN 1  
               ELSE 0  
             END AS bit) AS HasStatus  
FROM dbo.Product  

このクエリをビューとして保存し、オブジェクトエクスプローラーで列を見ると、列HasStatusはに設定されていBIT, NULLます。ただし、NULLであってはなりません。私はあることを、このコラムを強制するために使用できるいくつかの魔法のSQLのトリックがありますNOT NULL

CAST()周りを削除するCASEと、列は正しく設定されますがNOT NULL、列のタイプはに設定されますがINT、これは私が望むものではないことに注意してください。になりたいですBIT。:-)

回答:


150

クエリを少し再配置することで、目的を達成できます。秘訣は、ISNULLSQL Serverが結果の値が決してではないことを理解する前に、を外側に配置する必要があるということNULLです。

SELECT ISNULL(CAST(
    CASE Status
        WHEN 3 THEN 1  
        ELSE 0  
    END AS bit), 0) AS HasStatus  
FROM dbo.Product  

私が実際にこれが役立つと思う理由の1つは、ORMを使用していて、結果の値をnull許容型にマップしたくない場合です。アプリケーションが値がnullになる可能性がないことを認識している場合は、作業が簡単になります。そうすれば、null例外などを処理するためのコードを書く必要はありません。


@Gunder:心配ありません、実際には少し難解です。これは、テーブルに計算ビット列を作成し、結果をNULL可能にしたくない場合にも便利です。
RedFilter 2010

8
似たようなものが必要でしたが、COALESCE()うまくいかなかったので、実際使用する必要がありますISNULL()
EvilBob22 2013

@ EvilBob22 COALESCEとISNULLの両方がNULLを返す可能性があるため、これは奇妙なことです。ただのコンパイラの癖だと思います。
RedFilter 2013

1
これは、通常は推測されないときにEntityFrameworkにキーを推測させるために、10億倍になります。
エリック


3

参考までに、このメッセージに遭遇した人にとって、キャスト/変換の外側にISNULL()を追加すると、ビューのオプティマイザーが台無しになる可能性があります。

インデックスキーと同じ値を使用しているが、数値精度のタイプが異なる2つのテーブルがあり(悪い、私は知っています)、私たちのビューはそれらを結合して最終結果を生成していました。しかし、ミドルウェアコードは特定のデータ型を探していて、ビューには返された列の周りにCONVERT()がありました

OPと同様に、ビュー結果の列記述子でnull許容として定義されていることに気付き、2つのテーブルの主キー/外部キーだと思っていました。結果をnull許容として定義したいのはなぜですか?

私はこの投稿を見つけ、列の周りにISNULL()を投げて、出来上がりました-もうnull許容ではありません。

問題は、クエリがその列でフィルタリングされたときに、ビューのパフォーマンスがトイレをまっすぐ下がったことでした。

何らかの理由で、ビューの結果列の明示的なCONVERT()はオプティマイザーを台無しにしませんでしたが(精度が異なるため、とにかくそうする必要がありました)、冗長なISNULL()ラッパーを追加すると大きな問題が発生しました仕方。


CONVERT()例を挙げて、非ヌル可能性を保証/示す方法の解決策を示していただけますか?
またはマッパー2017年

1
こんにちはまたは-申し訳ありませんが、しばらくこれを見ていませんでした。これが例です。ビューにCONVERT(BIT、U.RETIRED)、0)AS Retiredがあり、たとえばバイトまたはint列をビット/ブール値に変換すると、null許容になります。ビュー内のその列をISNULL(CONVERT(BIT、U.RETIRED)、0)AS Retiredに置き換えることにより、その列をNULL不可にすることができます。U.RETIREDが開始時にnullでなかった場合、ビューの列以外は機能的に何も変更されません。警告:ISNULL()は、クエリの最適化とインデックスの選択を妨げる可能性があります。
user1664043 2017

-3

Selectステートメントで実行できるのは、データベースエンジンがクライアントとして送信するデータを制御することだけです。selectステートメントは、基になるテーブルの構造には影響しません。テーブル構造を変更するには、AlterTableステートメントを実行する必要があります。

  1. まず、テーブルのそのビットフィールドに現在nullがないことを確認します
  2. 次に、次のddlステートメントを実行します。 Alter Table dbo.Product Alter column status bit not null

otoh、あなたがしようとしているのがビューの出力を制御することだけであるなら、あなたがしていることは十分です。構文により、ビューの結果セットのHasStatus列の出力が実際にnullになることありません。それはなります常にDOは、オブジェクトエクスプローラが言っていることは心配しないでどちらかのビット値= 1またはビット値= 0になります...


6
テーブルの列を変更したくありません。列は整数列として定義されており、nullを許可します。これは私たちの仕様に適合します。しかし、nullにはできないビットフィールドを持つ列を返すビューが必要です。ORMで正しくマップされるように、nullにできないことを知っているだけでは不十分です。列はNOTNULLである必要があります。
ルネ・
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.