Perché una colonna di testo non può avere un valore predefinito in MySQL?


185

Se si tenta di creare una colonna TEXT su una tabella e si assegna un valore predefinito in MySQL, viene visualizzato un errore (almeno su Windows). Non riesco a vedere alcun motivo per cui una colonna di testo non dovrebbe avere un valore predefinito. Nessuna spiegazione è fornita dalla documentazione di MySQL. Mi sembra illogico (e alquanto frustrante, poiché voglio un valore predefinito!). Qualcuno sa perché questo non è permesso?


1
Possiamo vedere la query che hai usato?
Robert,

2
Sei sicuro di voler una colonna TEXT, non una VARCHAR? Le colonne TEXT sono per cose che possono avere una lunghezza superiore a 255 byte.
scy

5
Questo dovrebbe essere un commento. Inoltre, sì, significa che TEXTquelle colonne non possono avere un valore predefinito. VARCHARpuò.
Pekka,

1
Se stai usando phpmyadmin per configurare il tuo database, potresti voler indagare su mysql gui tools / workbench ...;)
dmp

1
Sì, purtroppo ho bisogno di più di 255 caratteri.
Russ,

Risposte:


92

Windows MySQL v5 genera un errore ma Linux e altre versioni generano solo un avviso. Questo deve essere risolto. WTF?

Vedi anche un tentativo di risolvere questo problema come bug # 19498 in MySQL Bugtracker:

Bryce Nesbitt il 4 aprile 2008 16:36:
su MS Windows la regola "no DEFAULT" è un errore, mentre su altre piattaforme è spesso un avvertimento. Pur non essendo un bug, è possibile rimanere intrappolati da questo se si scrive codice su una piattaforma indulgente e successivamente lo si esegue su una piattaforma rigida:

Personalmente, lo vedo come un bug. La ricerca di "La colonna BLOB / TESTO non può avere un valore predefinito" restituisce circa 2.940 risultati su Google. Molti di questi sono rapporti di incompatibilità quando si tenta di installare script DB che funzionavano su un sistema ma non su altri.

Sto riscontrando lo stesso problema ora su una webapp che sto modificando per uno dei miei client, originariamente distribuito su Linux MySQL v5.0.83-log. Sto eseguendo Windows MySQL v5.1.41. Anche cercando di utilizzare l'ultima versione di phpMyAdmin per estrarre il database, non riporta un valore predefinito per la colonna di testo in questione. Tuttavia, quando provo a eseguire un inserto su Windows (che funziona bene sulla distribuzione Linux) ricevo un errore di default sulla colonna ABC. Provo a ricreare la tabella localmente con il valore predefinito ovvio (basato su una selezione di valori univoci per quella colonna) e alla fine ricevendo la colonna BLOB / TEXT oh-così utile non può avere un valore predefinito .

Ancora una volta, non mantenere la compatibilità di base tra le piattaforme è inaccettabile ed è un bug.


Come disabilitare la modalità rigorosa in MySQL 5 (Windows):

  • Modifica /my.ini e cerca la riga

    sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"
  • Sostituiscilo con

    sql_mode='MYSQL40'
  • Riavvia il servizio MySQL (supponendo che sia mysql5)

    net stop mysql5
    net start mysql5

Se hai accesso root / admin potresti essere in grado di eseguire

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

3
Se hai accesso root e stai usando phpMyAdmin, vai alla pagina principale (fai clic sul logo phpMyAdmin), vai alla scheda Variabili, trova la variabile sql_mode e fai clic su Modifica.
Gavin,

1
Sono su CentOS 5.8 e MySQL v 14.14 Distrib 5.1.71 genera un errore invece di un avviso quando si tenta di impostare un valore predefinito su un campo TEXT. Vorrei solo notare che non funziona su tutte le piattaforme Linux.
Alex

Al giorno d'oggi OS X sembra lanciare un errore. I documenti dev.mysql.com/doc/refman/5.7/en/blob.html dicono "Le colonne BLOB e TEXT non possono avere valori DEFAULT." FWIW (ma non perché)
rogerdpack,

31

Senza una profonda conoscenza del motore mySQL, direi che suona come una strategia di risparmio di memoria. Suppongo che la ragione sia dietro questo paragrafo dai documenti :

Ogni valore BLOB o TEXT è rappresentato internamente da un oggetto allocato separatamente. Ciò è in contrasto con tutti gli altri tipi di dati, per i quali l'archiviazione viene allocata una volta per colonna all'apertura della tabella.

Sembra che il pre-riempimento di questi tipi di colonne porterebbe all'utilizzo della memoria e alle penalizzazioni delle prestazioni.


5
-1: l'archiviazione di dati, come i nomi di città, in una colonna TEXT occupa effettivamente meno memoria totale rispetto alla memorizzazione degli stessi dati in una colonna CHAR o VARCHAR.
David Cary,

5
@david il capitolo del manuale che sto citando non riguarda l'archiviazione, ma il recupero.
Pekka,

1
Non vedo come ciò comporterebbe un uso anomalo della memoria e penali delle prestazioni. Ovviamente quando un utente definisce un valore predefinito, si aspetta un calo delle prestazioni, indipendentemente dal tipo di dati (specialmente nelle operazioni in blocco). Tuttavia, per quanto ho capito, affermi che per un campo BLOB / TEXT questo successo è relativamente elevato rispetto ad altri tipi di dati? E in che modo ciò è legato al fatto che BLOB / TEXT è memorizzato internamente come oggetto separato? Questo non ha alcun senso per me.
strano

27
IMHO non è una strategia di risparmio di memoria. È un bug o le persone che lo hanno scritto sono pazze. E penso che sia quest'ultimo poiché non possono ripararlo da almeno 8 anni. Le funzionalità di base di ogni altro database.
strano

2
Non importa, dovrebbe comunque essere un'opzione per le persone che vogliono usarlo.
Jurchiks,

15

È possibile ottenere lo stesso effetto di un valore predefinito utilizzando un trigger

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

Come la domanda principale:

Qualcuno sa perché questo non è permesso?

non ha ancora ricevuto risposta, ho fatto una ricerca veloce e ho trovato un'aggiunta relativamente nuova da uno sviluppatore MySQL a MySQL Bugs :

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

Postato dallo sviluppatore:

Questa è davvero una richiesta di funzionalità valida, e a prima vista potrebbe sembrare banale aggiungere. Ma i valori TEXT / BLOBS non vengono memorizzati direttamente nel buffer dei record utilizzato per leggere / aggiornare le tabelle. Quindi è un po 'più complesso assegnare valori predefiniti per loro.

Questa non è una risposta definitiva, ma almeno un punto di partenza per la domanda sul perché .

Nel frattempo, mi limiterò a codificarlo e renderò nulla la colonna o assegnerò esplicitamente un valore (predefinito '') per ciascuno insertdal codice dell'applicazione ...


13

"Supporto per DEFAULT nelle colonne TEXT / BLOB" è una richiesta di funzionalità nel Bugtracker di MySQL (Bug # 21532) .

Vedo che non sono l'unico a cui piacerebbe inserire un valore predefinito in una colonna TEXT. Penso che questa funzione dovrebbe essere supportata in una versione successiva di MySQL.

Questo non può essere risolto nella versione 5.0 di MySQL, perché apparentemente causerebbe incompatibilità e perdita di dati se qualcuno provasse a trasferire un database avanti e indietro tra i database (attuali) che non supportano quella funzionalità e tutti i database che supportano quella caratteristica.


Mi sembra che dovresti essere in grado di cambiarlo tra "" e NULL per una colonna TEXT che consente null. Non sembra possibile farlo.
phpguru,

6

Normalmente gestisco siti su Linux, ma sviluppo anche su un computer Windows locale. Ho riscontrato questo problema molte volte e ho appena risolto i problemi quando ho riscontrato i problemi. Ieri ho installato un'app per aiutare qualcuno e, naturalmente, ho riscontrato di nuovo il problema. Quindi, ho deciso che era tempo di capire cosa stesse succedendo - e ho trovato questa discussione. Non mi piace l'idea di cambiare sql_mode del server in una modalità precedente (per impostazione predefinita), quindi ho trovato una soluzione semplice (penso).

Questa soluzione richiederebbe ovviamente agli sviluppatori di racchiudere gli script di creazione della tabella per compensare il problema MySQL in esecuzione su Windows. Vedrai concetti simili nei file di dump. Un grande avvertimento è che questo potrebbe / causerà problemi se si utilizza il partizionamento.

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

Questo è tutto.


1
Questo non affronta la questione del perché MySQL abbia il comportamento, ma grazie per aver condiviso il tuo approccio in modo che anche altri possano trarne beneficio. Benvenuto in Stack Overflow!
GargantuChet,

1
Ya lo so ... Dovrò esaminare ulteriormente la modalità STRICT per vedere se ha senso - dal momento che MySQL lancia un avvertimento sui box di Nix, ma fallisce sui box di Windows. Questa è un'indicazione che qualcosa potrebbe essere sbagliato con l'implementazione indipendentemente dalla piattaforma. Noterai che nella documentazione di MySQL è presente questo avviso: "Le colonne BLOB e TEXT non possono avere valori DEFAULT". Quindi, logicamente, sembra che l'implementazione nelle versioni precedenti alla 5 fosse effettivamente interrotta su tutte le piattaforme.
Darrell Greenhouse,

3

Per Ubuntu 16.04:

Come disabilitare la modalità rigorosa in MySQL 5.7:

Modifica il file /etc/mysql/mysql.conf.d/mysqld.cnf

Se la riga sottostante esiste in mysql.cnf

sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"

Quindi sostituirlo con

sql_mode='MYSQL40'

Altrimenti

Aggiungi sotto la riga in mysqld.cnf

sql_mode='MYSQL40'

Questo problema risolto.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.