Dlaczego kolumna tekstowa nie może mieć wartości domyślnej w MySQL?


184

Jeśli spróbujesz utworzyć kolumnę TEXT w tabeli i nadasz jej domyślną wartość w MySQL, pojawi się błąd (przynajmniej w systemie Windows). Nie widzę żadnego powodu, dla którego kolumna tekstowa nie powinna mieć wartości domyślnej. Dokumentacja MySQL nie zawiera wyjaśnień. Wydaje mi się to nielogiczne (i nieco frustrujące, ponieważ chcę wartości domyślnej!). Czy ktoś wie, dlaczego nie jest to dozwolone?


1
Czy możemy zobaczyć użyte zapytanie?
Robert,

2
Czy na pewno chcesz kolumnę TEXT, a nie VARCHAR? Kolumny TEKSTOWE dotyczą rzeczy, które mogą mieć długość przekraczającą 255 bajtów.
scy

5
To powinien być komentarz. TEXTMa też na myśli - te kolumny nie mogą mieć wartości domyślnej. VARCHARmogą.
Pekka

1
Jeśli używasz phpmyadmina do skonfigurowania bazy danych, może zajrzyj do mysql gui tools / workbench ...;)
dmp

1
Tak, niestety potrzebuję więcej niż 255 znaków.
Russ

Odpowiedzi:


92

Windows MySQL v5 zgłasza błąd, ale Linux i inne wersje zgłaszają tylko ostrzeżenie. To musi zostać naprawione. WTF?

Zobacz także próbę rozwiązania tego problemu jako błędu # 19498 w narzędziu Bugtracker MySQL:

Bryce Nesbitt 4 kwietnia 2008 16:36:
W MS Windows reguła „brak DOMYŚLNYCH” jest błędem, podczas gdy na innych platformach często jest to ostrzeżenie. Chociaż nie jest to błąd, można go złapać w pułapkę, jeśli napiszesz kod na łagodnej platformie, a później uruchomisz go na ścisłej platformie:

Osobiście uważam to za błąd. Wyszukiwanie „BLOB / TEKST kolumna nie może mieć wartości domyślnej” zwraca około 2940 wyników w Google. Większość z nich to raporty niezgodności podczas próby zainstalowania skryptów DB, które działały w jednym systemie, ale nie w innych.

Mam teraz ten sam problem w aplikacji internetowej, którą modyfikuję dla jednego z moich klientów, pierwotnie wdrożonej na Linux MySQL v5.0.83-log. Korzystam z systemu Windows MySQL 5.1.41. Nawet próbując użyć najnowszej wersji phpMyAdmin do wyodrębnienia bazy danych, nie zgłasza wartości domyślnej dla danej kolumny tekstowej. Jednak gdy próbuję uruchomić wstawkę w systemie Windows (która działa dobrze w przypadku wdrożenia w systemie Linux), pojawia się błąd braku wartości domyślnej w kolumnie ABC. Próbuję odtworzyć lokalnie tabelę z oczywistymi wartościami domyślnymi (w oparciu o wybór unikalnych wartości dla tej kolumny) i ostatecznie otrzymuję bardzo przydatną kolumnę BLOB / TEXT nie może mieć wartości domyślnej .

Ponownie, brak zachowania podstawowej kompatybilności na różnych platformach jest niedopuszczalny i jest błędem.


Jak wyłączyć tryb ścisły w MySQL 5 (Windows):

  • Edytuj /my.ini i poszukaj linii

    sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"
  • Zamień na

    sql_mode='MYSQL40'
  • Uruchom ponownie usługę MySQL (zakładając, że jest to mysql5)

    net stop mysql5
    net start mysql5

Jeśli masz uprawnienia roota / administratora, możesz być w stanie wykonać

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

3
Jeśli masz dostęp do konta root i używasz phpMyAdmin, przejdź do strony głównej (kliknij logo phpMyAdmin), przejdź do zakładki Zmienne, znajdź zmienną sql_mode i kliknij Edytuj.
Gavin

1
Jestem na CentOS 5.8 i MySQL v 14.14 Distrib 5.1.71 zgłasza błąd zamiast ostrzeżenia podczas próby ustawienia wartości domyślnej na pole TEXT. Chciałbym tylko zauważyć, że nie działa na każdej platformie Linux.
Alex

OS X przynajmniej wydaje się w dzisiejszych czasach generować błąd. Dokumenty dev.mysql.com/doc/refman/5.7/en/blob.html mówią „Kolumny BLOB i TEKST nie mogą mieć wartości DOMYŚLNYCH”. FWIW (ale nie dlaczego)
rogerdpack,

31

Bez dogłębnej znajomości silnika mySQL powiedziałbym, że brzmi to jak strategia oszczędzania pamięci. Zakładam, że powodem jest ten akapit z dokumentów :

Każda wartość BLOB lub TEXT jest reprezentowana wewnętrznie przez osobno przydzielony obiekt. Jest to w przeciwieństwie do wszystkich innych typów danych, dla których pamięć jest przydzielana jeden raz na kolumnę po otwarciu tabeli.

Wygląda na to, że wstępne wypełnienie tych typów kolumn doprowadziłoby do zużycia pamięci i pogorszenia wydajności.


5
-1: Przechowywanie danych, takich jak nazwy miast, w kolumnie TEKSTOWE zajmuje w rzeczywistości mniej pamięci całkowitej niż przechowywanie tych samych danych w kolumnie CHAR lub VARCHAR.
David Cary,

5
@david w podręczniku, który cytuję, nie dotyczy przechowywania, ale odzyskiwania.
Pekka

1
Nie rozumiem, w jaki sposób doprowadziłoby to do nieprawidłowego użycia pamięci i kar za wydajność. Oczywiście, gdy użytkownik zdefiniuje wartość domyślną, oczekuje poprawy wydajności bez względu na typ danych (szczególnie w przypadku operacji masowych). Jednak, o ile rozumiem, stwierdzasz, że w przypadku pola BLOB / TEXT ten wynik wydajności jest stosunkowo wysoki w porównaniu do innych typów danych? Jak to się wiąże z faktem, że BLOB / TEXT jest przechowywany wewnętrznie jako oddzielny obiekt? To nie ma dla mnie żadnego sensu.
dziwaczny

27
IMHO nie jest strategią oszczędzania pamięci. To albo błąd, albo ludzie, którzy go napisali, są szaleni. I myślę, że to ta ostatnia, ponieważ nie mogą tego naprawić od co najmniej 8 lat. Podstawowa funkcjonalność, którą ma każda inna baza danych.
dziwaczny

2
Nie ma znaczenia, nadal powinna być opcją dla osób, które chcą z niej skorzystać.
jurchiks

15

Możesz uzyskać taki sam efekt jak wartość domyślną, używając wyzwalacza

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

Jako główne pytanie:

Czy ktoś wie, dlaczego nie jest to dozwolone?

wciąż nie ma odpowiedzi, zrobiłem szybkie wyszukiwanie i znalazłem stosunkowo nowy dodatek od programisty MySQL w MySQL Bugs :

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

Wysłane przez programistę:

Jest to rzeczywiście prawidłowe żądanie funkcji i na pierwszy rzut oka może wydawać się trywialne. Ale wartości TEKST / BLOBY nie są przechowywane bezpośrednio w buforze rekordów używanym do odczytu / aktualizacji tabel. Dlatego przypisywanie im wartości domyślnych jest nieco bardziej skomplikowane.

To nie jest jednoznaczna odpowiedź, ale przynajmniej punkt wyjścia do pytania dlaczego .

W międzyczasie po prostu koduję wokół niego i albo nadam kolumnie wartość zerową, albo jawnie przypisam (domyślną '') wartość każdemu insertz kodu aplikacji ...


13

„Wsparcie dla DOMYŚLNYCH w kolumnach TEKST / BLOB” to żądanie funkcji w MySQL Bugtracker (Bug # 21532) .

Widzę, że nie jestem jedynym, który chciałby umieścić wartość domyślną w kolumnie TEKST. Myślę, że ta funkcja powinna być obsługiwana w późniejszej wersji MySQL.

Nie można tego naprawić w wersji 5.0 MySQL, ponieważ najwyraźniej spowodowałoby to niekompatybilność i utratę danych, gdyby ktoś próbował przenieść bazę danych tam iz powrotem między (obecnymi) bazami danych, które nie obsługują tej funkcji, a dowolnymi bazami danych, które obsługiwały ta funkcja.


Wydaje mi się, że powinieneś być w stanie zmienić go z „” na NULL dla kolumny TEXT, która pozwala na null. Nie wydaje się to możliwe.
phpguru

6

Zwykle prowadzę witryny w systemie Linux, ale rozwijam się również na lokalnym komputerze z systemem Windows. Natknąłem się na ten problem wiele razy i właśnie naprawiłem tabele, gdy napotkałem problemy. Wczoraj zainstalowałem aplikację, aby komuś pomóc, i oczywiście znów napotkałem problem. Zdecydowałem więc, że nadszedł czas, aby dowiedzieć się, co się dzieje - i znalazłem ten wątek. Naprawdę nie podoba mi się pomysł zmiany trybu sql_serwera na tryb wcześniejszy (domyślnie), więc wpadłem na proste (jak sądzę) rozwiązanie.

To rozwiązanie wymagałoby oczywiście od twórców zawinięcia skryptów tworzenia tabel, aby zrekompensować problem MySQL działający w systemie Windows. Podobne pojęcia zobaczysz w plikach zrzutu. Jednym DUŻYM zastrzeżeniem jest to, że może to powodować problemy, jeśli partycjonowanie jest używane.

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

O to chodzi.


1
To nie dotyczy pytania, dlaczego MySQL w ogóle zachowuje się, ale dziękuję za podzielenie się twoim podejściem, aby inni również mogli skorzystać. Witamy w Stack Overflow!
GargantuChet,

1
Tak, wiem ... Będę musiał spojrzeć dalej w tryb STRICT, aby sprawdzić, czy ma to sens - ponieważ MySQL wyświetla ostrzeżenie w polach Nix, ale nie działa w oknach Windows. Wskazuje to, że coś może być nie tak z implementacją niezależnie od platformy. Zauważysz, że w dokumentacji MySQL znajduje się ta informacja: „Kolumny BLOB i TEKST nie mogą mieć wartości DOMYŚLNYCH”. Logicznie więc wydaje się, że implementacja w wersjach wcześniejszych niż 5 została faktycznie zepsuta na wszystkich platformach.
Darrell Greenhouse

3

W przypadku Ubuntu 16.04:

Jak wyłączyć tryb ścisły w MySQL 5.7:

Edytuj plik /etc/mysql/mysql.conf.d/mysqld.cnf

Jeśli poniżej znajduje się wiersz w mysql.cnf

sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"

Następnie zamień na

sql_mode='MYSQL40'

Inaczej

Po prostu dodaj poniżej wiersza w mysqld.cnf

sql_mode='MYSQL40'

To rozwiązało problem.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.