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


82

Je m'intéresse principalement à MySQL et à PostgreSQL, mais vous pouvez 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 stocker une chaîne vide en tant que ...

    • NUL?
    • Chaîne vide?
    • Un autre domaine?
    • Une autre manière?

Réponses:


67

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. Une chaîne vide dans ce cas est parfaitement valide. J'ai tendance à préférer utiliser NULL pour signifier que la valeur est inconnue ou non donnée.

Je ne crois pas que la différence de stockage physique mérite de s’inquiéter dans la pratique. En tant qu'administrateur de base de données, nous avons des poissons beaucoup plus gros à faire frire!


2
+1 très peu de dba n'ont jamais à s'inquiéter des différences de vitesse / taille d'utilisation NULLou non
Patrick

28
D'accord ... J'essaie de réserver NULL pour 'inconnue' ... la chaîne vide est 'nous savons qu'elle devrait être vide'. C'est particulièrement utile lorsque vos données proviennent de sources multiples
Joe

6
En suspens - NULL n'est pas connu, une chaîne vide a été spécifiée.
ScottCher

@ Larry quel est l'impact sur les performances? Comment la performance varie-t-elle avec les tables de plusieurs colonnes par rapport aux tables de nombreuses lignes?
Shimmy

Je conviens que s'il existe une distinction entre aucune valeur donnée et une chaîne vide dans votre jeu de données, vous devez les utiliser correctement, mais personnellement, si je n'ai pas besoin de cette distinction avec mes données, j'utilise toujours une chaîne vide, uniquement parce que je trouver le résultat de la requête d'un client MySQL sur la ligne de commande peut être plus propre à regarder avec des chaînes vides au lieu de beaucoup de valeurs NULL
RTF

25

Je ne connais pas MySQL ni PostgreSQL, mais laissez-moi traiter cela un peu en général.

Il existe 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 faire la distinction entre les deux. Il y a des conséquences agaçantes:

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 correct, mais il ne retourne 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 . Les autres SGBD renverraient NULL dans ces cas.

Quand vous voulez exprimer explicitement qu'une valeur est assignée, vous devez utiliser quelque chose comme ''.

Et vous devez vous demander si le rognage n'est pas vide, cela donne NULL

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

Cela fait.

Regardons maintenant les 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 faire la distinction entre les deux. Une des exceptions que je connaisse est lorsque votre colonne représente un paramètre et que vous ne disposez pas de valeurs par défaut vides. Lorsque vous pouvez faire la distinction entre '' et NULL, vous pouvez indiquer que votre paramètre est vide et éviter que la valeur par défaut ne s'applique.



17

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

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


7
Si l'utilisateur a choisi de ne pas fournir de sexe, vous devez sûrement enregistrer "Refusé de fournir". NULL est ambigu; cela pourrait également signifier "le client n'a pas été interrogé", "le client s'identifie avec un sexe ne figurant pas sur notre liste", etc.
Jon of All Trades

9

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

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


4
Ce n'est en fait pas le cas que NULL! = NULL, car c'est NULL. ;-)
Peter Eisentraut le

1
Notez que MS SQL ne suit pas cette règle: plusieurs valeurs NULL violeront une UNIQUEcontrainte. Heureusement, à partir de 2008, vous pouvez utiliser un index filtré pour obtenir un comportement correct.
Jon of All Trades


4

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

Si vous n'utilisez pas de framework ou si vous utilisez des instructions SQL simples et leur traitement, j'opterais pour le choix le plus simple à suivre. Je préfère généralement NULL pour que les INSERTdéclarations ne soient pas fastidieuses en oubliant de définir les champs vides NULL.


la question concerne NULL vs chaîne vide (dans une colonne nullable, IMO), pas NULL vs NOT NULL, n'est-ce pas?
Gan

la partie de la question concernant le stockage m'a amené à penser qu'il pense peut-être aussi à Null / Not Null
Patrick

ou @ tout le monde concernant l'implication de NULL vs NOT NULL, vous pouvez vous référer à ceci: dba.stackexchange.com/q/63/107
Gan

2

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

  • D'un point de vue logique, cela n'a pas d'importance. Je ne peux vraiment pas penser à un exemple probant où la distinction entre NULL et chaîne zéro-longueur ajoute une valeur quelconque au SGBD.

  • A partir de ce qui suit: Vous avez soit une NULLcolonne capable qui n'autorise pas zéro-len ''(solution Oracle-ish), soit une NOT NULLcolonne qui autorise zéro-len.

  • Et de par mon expérience, ''cela a beaucoup plus de sens lors du traitement des données, car normalement vous voudriez traiter l'absence d'une chaîne en tant que chaîne vide: Concaténation, Comparaison, etc.

Remarque: Pour revenir à mon expérience Oracle: Disons que vous souhaitez générer une requête pour une requête 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 NULLvous devez faire WHERE columnX=<searchvalue> or (columnX is NULL and serchvalue is NULL). Bah! :-)


2

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

Ceci est permis.

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

À votre santé


1

Si nous parlons de théorie, les règles de Codd stipulent que le SGBDR doit traiter les NULLvaleurs d’une manière particulière.

Les architectes de base de données peuvent déterminer exactement comment utiliser cela, en fonction du domaine réel - domaine - tâche - projet - application -.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.