web-dev-qa-db-ja.com

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

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

222
roflwaffle

NULLを使用することにより、「データを入れない」と「空のデータを入れる」を区別できます。

さらにいくつかの違い:

  • LENGTHNULLNULLで、空の文字列のLENGTH0です。

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

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

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

    SELECT  *
    FROM    mytable 
    WHERE   mytext = ?
    

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

    SELECT  *
    FROM    mytable 
    WHERE   mytext IS NULL
    
216
Quassnoi

データベースの切り替えをever計画している場合、考慮すべきことの1つは、 Oracleは空の文字列をサポートしていない です。それらは自動的にNULLに変換され、WHERE somefield = ''などの句を使用してそれらを照会することはできません。

41
Matt Solnit

MySQLのデータベースの一貫性のためにNULLを挿入する方が適切です。外部キーはNULLとして保存できますが、空の文字列としては保存できません。

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

次も参照してください。 外部キーをNULLや複製にすることはできますか?

8
micaball

留意すべきことの1つは、NULLを使用するとコードパスがはるかに困難になる可能性があることです。たとえば、ほとんどのデータベースアダプタ/ ORMのPythonでは、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

これにより、事態はさらに複雑になります。

8
max

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

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

ああ、列がnullの場合、その列に基づいて選択する(SQL用語ではwhere句がある)クエリが実際に表示される可能性が低いことに注意してください。もちろん。

5
Platinum Azure

一意のインデックスで複数の列を使用しており、これらの列の少なくとも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', '', '');

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

0
João Marques