MySQL、NULLまたは空の文字列を挿入する方が良いですか?


230

さまざまな分野のウェブサイトにフォームがあります。一部のフィールドはオプションですが、一部は必須です。私のDBには、これらすべての値を保持するテーブルがあります。ユーザーがデータを入力しなかったDB列にNULL値または空の文字列を挿入することをお勧めしますか?

回答:


220

を使用NULLすると、「データを入力しない」と「空のデータを入力する」を区別できます。

さらにいくつかの違い:

  • A LENGTHNULLIS NULLLENGTH空の文字列のです0

  • NULLsは空の文字列の前にソートされます。

  • COUNT(message)空の文字列はカウントしますが、NULLs はカウントしません

  • バインドされた変数を使用して空の文字列を検索できますが、は検索できませんNULL。このクエリ:

    SELECT  *
    FROM    mytable 
    WHERE   mytext = ?

    クライアントから渡される値に関係なく、NULLin mytextに一致することはありません。NULLs を照合するには、他のクエリを使用する必要があります。

    SELECT  *
    FROM    mytable 
    WHERE   mytext IS NULL

3
どちらが速いと思いますか?0またはNULLまたは ""
Atul Dravid

8
InnoDBでは、NULLは占有するスペースが少なくなります
Timo Huovinen '25 / 07/25

37
これは大丈夫だと思いますが、質問の「ベストプラクティス」要素を完全に無視し、接線的に関連する事実(NULLの並べ替え順序と長さ?これらは問題ではありません)にのみ焦点を当てています。ほとんどのテキストデータ入力タイプで、「応答なし」と「空の応答」の間に違いがないため、これはより良い答えに値する素晴らしい質問だと思います。
Nick

6
UNIQUEフィールドが設定されている場合、NULLも適切に機能します。たとえば、運転免許証などの人物のDL番号を追加するフィールドがあり、男にはそれがない場合。一意のフィールドであるため、DL番号のない最初の人は追加されますが、一意の制約のエラーがスローされるため、次の人は追加されません。したがって、NULLの方が優れています。
Saifur Ra​​hman Mohsin 2016

1
@Quassnoiあ、ごめんなさい...運転免許証をユニークに設定するのはなぜ悪い習慣なのですか...?
cedbeu 2016年

44

あなたがあれば検討することの一つは、これまでのデータベースを切り替えることを計画し、ということであるOracleは空の文字列をサポートしていません。これらは自動的にNULLに変換され、などの句を使用してクエリすることはできませんWHERE somefield = ''


11
これはあなたのリンク上でも信じられないほど魚のように聞こえたので、試してみました。Nullフィールド、 ''に設定、オラクルはそれを無視します。長さを0ではなくnullとして報告します。それはまったく間違っています。これを回避する方法があるはずです。これを別の質問として投稿します。
スティーブB.

1
Steve B.::この質問を参照stackoverflow.com/questions/1171196/...
Quassnoi

理由はわかりませんが、参考にしてください。stackoverflow.com/questions/1268177/…
Steve B.

Quassnoiによって投稿されたリンクからの情報を含めるために回答を更新する価値があるかもしれません
SamuelKDavis

7
Peoplesoft(Oracle DBを使用)では、単一のスペースを使用して空の値を示します。信じられないほど愚か。また、0は許可されないため、0.00025を使用してFTEの0を示します。その製品には素敵な選択がなされました。
JPダッフィー

9

注意すべき点の1つは、NULLはコードパスをはるかに困難にする可能性があることです。たとえばPythonでは、ほとんどのデータベースアダプタ/ ORMはにマップさNULLNoneます。

したがって、次のようなもの:

print "Hello, %(title)s %(firstname) %(lastname)!" % databaserow

「Hello、None Joe Doe!」になるかもしれません これを回避するには、次のようなコードが必要です。

if databaserow.title:
    print "Hello, %(title)s %(firstname) %(lastname)!" % databaserow
else:
    print "Hello, %(firstname) %(lastname)!" % databaserow

これは物事をより複雑にすることができます。


25
私の意見では、コードまたはフレームワークのエラーを「修正」するためにデータベースを悪用することは、(非常に)悪いコーディング方法です。データがない場合は、NULLを挿入して、一貫して使用する必要があります。そうでない場合は、if(myString == null || myString = "")などのステートメントを使用する必要があります。オブジェクトがコードで設定または定義されていない場合、ある種の「プレースホルダー」(空の文字列は私の意見では)の代わりにNULLも使用しています。
Gertjan

5
選択した言語に大きく依存します。Pythonでは、「myStringでない場合:」はNoneと「」をテストします。おそらく主に文化的な問題です。Java Guysの「悪い習慣」は、ダイナミックな人の優雅さです。
最大

9

NULLMySQLのデータベースの整合性を保つために挿入するほうがよい。外部キーはNULL空の文字列として保存できますが、保存することはできません。

制約の空の文字列に関する問題が発生します。外部キー制約を満たすために、一意の空の文字列を持つ偽のレコードを挿入する必要がある場合があります。悪い習慣だと思います。

参照:外部キーをNULLや重複にすることはできますか?


過去に制約の問題が原因で問題が発生したため、この答えを「+1」しました。
HPWD 2018年

ただし、NULLを使用する場合は、空の文字列で終了しないようにしてください。多くのUIテクノロジで簡単に実行できます。
調整可能

5

ここでどのようなベストプラクティスになるかわかりませんが、nullを空の文字列とは異なるものにしたい場合や、ユーザーの入力が空の文字列の定義と一致しない限り、通常はnullを優先します。

あなたがあなたがそれらをどのように違うものにしたいかを定義する必要があると私が言っていることに注意してください。それらを異なるものにすることが理にかなっている場合とそうでない場合があります。そうでない場合は、1つを選んでそれを使用してください。私が言ったように、私はほとんどの場合NULLを支持する傾向があります。

ああ、そして列がnullの場合、選択がnull列に対するものでない限り、その列に基づいて選択する(SQL用語ではwhere句がある)実質的にすべてのクエリにレコードが表示される可能性が低いことを覚えておいてください。もちろん。


1
...そして、私が上の答えを見つけた今、あなたが気にするであろう通常の違いは、データがないか空のデータであると言っても安全だと思います。:-)
Platinum Azure

1

一意のインデックスで複数の列を使用していて、これらの列の少なくとも1つが必須(つまり、必須のフォームフィールド)である場合、インデックスの他の列をNULLに設定すると、行が重複する可能性があります。これは、一意の列ではNULL値が無視されるためです。この場合、重複する行を避けるために、一意のインデックスの他の列で空の文字列を使用します。

一意のインデックスの列:
(event_type_id、event_title、日付、場所、URL)

例1:
(1、 'BBQ'、 '2018-07-27'、null、null)
(1、 'BBQ'、 '2018-07-27'、null、null)//許可され、複製されます。

例2:
(1、 'BBQ'、 '2018-07-27'、 ''、 '')
(1、 'BBQ'、 '2018-07-27'、 ''、 '')//重複しているため許可されません。

ここにいくつかのコードがあります:

CREATE TABLE `test` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `event_id` int(11) DEFAULT NULL,
  `event_title` varchar(50) DEFAULT NULL,
  `date` date DEFAULT NULL,
  `location` varchar(50) DEFAULT NULL,
  `url` varchar(200) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `event_id` (`event_id`,`event_title`,`date`,`location`,`url`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

これを挿入して、複製された行が許可されることを確認します。

INSERT INTO `test` (`id`, `event_id`, `event_title`, `date`, `location`, 
`url`) VALUES (NULL, '1', 'BBQ', '2018-07-27', NULL, NULL);

INSERT INTO `test` (`id`, `event_id`, `event_title`, `date`, `location`, 
`url`) VALUES (NULL, '1', 'BBQ', '2018-07-27', NULL, NULL);

これを挿入して、許可されていないことを確認します。

INSERT INTO `test` (`id`, `event_id`, `event_title`, `date`, `location`, 
`url`) VALUES (NULL, '1', 'BBQ', '2018-07-28', '', '');

INSERT INTO `test` (`id`, `event_id`, `event_title`, `date`, `location`, 
`url`) VALUES (NULL, '1', 'BBQ', '2018-07-28', '', '');

ですから、ここに正誤はありません。ビジネスルールに最適なものを決定するのはあなた次第です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.