web-dev-qa-db-fra.com

Quand utiliser NULL et quand utiliser une chaîne vide?

Je m'intéresse principalement à MySQL et PostgreSQL, mais vous pourriez répondre aux questions suivantes en général:

  • Existe-t-il un scénario logique dans lequel il serait utile de distinguer une chaîne vide de NULL?
  • Quelles seraient les implications du stockage physique pour le stockage d'une chaîne vide en tant que ...

    • NUL?
    • Chaîne vide?
    • Un autre domaine?
    • De toute autre manière?
87
Maniero

Disons que l'enregistrement provient d'un formulaire pour recueillir des informations de nom et d'adresse. La ligne 2 de l'adresse sera généralement vide si l'utilisateur ne vit pas en appartement. Dans ce cas, une chaîne vide est parfaitement valide. J'ai tendance à préférer utiliser NULL pour signifier que la valeur est inconnue ou non donnée.

Je ne pense pas que la différence de stockage physique mérite d'être inquiétée dans la pratique. En tant qu'administrateurs de bases de données, nous avons beaucoup plus de poissons à faire frire!

67
Larry Coleman

Je ne connais pas MySQL et PostgreSQL, mais permettez-moi de traiter cela un peu généralement.

Il y a un SGBD à savoir Oracle qui ne permet pas de choisir ses utilisateurs entre NULL et ''. Cela démontre clairement qu'il n'est pas nécessaire de distinguer les deux. Il y a des conséquences gênantes:

Vous définissez un varchar2 sur une chaîne vide comme ceci:

Update mytable set varchar_col = '';

ce qui suit conduit au même résultat

Update mytable set varchar_col = NULL;

Mais pour sélectionner les colonnes où la valeur est vide ou NULL, vous devez utiliser

select * from mytable where varchar_col is NULL;

En utilisant

select * from mytable where varchar_col = '';

est syntaxiquement correcte, mais ne renvoie jamais une ligne.

De l'autre côté, lors de la concaténation de chaînes dans Oracle. Les varchars NULL sont traités comme des chaînes vides.

select NULL || 'abc' from DUAL;

donne abc. D'autres SGBD renverraient NULL dans ces cas.

Lorsque vous souhaitez exprimer explicitement qu'une valeur est affectée, vous devez utiliser quelque chose comme ''.

Et vous devez vous inquiéter si le rognage n'est pas vide en NULL

select case when ltrim(' ') is null then 'null' else 'not null' end from dual

Cela fait.

Regardons maintenant le SGBD où '' n'est pas identique à NULL (par exemple SQL-Server)

Travailler avec '' est généralement plus facile et dans la plupart des cas, il n'est pas nécessaire de distinguer les deux. L'une des exceptions que je connais, c'est lorsque votre colonne représente un paramètre et que vous n'avez pas de valeurs par défaut vides pour eux. Lorsque vous pouvez distinguer '' et NULL, vous pouvez exprimer que votre paramètre est vide et éviter que la valeur par défaut ne s'applique.

26
bernd_k

Cela dépend du domaine sur lequel vous travaillez. NULL signifie absence de valeur (c'est-à-dire qu'il n'y a aucune valeur ), tandis qu'une chaîne vide signifie qu'il y a un valeur de chaîne de longueur nulle.

Par exemple, supposons que vous disposiez d'une table pour stocker les données d'une personne et qu'elle contienne une colonne Gender. Vous pouvez enregistrer les valeurs sous "Homme" ou "Femme". Si l'utilisateur peut choisir de ne pas fournir les données de genre, vous devez l'enregistrer sous NULL (c'est-à-dire que l'utilisateur n'a pas fourni la valeur) et pas chaîne vide (car il n'y a pas genre avec valeur '').

17
Gan

Une chose à garder à l'esprit est que lorsque vous avez un champ qui n'est pas requis, mais que toutes les valeurs présentes doivent être uniques, vous devrez stocker les valeurs vides en tant que NULL. Sinon, vous ne pourrez avoir qu'un seul Tuple avec une valeur vide dans ce champ.

Il existe également des différences avec l'algèbre relationnelle et les valeurs NULL: NULL! = NULL, par exemple.

10
Matthew Schinckel

Vous pouvez également prendre en compte la critique de Date sur NULL et les problèmes de 3VL dans SQL et théorie relationnelle (et la critique de Rubinson sur la critique de Date, Nulls, Three-Valued Logic et Ambiguity in SQL: Critique de la critique de la date ).

Les deux sont référencés et discutés en détail dans un thread SO thread, Options pour éliminer les colonnes NULLable d'un modèle DB .

6
Abie

Une nouvelle pensée, une grande influence sur votre choix de NULL/NOT NULL est si vous utilisez un framework. J'utilise beaucoup symfony et l'utilisation de l'autorisation des champs NULL simplifie une partie du code et de la vérification des données lors de la manipulation des données.

Si vous n'utilisez pas de framework ou si vous utilisez de simples instructions et traitements sql, je choisirais le choix qui vous semble le plus simple à suivre. Je préfère généralement NULL pour que les instructions INSERT ne soient pas fastidieuses en oubliant de définir les champs vides sur NULL.

4
Patrick

Ayant dû travailler avec Oracle ( ce qui ne vous permet pas de différencier ) je suis arrivé à la conclusion suivante:

  • D'un POV logique, cela n'a pas d'importance. Je ne peux vraiment pas penser à un exemple convaincant où la différence entre NULL et la chaîne de longueur nulle ajoute une valeur dans le SGBD.

  • D'où: Vous avez soit une colonne NULLable qui ne permet pas zéro-len '' (Solution Oracle-ish) ou une colonne NOT NULL Qui permet zéro-len.

  • Et d'après mon expérience, '' Donne beaucoup plus de sens lors du traitement des données, car normalement vous souhaitez traiter l'absence d'un chaîne comme chaîne vide: concaténation, comparaison, etc.

Remarque: Pour revenir à mon expérience Oracle: Supposons que vous souhaitiez générer une requête pour une demande de recherche. Si vous utilisez '', Vous pouvez simplement générer WHERE columnX = <searchvalue> Et cela fonctionnera pour les recherches d'égalité. Si vous utilisez NULL, vous devez faire WHERE columnX=<searchvalue> or (columnX is NULL and serchvalue is NULL). Bah! :-)

2
Martin

Ils sont également différents du point de vue du design:

par exemple.

CREATE TABLE t (
    id INTEGER  NOT NULL,
    name CHARACTER(40),
    CONSTRAINT t_PK PRIMARY KEY (id)
);

CREATE UNIQUE INDEX t_AK1 ON t (name);

Ressemble à:

 \d t
          Table "public.t"
 Column |     Type      | Modifiers
--------+---------------+-----------
 id     | integer       | not null
 name   | character(40) |
Indexes:
    "t_pk" PRIMARY KEY, btree (id)
    "t_ak1" UNIQUE, btree (name)

Permet d'insérer quelques données:

op=# insert into t(id, name ) values ( 1, 'Hello');
INSERT 0 1

op=# insert into t( id, name) values ( 2, '');
INSERT 0 1

op=# insert into t( id, name) values ( 3, '');

ERROR:  duplicate key value violates unique constraint "t_ak1"

Essayons maintenant avec null:

op=# insert into t( id, name) values (4, null );

INSERT 0 1

op=# insert into t( id, name) values (5, null);

INSERT 0 1

C'est permis.

Soooooo: les nulls ne sont pas des chaînes triviales ni l'inverse.

À votre santé

2
Guy Birkbeck

Si nous parlons de théorie, les règles de Codd disent que le SGBDR doit traiter les valeurs de NULL d'une manière spéciale.

La manière exacte dont cela est utilisé dépend des architectes de bases de données, en fonction du domaine réel - tâche - projet - application - domaine.

1
noonex