1. ホーム
  2. sql

欠損データを表現するためにNULLの代わりに'Z'を標準的に使用する?

2023-10-04 10:18:26

質問

NULL が使用されるべきかどうかという議論から外れて。私は既存のデータベースを担当していますが、NULL は「入力されなかった、または入力されなかったデータ」という意味で使用しています。 これは、「ユーザーがこの値を設定し、'empty' を選択した」という意味の空の文字列とは異なります。

プロジェクトの別の請負業者は、「NULL は私にとっては存在しない、私は決して NULL を使用しないし、他の誰も使用すべきではない」という側にしっかりと立っています。 しかし、私が混乱したのは、その請負業者のチームが、quot; missing/never entered" と " intentionally empty or indicated by the user as unknown, " の違いを認めているため、コードとストアド プロシージャ全体を通して 1 文字 'Z' を使用して、データベースの残りの部分で NULL と同じ意味を持つ " missing/never entered" を表していることです。

共有の顧客はこれを変更するように要求し、私はこの要求をサポートしましたが、チームはこれを私よりはるかに高度な DBA の間での "標準的な慣習" としており、私の無知な要求だけに基づいて NULL を使うように変更することを渋っています。 そこで、どなたか私の無知を克服する手助けをしていただけないでしょうか? NULLの代わりに'Z'を使用することを提唱する標準、または個人の小さなグループ、あるいはSQL専門家の間の単一の大きな声さえあるのでしょうか?

更新

業者からの回答がありましたので、追記します。 以下は、お客様から「データのない列のNULLを許可するために特殊な値を削除してほしい」という依頼を受けたときの内容です。

基本的に、私は可能な限り NULL を回避するようにデータベースを設計しました。 以下はその根拠です。

- 文字列 [VARCHAR] フィールドの NULL は、空の (長さゼロの) 文字列がまったく同じ情報を提供するため、決して必要ではありません。

- 整数フィールド (例: ID 値) の NULL は、データ中に決して発生しない値 (例: 整数 IDENTITY フィールドの -1) を使用することで処理することができます。

- 日付フィールドに NULL があると、日付の計算が簡単に複雑になります。 たとえば、[RecoveryDate] と [OnsetDate] の日数の差など、日付の差を計算するロジックでは、両方の日付が NULL であることを明示的に許容しない限り、一方または両方の日付が NULL であると、ロジックが吹き飛んでしまいます。 これは余分な作業と余分な処理です。 RecoveryDate]と[OnsetDate]にデフォルトまたはプレースホルダーの日付が使用されている場合(例えば、1/1/1900など)、数学的計算で異常な値が示されることがありますが、日付ロジックが吹き飛ぶことはありません。

NULL 処理は、伝統的に開発者がストアド プロシージャで間違いを犯す領域です。

DBA としての 15 年間で、私は可能な限り NULL を避けることが最善であることを発見しました。

これは、この質問に対するほとんどの否定的な反応を検証しているようです。 私はオープンマインドでこの質問を投稿し、quot;NULL は有用/NULL は悪の議論についてより多くを学んだことを嬉しく思っています。

空の (長さゼロの) 文字列は、まったく同じ情報を提供します。

いいえ、そうではありません。私たちが変更しようとしている既存のデータベースでは、NULL は "入力されなかったことを意味し、空の文字列は "空のまま入力されたことを意味します。

NULL の処理は、伝統的に開発者がストアド プロシージャで間違いを犯す領域でした。

しかし、そのような間違いは何千人もの開発者が何千回も犯しており、その間違いを避けるための教訓や注意点は知られていて文書化されています。 ここで言及されているように、NULL を受け入れるか拒否するかは別として、欠損値の表現方法は 解決済み問題 . 開発者が克服しやすい (そして特定しやすい) 間違いを犯し続けるからといって、新しい解決策を考案する必要はないのです。


脚注: 私は 20 年以上にわたって DBE および開発者をしてきました (これは、データベース エンジニアとデータベース管理者の違いを知るには十分な時間です)。 そのキャリアを通じて、私は常に「NULLは有用である」と考えてきました。しかし、非常に賢い人たちがそれに同意していないことは知っていました。 しかし、「正しいNULLの避け方」の学術的な知識には乏しく、確固たる立場をとることはできませんでした。 私は常に新しいことを学ぶのが好きで、20年経った今でも学ぶべきことがたくさんあります。 この議論を有益なものにするために貢献してくれたすべての人に感謝します。

どのように解決するのですか?

契約者をクビにする。

さて、真面目な話、これは標準的なやり方ではありません。 これは、私がこれまでに扱ったすべての RDBMS が NULL、NULL 用のロジック、外部キーの NULL を考慮する、COUNT の NULL に対して異なる動作をする、などといったことを実装しているからにほかなりません。

私は、'Z'または他のプレースホルダーを使用することは、実際にはより悪いと主張します。 あなたはまだ 'Z' をチェックするコードを必要とします。 しかし、'Z' が 'Z' を意味するのではなく、他のものを意味することを文書化する必要もあります。 そして、そのような文書が確実に読まれるようにしなければなりません。 そして、もし'Z'が有効なデータの一部になったらどうなるのでしょうか? (例えば、イニシャルのフィールドなど?)

基本的なレベルでは、NULL 対 'Z' の有効性を議論しなくても、私は請負業者が自分の会社ではなく、あなたの会社に存在する標準的な慣行に準拠するよう主張します。 代替の標準的な慣習がある環境で、彼の標準的な慣習を導入すると、混乱、メンテナンスのオーバーヘッド、誤解が生じ、最終的にはコストとミスが増加します。


編集

私の意見では、NULLの代替を使用することが有効である場合があります。 しかし、そうすることでコードが削減される場合のみで、むしろ説明する必要がある特別なケースを作成する場合です。

例えば、私は日付に縛られたデータに対してそれを使用しました。 データが開始日と終了日の間で有効である場合、NULL 値を持たないことでコードを簡略化することができます。 代わりに、NULLの開始日を'01 Jan 1900'に、NULLの終了日を'31 Dec 2079'に置き換えることができます。

これはまだ、期待されるものから動作を変えることができるので、注意して使用する必要があります。

  • WHERE end-date IS NULL 有効なデータを提供しない
  • あなたは今、自分自身のミレニアムバグを作成しました
  • など

これは、すべてのプロパティが常に有効な値を持つことができるように、抽象化を改めることと同じです。 任意に選択された値に暗黙的に特定の意味をエンコードすることとは明らかに異なります。

それでも、契約者をクビにしろ。