Pourquoi une colonne de texte ne peut-elle pas avoir une valeur par défaut dans MySQL?


185

Si vous essayez de créer une colonne TEXT sur une table et que vous lui donnez une valeur par défaut dans MySQL, vous obtenez une erreur (sous Windows au moins). Je ne vois aucune raison pour laquelle une colonne de texte ne devrait pas avoir de valeur par défaut. Aucune explication n'est donnée par la documentation MySQL. Cela me semble illogique (et quelque peu frustrant, car je veux une valeur par défaut!). Quelqu'un sait pourquoi cela n'est pas autorisé?


1
Pouvons-nous voir la requête que vous avez utilisée?
Robert

2
Êtes-vous sûr de vouloir une colonne TEXT, pas une colonne VARCHAR? Les colonnes TEXT sont destinées aux objets qui peuvent atteindre plus de 255 octets.
scy

5
Cela devrait être un commentaire. En outre, oui, il veut dire TEXT- ces colonnes ne peuvent pas avoir de valeur par défaut. VARCHARpouvez.
Pekka

1
Si vous utilisez phpmyadmin pour configurer votre base de données, vous voudrez peut-être enquêter sur les outils / workbench de mysql gui ...;)
dmp

1
Oui, j'ai besoin de plus de 255 caractères malheureusement.
Russ

Réponses:


92

Windows MySQL v5 génère une erreur, mais Linux et les autres versions ne déclenchent qu'un avertissement. Cela doit être corrigé. WTF?

Voir également une tentative pour résoudre ce problème en tant que bogue # 19498 dans MySQL Bugtracker:

Bryce Nesbitt le 4 avril 2008 16h36:
Sous MS Windows, la règle "no DEFAULT" est une erreur, alors que sur d'autres plates-formes, c'est souvent un avertissement. Bien que ce ne soit pas un bogue, il est possible d'être piégé par cela si vous écrivez du code sur une plate-forme clémente, puis l'exécutez sur une plate-forme stricte:

Personnellement, je considère cela comme un bug. La recherche de "La colonne BLOB / TEXT ne peut pas avoir de valeur par défaut" renvoie environ 2 940 résultats sur Google. La plupart d'entre eux sont des rapports d'incompatibilités lors de la tentative d'installation de scripts DB fonctionnant sur un système mais pas sur d'autres.

Je rencontre le même problème maintenant sur une application Web que je modifie pour l'un de mes clients, initialement déployée sur Linux MySQL v5.0.83-log. J'utilise Windows MySQL v5.1.41. Même en essayant d'utiliser la dernière version de phpMyAdmin pour extraire la base de données, il ne signale pas de valeur par défaut pour la colonne de texte en question. Pourtant, lorsque j'essaie d'exécuter une insertion sur Windows (cela fonctionne bien sur le déploiement Linux), je reçois une erreur sans défaut sur la colonne ABC. J'essaie de recréer la table localement avec la valeur par défaut évidente (basée sur une sélection de valeurs uniques pour cette colonne) et finis par recevoir la colonne BLOB / TEXT si utile ne peut pas avoir de valeur par défaut .

Encore une fois, ne pas maintenir la compatibilité de base entre les plates-formes est inacceptable et constitue un bogue.


Comment désactiver le mode strict dans MySQL 5 (Windows):

  • Modifiez /my.ini et recherchez la ligne

    sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"
  • Remplacez-le par

    sql_mode='MYSQL40'
  • Redémarrez le service MySQL (en supposant qu'il s'agit de mysql5)

    net stop mysql5
    net start mysql5

Si vous avez un accès root / admin, vous pourrez peut-être exécuter

mysql_query("SET @@global.sql_mode='MYSQL40'");

3
Si vous avez un accès root et que vous utilisez phpMyAdmin, allez à la page principale (cliquez sur le logo phpMyAdmin), allez dans l'onglet Variables, recherchez la variable sql_mode et cliquez sur Modifier.
Gavin

1
Je suis sur un CentOS 5.8 et MySQL v 14.14 Distrib 5.1.71 jette une erreur au lieu d'un avertissement lorsque vous essayez de définir une valeur par défaut dans un champ TEXT. Je voudrais juste remarquer que cela ne fonctionne pas sur toutes les plates-formes Linux.
Alex

OS X au moins semble générer une erreur ces jours-ci. La documentation dev.mysql.com/doc/refman/5.7/en/blob.html indique "Les colonnes BLOB et TEXT ne peuvent pas avoir de valeurs DEFAULT." FWIW (mais pas pourquoi)
rogerdpack

31

Sans aucune connaissance approfondie du moteur mySQL, je dirais que cela ressemble à une stratégie d'économie de mémoire. Je suppose que la raison est derrière ce paragraphe de la documentation :

Chaque valeur BLOB ou TEXT est représentée en interne par un objet alloué séparément. Cela diffère de tous les autres types de données, pour lesquels le stockage est alloué une fois par colonne lorsque la table est ouverte.

Il semble que le préremplissage de ces types de colonnes entraînerait une utilisation de la mémoire et des pénalités de performances.


5
-1: le stockage de données, telles que les noms de villes, dans une colonne TEXT prend en fait moins de mémoire totale que le stockage des mêmes données dans une colonne CHAR ou VARCHAR.
David Cary

5
@david le chapitre du manuel que je cite ne concerne pas le stockage, mais la récupération.
Pekka

1
Je ne vois pas comment cela entraînerait une utilisation anormale de la mémoire et des pénalités de performances. De toute évidence, lorsqu'un utilisateur définit une valeur par défaut, il s'attend à une amélioration des performances quel que soit le type de données (en particulier sur les opérations en bloc). Cependant, pour autant que je sache, vous dites que pour un champ BLOB / TEXT, cette performance est relativement élevée par rapport aux autres types de données? Et comment cela est-il lié au fait que BLOB / TEXT est stocké en interne en tant qu'objet séparé? Cela n'a aucun sens pour moi.
freakish

27
IMHO ce n'est pas une stratégie d'économie de mémoire. C'est soit un bug, soit les gens qui l'ont écrit sont fous. Et je pense que c'est le dernier car ils ne peuvent pas le réparer depuis au moins 8 ans maintenant. La fonctionnalité de base de toutes les autres bases de données.
freakish

2
Peu importe, cela devrait toujours être une option pour les personnes qui souhaitent l'utiliser.
jurchiks

15

Vous pouvez obtenir le même effet qu'une valeur par défaut en utilisant un déclencheur

create table my_text

(
   abc text
);

delimiter //
create trigger mytext_trigger before insert on my_text
for each row
begin
   if (NEW.abc is null ) then
      set NEW.abc = 'default text';
   end if;
end
//
delimiter ;

14

Comme question principale:

Quelqu'un sait pourquoi cela n'est pas autorisé?

n'a toujours pas de réponse, j'ai fait une recherche rapide et j'ai trouvé un ajout relativement nouveau d'un développeur MySQL chez MySQL Bugs :

[17 mars 2017 15:11] Ståle Deraas

Publié par le développeur:

Il s'agit en effet d'une demande de fonctionnalité valide, et à première vue, cela peut sembler trivial à ajouter. Mais les valeurs TEXT / BLOBS ne sont pas stockées directement dans le tampon d'enregistrement utilisé pour lire / mettre à jour les tables. Il est donc un peu plus complexe de leur attribuer des valeurs par défaut.

Ce n'est pas une réponse définitive, mais au moins un point de départ pour la question du pourquoi .

En attendant, je vais juste coder autour de lui et rendre la colonne Nullable ou attribuer explicitement une valeur (par défaut '') pour chacun à insertpartir du code de l'application ...


13

"Prise en charge de DEFAULT dans les colonnes TEXT / BLOB" est une demande de fonctionnalité dans MySQL Bugtracker (bogue # 21532) .

Je vois que je ne suis pas le seul à souhaiter mettre une valeur par défaut dans une colonne TEXT. Je pense que cette fonctionnalité devrait être prise en charge dans une version ultérieure de MySQL.

Cela ne peut pas être corrigé dans la version 5.0 de MySQL, car apparemment, cela entraînerait une incompatibilité et une perte de données si quelqu'un essayait de transférer une base de données dans les deux sens entre les bases de données (actuelles) qui ne prennent pas en charge cette fonctionnalité et toutes les bases de données prenant en charge cette fonctionnalité.


Il me semble que vous devriez pouvoir le changer entre "" et NULL pour une colonne TEXT qui autorise null. Cela ne semble pas possible.
phpguru

6

J'exécute normalement des sites sous Linux, mais je développe également sur une machine Windows locale. J'ai rencontré ce problème plusieurs fois et je viens de réparer les tables lorsque j'ai rencontré les problèmes. J'ai installé une application hier pour aider quelqu'un et, bien sûr, j'ai de nouveau rencontré le problème. J'ai donc décidé qu'il était temps de comprendre ce qui se passait - et j'ai trouvé ce fil. Je n'aime vraiment pas l'idée de changer le sql_mode du serveur vers un mode antérieur (par défaut), alors j'ai proposé une solution simple (je pense).

Cette solution obligerait bien sûr les développeurs à encapsuler leurs scripts de création de table pour compenser le problème MySQL sous Windows. Vous verrez des concepts similaires dans les fichiers de vidage. Une GRANDE mise en garde est que cela pourrait / causera des problèmes si le partitionnement est utilisé.

// Store the current sql_mode
mysql_query("set @orig_mode = @@global.sql_mode");

// Set sql_mode to one that won't trigger errors...
mysql_query('set @@global.sql_mode = "MYSQL40"');

/**
 * Do table creations here...
 */

// Change it back to original sql_mode
mysql_query('set @@global.sql_mode = @orig_mode');

C'est à peu près ça.


1
Cela ne répond pas du tout à la question de savoir pourquoi MySQL a ce comportement, mais merci de partager votre approche afin que d'autres puissent également en bénéficier. Bienvenue dans Stack Overflow!
GargantuChet

1
Oui, je sais ... Je vais devoir examiner plus en détail le mode STRICT pour voir si cela a du sens - puisque MySQL jette un avertissement sur les boîtes de Nix, mais échoue sur les boîtes Windows. C'est une indication que quelque chose ne va pas avec la mise en œuvre, quelle que soit la plate-forme. Vous remarquerez que dans la documentation de MySQL, il y a cet avis: "Les colonnes BLOB et TEXT ne peuvent pas avoir de valeurs DEFAULT." Donc, logiquement, il semble que l'implémentation dans les versions antérieures à 5 était en fait cassée sur toutes les plateformes.
Darrell Greenhouse

3

Pour Ubuntu 16.04:

Comment désactiver le mode strict dans MySQL 5.7:

Modifier le fichier /etc/mysql/mysql.conf.d/mysqld.cnf

Si la ligne ci-dessous existe dans mysql.cnf

sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"

Puis remplacez-le par

sql_mode='MYSQL40'

Autrement

Ajoutez simplement la ligne ci-dessous dans mysqld.cnf

sql_mode='MYSQL40'

Ce problème résolu.

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.