Warum kann eine Textspalte in MySQL keinen Standardwert haben?

184

Wenn Sie versuchen, eine TEXT-Spalte in einer Tabelle zu erstellen und in MySQL einen Standardwert anzugeben, wird eine Fehlermeldung angezeigt (zumindest unter Windows). Ich kann keinen Grund erkennen, warum eine Textspalte keinen Standardwert haben sollte. Die MySQL-Dokumentation enthält keine Erklärung. Es scheint mir unlogisch (und etwas frustrierend, da ich einen Standardwert haben möchte!). Weiß jemand warum das nicht erlaubt ist?

Russ
quelle
1
Können wir die von Ihnen verwendete Abfrage sehen?
Robert
2
Sind Sie sicher, dass Sie eine TEXT-Spalte und keine VARCHAR-Spalte möchten? TEXT-Spalten stehen für Dinge, die länger als 255 Byte werden können.
scy
5
Dies sollte ein Kommentar sein. Ja, er meint auch TEXT- diese Spalten können keinen Standardwert haben. VARCHARkönnen.
Pekka
1
Wenn Sie phpmyadmin verwenden, um Ihre Datenbank einzurichten, möchten Sie vielleicht die MySQL-GUI-Tools / Workbench untersuchen ...;)
dmp
1
Ja, ich brauche leider mehr als 255 Zeichen.
Russ

Antworten:

92

Windows MySQL v5 gibt einen Fehler aus, aber Linux und andere Versionen geben nur eine Warnung aus. Dies muss behoben werden. WTF?

Sehen Sie auch einen Versuch, dies als Fehler # 19498 im MySQL Bugtracker zu beheben:

Bryce Nesbitt am 4. April 2008, 16:36 Uhr:
Unter MS Windows ist die Regel "no DEFAULT" ein Fehler, während sie auf anderen Plattformen häufig eine Warnung darstellt. Obwohl dies kein Fehler ist, ist es möglich, dass Sie davon erfasst werden, wenn Sie Code auf einer milden Plattform schreiben und ihn später auf einer strengen Plattform ausführen:

Persönlich sehe ich das als Fehler an. Wenn Sie nach "BLOB / TEXT-Spalte kann keinen Standardwert haben" suchen, werden bei Google etwa 2.940 Ergebnisse zurückgegeben. Bei den meisten handelt es sich um Berichte über Inkompatibilitäten beim Versuch, DB-Skripts zu installieren, die auf einem System funktionieren, auf anderen jedoch nicht.

Ich habe jetzt das gleiche Problem mit einer Webanwendung, die ich für einen meiner Clients ändere und die ursprünglich unter Linux MySQL v5.0.83-log bereitgestellt wurde. Ich verwende Windows MySQL v5.1.41. Selbst wenn versucht wird, die neueste Version von phpMyAdmin zum Extrahieren der Datenbank zu verwenden, wird kein Standard für die betreffende Textspalte gemeldet. Wenn ich jedoch versuche, eine Einfügung unter Windows auszuführen (was bei der Linux-Bereitstellung problemlos funktioniert), wird in der ABC-Spalte der Fehler "Keine Standardeinstellung" angezeigt. Ich versuche, die Tabelle lokal mit dem offensichtlichen Standardwert neu zu erstellen (basierend auf einer Auswahl eindeutiger Werte für diese Spalte) und erhalte am Ende die ach so nützliche BLOB / TEXT-Spalte, die keinen Standardwert haben kann .

Auch hier ist es nicht akzeptabel, die grundlegende Kompatibilität zwischen Plattformen nicht aufrechtzuerhalten, und dies ist ein Fehler.


So deaktivieren Sie den strengen Modus in MySQL 5 (Windows):

  • Bearbeiten Sie /my.ini und suchen Sie nach einer Zeile

    sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"
  • Ersetzen Sie es durch

    sql_mode='MYSQL40'
  • Starten Sie den MySQL-Dienst neu (vorausgesetzt, es handelt sich um mysql5).

    net stop mysql5
    net start mysql5

Wenn Sie Root- / Administratorzugriff haben, können Sie möglicherweise ausführen

mysql_query("SET @@global.sql_mode='MYSQL40'");
Ku Logix
quelle
3
Wenn Sie Root-Zugriff haben und phpMyAdmin verwenden, rufen Sie die Hauptseite auf (klicken Sie auf das phpMyAdmin-Logo), wechseln Sie zur Registerkarte Variablen, suchen Sie die Variable sql_mode und klicken Sie auf Bearbeiten.
Gavin
1
Ich bin auf einem CentOS 5.8 und MySQL v 14.14 Distrib 5.1.71 gibt einen Fehler anstelle einer Warnung aus, wenn versucht wird, einen Standardwert für ein TEXT-Feld festzulegen. Ich möchte nur bemerken, dass es nicht auf jeder Linux-Plattform funktioniert.
Alex
OS X scheint heutzutage zumindest einen Fehler zu werfen. In den Dokumenten dev.mysql.com/doc/refman/5.7/en/blob.html heißt es: "BLOB- und TEXT-Spalten dürfen keine DEFAULT-Werte haben." FWIW (aber nicht warum)
Rogerdpack
31

Ohne tiefes Wissen über die mySQL-Engine würde ich sagen, dass dies nach einer Strategie zum Speichern von Speicher klingt. Ich gehe davon aus, dass der Grund für diesen Absatz aus den Dokumenten liegt :

Jeder BLOB- oder TEXT-Wert wird intern durch ein separat zugewiesenes Objekt dargestellt. Dies steht im Gegensatz zu allen anderen Datentypen, für die beim Öffnen der Tabelle einmal pro Spalte Speicher zugewiesen wird.

Es scheint, als würde das Vorfüllen dieser Spaltentypen zu Speichernutzung und Leistungseinbußen führen.

Pekka
quelle
5
-1: Das Speichern von Daten wie Städtenamen in einer TEXT-Spalte benötigt weniger Gesamtspeicher als das Speichern derselben Daten in einer CHAR- oder VARCHAR-Spalte.
David Cary
5
@david In dem von mir zitierten Handbuchkapitel geht es nicht um Speicherung, sondern um Abruf.
Pekka
1
Ich sehe nicht ein, wie dies zu einer abnormalen Speichernutzung und Leistungseinbußen führen würde. Wenn ein Benutzer einen Standardwert definiert, erwartet er offensichtlich einen Leistungseinbruch, unabhängig vom Datentyp (insbesondere bei Massenvorgängen). Soweit ich weiß, geben Sie jedoch an, dass dieser Leistungseinbruch für ein BLOB / TEXT-Feld im Vergleich zu anderen Datentypen relativ hoch ist? Und wie hängt das damit zusammen, dass BLOB / TEXT intern als getrenntes Objekt gespeichert wird? Das ergibt für mich keinen Sinn.
freakish
27
IMHO ist es keine Strategie zum Speichern von Speicher. Es ist entweder ein Fehler oder die Leute, die ihn geschrieben haben, sind verrückt. Und ich denke, es ist das letztere, da sie es seit mindestens 8 Jahren nicht mehr reparieren können. Die grundlegende Funktionalität, die jede andere Datenbank hat.
freakish
2
Egal, es sollte immer noch eine Option für Leute sein, die es benutzen wollen.
Jurchiks
15

Mit einem Trigger können Sie den gleichen Effekt wie mit einem Standardwert erzielen

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 ;
Tim Kind
quelle
14

Als Hauptfrage:

Weiß jemand warum das nicht erlaubt ist?

wird immer noch nicht beantwortet, ich habe eine schnelle Suche durchgeführt und einen relativ neuen Zusatz von einem MySQL-Entwickler bei MySQL Bugs gefunden :

[17. März 2017, 15:11 Uhr] Ståle Deraas

Gepostet von Entwickler:

Dies ist in der Tat eine gültige Funktionsanforderung, und auf den ersten Blick scheint es trivial zu sein, sie hinzuzufügen. TEXT / BLOBS-Werte werden jedoch nicht direkt im Datensatzpuffer gespeichert, der zum Lesen / Aktualisieren von Tabellen verwendet wird. Es ist daher etwas komplexer, ihnen Standardwerte zuzuweisen.

Dies ist keine eindeutige Antwort, aber zumindest ein Ausgangspunkt für die Warum- Frage.

In der Zwischenzeit werde ich nur darum herum codieren und entweder die Spalte auf Null setzen oder explizit einen (Standard- '') Wert für jede Spalte insertaus dem Anwendungscode zuweisen ...

Marten Koetsier
quelle
13

"Unterstützung für DEFAULT in TEXT / BLOB-Spalten" ist eine Funktionsanforderung im MySQL Bugtracker (Bug # 21532) .

Ich bin nicht der einzige, der einen Standardwert in eine TEXT-Spalte einfügen möchte. Ich denke, diese Funktion sollte in einer späteren Version von MySQL unterstützt werden.

Dies kann in der Version 5.0 von MySQL nicht behoben werden, da dies anscheinend zu Inkompatibilität und Datenverlust führen würde, wenn jemand versuchen würde, eine Datenbank zwischen den (aktuellen) Datenbanken, die diese Funktion nicht unterstützen, und den Datenbanken, die diese unterstützen, hin und her zu übertragen diese Funktion.

David Cary
quelle
Mir scheint, Sie sollten in der Lage sein, es für eine TEXT-Spalte, die null zulässt, zwischen "" und NULL zu ändern. Das scheint nicht möglich zu sein.
Phpguru
6

Normalerweise führe ich Sites unter Linux aus, entwickle aber auch auf einem lokalen Windows-Computer. Ich bin oft auf dieses Problem gestoßen und habe gerade die Tabellen repariert, als ich auf die Probleme gestoßen bin. Ich habe gestern eine App installiert, um jemandem zu helfen, und bin natürlich wieder auf das Problem gestoßen. Also entschied ich, dass es Zeit war herauszufinden, was los war - und fand diesen Thread. Die Idee, den sql_mode des Servers in einen früheren Modus (standardmäßig) zu ändern, gefällt mir wirklich nicht, deshalb habe ich eine einfache (ich denke) Lösung gefunden.

Diese Lösung würde natürlich erfordern, dass Entwickler ihre Tabellenerstellungsskripte umschließen, um das unter Windows ausgeführte MySQL-Problem zu kompensieren. Sie werden ähnliche Konzepte in Dump-Dateien sehen. Eine große Einschränkung ist, dass dies Probleme verursachen kann / wird, wenn Partitionierung verwendet wird.

// 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');

Das ist alles.

Darrell Gewächshaus
quelle
1
Hier geht es nicht um die Frage, warum MySQL überhaupt das Verhalten hat, aber danke, dass Sie Ihren Ansatz geteilt haben, damit auch andere davon profitieren können. Willkommen bei Stack Overflow!
GargantuChet
1
Ja, ich weiß ... Ich muss weiter in den STRICT-Modus schauen, um zu sehen, ob es sinnvoll ist - da MySQL eine Warnung auf Nix-Boxen ausgibt, aber auf Windows-Boxen fehlschlägt. Dies ist ein Hinweis darauf, dass unabhängig von der Plattform möglicherweise Probleme mit der Implementierung auftreten. Sie werden feststellen, dass in der MySQL-Dokumentation der folgende Hinweis enthalten ist: "BLOB- und TEXT-Spalten dürfen keine DEFAULT-Werte haben." Logischerweise scheint die Implementierung in Versionen vor 5 tatsächlich auf allen Plattformen fehlerhaft zu sein.
Darrell Greenhouse
3

Für Ubuntu 16.04:

So deaktivieren Sie den strengen Modus in MySQL 5.7:

Bearbeiten Sie die Datei /etc/mysql/mysql.conf.d/mysqld.cnf

Wenn die folgende Zeile in mysql.cnf vorhanden ist

sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"

Dann ersetzen Sie es durch

sql_mode='MYSQL40'

Andernfalls

Fügen Sie einfach die folgende Zeile in mysqld.cnf hinzu

sql_mode='MYSQL40'

Dieses Problem wurde behoben.

Shiv Buyya
quelle