# 1071 - La chiave specificata era troppo lunga; la lunghezza massima della chiave è 767 byte


563

Quando ho eseguito il seguente comando:

ALTER TABLE `mytable` ADD UNIQUE (
`column1` ,
`column2`
);

Ho ricevuto questo messaggio di errore:

#1071 - Specified key was too long; max key length is 767 bytes

Informazioni su column1 e column2:

column1 varchar(20) utf8_general_ci
column2  varchar(500) utf8_general_ci

Penso che varchar(20)richiede solo 21 byte mentre varchar(500)richiede solo 501 byte. Quindi i byte totali sono 522, meno di 767. Quindi perché ho ricevuto il messaggio di errore?

#1071 - Specified key was too long; max key length is 767 bytes

5
Poiché non è 520 byte, ma piuttosto 2080 byte, che supera di gran lunga 767 byte, è possibile eseguire column1 varchar (20) e column2 varchar (170). se vuoi un carattere / byte equivalente, usa latin1
Rahly il

3
penso che il tuo calcolo sia un po 'sbagliato qui. mysql usa 1 o 2 byte extra per registrare la lunghezza dei valori: 1 byte se la lunghezza massima della colonna è 255 byte o meno, 2 se è più lunga di 255 byte. la codifica utf8_general_ci richiede 3 byte per carattere, quindi varchar (20) utilizza 61 byte, varchar (500) utilizza 1502 byte in totale 1563 byte
lackovic10

3
mysql> seleziona maxlen, character_set_name da information_schema.character_sets in cui character_set_name in ('latin1', 'utf8', 'utf8mb4'); maxlen | character_set_name ------ | ------------------- 1 | latino1 ------ | ------------------- 3 | utf8 ------ | ------------------- 4 | utf8mb4
lackovic10

15
'se vuoi un carattere / byte equiv, usa latin1' Per favore non farlo . Latin1 davvero, fa davvero schifo. Te ne pentirai.
Stijn de Witt,

Consultare stackoverflow.com/a/52778785/2137210 per la soluzione
Pratik,

Risposte:


490

767 byte è la limitazione del prefisso dichiarata per le tabelle InnoDB in MySQL versione 5.6 (e versioni precedenti). È lungo 1.000 byte per le tabelle MyISAM. In MySQL versione 5.7 e successive questo limite è stato aumentato a 3072 byte.

Devi anche essere consapevole che se imposti un indice su un campo big char o varchar codificato in utf8mb4, devi dividere la lunghezza massima del prefisso dell'indice di 767 byte (o 3072 byte) per 4, risultando in 191. Questo perché la lunghezza massima di un carattere utf8mb4 è di quattro byte. Per un carattere utf8 sarebbero tre byte con una lunghezza massima del prefisso indice di 254.

Un'opzione che hai è quella di posizionare il limite inferiore sui campi VARCHAR.

Un'altra opzione (in base alla risposta a questo problema ) è quella di ottenere il sottoinsieme della colonna anziché l'intero importo, ovvero:

ALTER TABLE `mytable` ADD UNIQUE ( column1(15), column2(200) );

Modifica in quanto è necessario ottenere la chiave da applicare, ma mi chiedo se varrebbe la pena rivedere il tuo modello di dati relativo a questa entità per vedere se ci sono miglioramenti che ti permetterebbero di implementare le regole aziendali previste senza colpire la limitazione MySQL.


4
Da applicare specificando un sottoinsieme della colonna anziché l'intero importo. Una buona soluzione
Steven,

204
Questo non spiega perché i campi ben al di sotto del limite di lunghezza stiano superando il limite di lunghezza ...
Cerin

6
Ho provato a modificare nelle informazioni @Cerin manca sopra, che chiaramente è considerato mancante anche da altri, ma viene rifiutato come più adatto come commento. Per coloro che cercano di capire perché 500 + 20> 767 vedi il commento di Stefan Endrullis sulla risposta di Julien.
Letharion,

8
Questo può essere un problema. Ad esempio: ho un nome campo (255) e aggiungo univoco a questo campo nel nome (191) mentre sto usando utf8mb4. Se ho il mio utente aggiungo il loro nome con 'IJUE3ump5fiUuCi16jSofYS234MLschW4wsIktKiBrTPOTKBK6Vteh5pNuz1tKjy ... aO500mlJs' E l'altro utente aggiunge il loro nome con questo 'IJUE3ump5fiUKCjjjji Dovrebbe superare la convalida non bloccata alla voce duplicata.
Vee,

28
Il limite dell'indice è di 767 byte , non di caratteri. E poiché il utf8mb4set di caratteri di Mysql (che il resto del mondo chiama utf8) ha bisogno (al massimo) di 4 byte per carattere , puoi indicizzare solo fino a VARCHAR(191). Il utf8set di caratteri di Mysql (che il resto del mondo chiama rotto) ha bisogno di un massimo di 3 byte per carattere, quindi se stai usando quello (che non dovresti ), puoi indicizzare fino aVARCHAR(255)
Stijn de Witt

404

Se qualcuno sta riscontrando problemi con INNODB / Utf-8 nel tentativo di inserire un UNIQUEindice in un VARCHAR(256)campo, passare a VARCHAR(255). Sembra che 255 sia il limite.


247
Il numero di caratteri consentiti dipende solo dal set di caratteri. UTF8 può utilizzare fino a 3 byte per carattere, utf8mb4 fino a 4 byte e lat1 solo 1 byte. Pertanto per utf8 la lunghezza della chiave è limitata a 255 caratteri, da allora 3*255 = 765 < 767.
Stefan Endrullis,

10
Questo mi ha risparmiato molta frustrazione - grazie. Dovrebbe essere la risposta accettata IMO, considerando che l'utente sta usando InnoDB sostenendo di aver raggiunto un limite di 767b.
TheCarver,

8
Come ha affermato Stefan Endrullis, dipende dal set di caratteri. Se si utilizza UTF8 che utilizza 3 byte: 255x3 = 765 che è inferiore al limite 767, mentre 256x3 = 768 che è maggiore. Ma se usi UTF8mb4 è 255 * 4 = 1020, quindi non è davvero una soluzione
bernhardh

25
Questa risposta è corretta Tuttavia, se 255 funziona davvero per te, significa che stai usando Mysql utf8, che purtroppo è rotto. Può solo codificare caratteri nel piano multilingue di base. Avrai problemi con i personaggi che non ci sono. Ad esempio, penso che quei personaggi Emoji che hanno aggiunto cadano al di fuori di esso. Quindi, invece di passare a VARCHAR(255), passa a VARCHAR(191) e cambia la codifica in utf8mb4(che in realtà è solo utf8, ma MySql voleva tornare indietro. Compat).
Stijn de Witt,

1
Non utile per il mio vincolo univoco a più colonne. Inoltre non funzionerebbe per il vincolo univoco a più colonne dell'OP. (darebbe una dimensione totale di 825 byte)
Barett

351

Quando raggiungi il limite. Impostare quanto segue.

  • INNODB utf8 VARCHAR(255)
  • INNODB utf8mb4 VARCHAR(191)

34
Questa è la risposta migliore Semplice, diretto al punto e include anche il utf8mb4limite (che è la codifica più utilizzata per i database più recenti, poiché accetta emoji / ecc.).
Claudio Holanda,

10
perché 767/4 ~ = 191 e 767/3 ~ = 255
Contabile م

11
dove e come impostarlo?
Dinesh Sunny,

1
Sì, specificando ENGINE=InnoDB DEFAULT CHARSET=utf8alla fine CREATE TABLEdell'istruzione sono stato in grado di avere una VARCHAR(255)chiave primaria. Grazie.
Xonya,

1
qualcuno gli dà +1 per superare il limite 191 :)
cagcak

147

MySQL presuppone il caso peggiore per il numero di byte per carattere nella stringa. Per la codifica "utf8" di MySQL, vale 3 byte per carattere poiché quella codifica non consente caratteri oltre U+FFFF. Per la codifica "utf8mb4" di MySQL, è di 4 byte per carattere, poiché questo è ciò che MySQL chiama UTF-8 reale.

Quindi supponendo che tu stia usando 'utf8', la tua prima colonna prenderà 60 byte dell'indice e la seconda un altro 1500.


4
- Il che presumibilmente significa che quando uso utf8mb4, devo impostarli su (al massimo) 191 come 191 * 4 = 764 <767.
Isaac

2
@Isaac Sì, esattamente,
morganwahl,

2
Penso che questa potrebbe essere la risposta giusta, ma potresti approfondire cosa si dovrebbe fare per correggere un simile problema? Almeno per i nomi di MySQL come me?
Adam Grant,

Non esiste un modo per aggirare questo limite di indice. La domanda qui riguarda i vincoli unici; per quelli, puoi avere una colonna di testo di lunghezza illimitata e un'altra in cui memorizzi un hash (come MD5) di quel testo e usi la colonna di hash per il tuo vincolo unico. Dovrai assicurarti che il tuo programma mantenga gli hash aggiornati quando modifica il testo, ma ci sono vari modi per gestirlo senza troppi problemi. Francamente, MySQL dovrebbe implementare una cosa del genere in modo da non doverlo fare; Non sarei sorpreso se MariaDB avesse qualcosa di simile incorporato.
morganwahl,

Un indice univoco su una colonna varchar molto lunga è raro. Pensa al motivo per cui ne hai bisogno perché potrebbe essere un problema di progettazione. Se vuoi solo un indice su di esso per la ricerca, considera alcuni campi "parole chiave" che si adattano a 191 caratteri, o dividi il testo in una breve descrizione e un testo lungo / completo ecc. O se hai davvero bisogno di una ricerca full text, considera l'utilizzo di software specializzato per come Apache Lucene.
Stijn de Witt,

56

eseguire questa query prima della query:

SET @@global.innodb_large_prefix = 1;

questo aumenterà il limite a 3072 bytes.


4
C'è qualche svantaggio nel cambiare a innodb_large_prefix a livello globale? E quel DB è "globale" o tutti i DB TOTALMENTE GLOBALI?
SciPhi,

5
Si applica solo quando si utilizzano formati di riga non standard. Vedi dev.mysql.com/doc/refman/5.5/en/… . In particolare, "Abilitare questa opzione per consentire prefissi chiave di indice più lunghi di 767 byte (fino a 3072 byte), per le tabelle InnoDB che utilizzano i formati di riga DYNAMIC e COMPRESSED". Il formato di riga predefinito non è interessato.
Chris Lear,

5
Questo ha funzionato bene per me - maggiori dettagli e una guida sono disponibili qui: mechanics.flite.com/blog/2014/07/29/…
cwd

1
dobbiamo riavviare il server mysql dopo questo?
SimpleGuy

7
Importanti dettagli mancanti da questa risposta. innodb_file_formatdeve essere BARRACUDAe a livello di tavolo devi usare ROW_FORMAT=DYNAMICo ROW_FORMAT=COMPRESSED. Vedi il commento di @ cwd sopra con la guida.
q0rban

46

Soluzione per Laravel Framework

Secondo la documentazione di Laravel 5.4. * ; Devi impostare la lunghezza della stringa predefinita all'interno del bootmetodo del app/Providers/AppServiceProvider.phpfile come segue:

use Illuminate\Support\Facades\Schema;

public function boot() 
{
    Schema::defaultStringLength(191); 
}

Spiegazione di questa correzione, fornita dalla documentazione di Laravel 5.4. * :

Laravel utilizza il utf8mb4set di caratteri per impostazione predefinita, che include il supporto per la memorizzazione di "emoji" nel database. Se si esegue una versione di MySQL precedente alla versione 5.7.7 o MariaDB precedente alla versione 10.2.2, potrebbe essere necessario configurare manualmente la lunghezza della stringa predefinita generata dalle migrazioni per consentire a MySQL di creare gli indici per esse. Puoi configurarlo chiamando il Schema::defaultStringLengthmetodo nel tuo AppServiceProvider.

In alternativa, è possibile abilitare l' innodb_large_prefixopzione per il database. Fare riferimento alla documentazione del database per istruzioni su come abilitare correttamente questa opzione.


10
@BojanPetkovic Beh, sono appena arrivato da un problema di Laravel e questa risposta ha risolto il mio problema.
mkmnstr,

Questa risposta è fantastica Ma qualcuno lo sa, perché funziona esattamente?
UeliDeSchwert,

1
La documentazione di @Bobby Laravel fornisce la sua spiegazione nel titolo "Index Lengths & MySQL / MariaDB" laravel.com/docs/5.4/migrations#creating-indexes
Ali Shaukat

1
@Bobby Ho aggiornato la risposta. Ho aggiunto la spiegazione fornita dalla documentazione di laravel per questa correzione.
Ali Shaukat,

39

Quale codifica dei caratteri stai usando? Alcuni set di caratteri (come UTF-16, eccetera) utilizzano più di un byte per carattere.


8
Se è UTF8, un personaggio può usare fino a 4 byte, in modo che la colonna di 20 caratteri sia 20 * 4 + 1byte e la colonna da 500 caratteri sia 500 * 4 + 2byte
Thanatos,

5
Per quello che vale, ho appena avuto lo stesso problema e il passaggio da utf8_general_ci a utf8_unicode_ci ha risolto il problema per me. Non so perché però :(
Andresch Serj,

11
Per una VARCHAR(256)colonna con un UNIQUEindice, la modifica delle regole di confronto non ha avuto alcun effetto per me, come ha fatto per @Andresch. Tuttavia, riducendo la lunghezza da 256 a 255 lo ha risolto. Non capisco perché, dato che 767 / max 4 byte per carattere generano un massimo di 191?
Arjan,

10
255*3 = 765; 256*3 = 768. Sembra che il tuo server abbia assunto 3 byte per carattere, @Arjan
Ambra

21
@Greg: hai ragione, ma questo dovrebbe essere elaborato: UTF-8 stesso usa 1–4 byte per punto di codice. I "set di caratteri" di MySQL (in realtà codifiche) hanno un set di caratteri chiamato "utf8" che è in grado di codificare parte di UTF-8 e utilizza 1-3 byte per punto di codice ed è incapace di codificare punti di codice al di fuori del BMP. Include anche un altro set di caratteri chiamato "utf8mb4", che utilizza 1–4 byte per punto di codice ed è in grado di codificare tutti i punti di codice Unicode. (utf8mb4 è UTF-8, utf8 è una versione strana di UTF-8.)
Thanatos

28

Penso che varchar (20) richieda solo 21 byte mentre varchar (500) richieda solo 501 byte. Quindi i byte totali sono 522, meno di 767. Quindi perché ho ricevuto il messaggio di errore?

UTF8 richiede 3 byte per carattere per memorizzare la stringa, quindi nel tuo caso 20 + 500 caratteri = 20 * 3 + 500 * 3 = 1560 byte che è più di 767 byte consentiti .

Il limite per UTF8 è 767/3 = 255 caratteri , per UTF8mb4 che utilizza 4 byte per carattere è 767/4 = 191 caratteri.


Esistono due soluzioni a questo problema se è necessario utilizzare una colonna più lunga del limite:

  1. Usa la codifica "più economica" (quella che richiede meno byte per carattere)
    Nel mio caso, avevo bisogno di aggiungere un indice Unico sulla colonna contenente una stringa di articoli SEO, poiché utilizzo solo [A-z0-9\-]caratteri per SEO, che ho usato latin1_general_ciche utilizza solo un byte per carattere e quindi la colonna può avere una lunghezza di 767 byte.
  2. Crea hash dalla tua colonna e usa un indice univoco solo su quello
    L'altra opzione per me era creare un'altra colonna che memorizzasse hash di SEO, questa colonna avrebbe avuto la UNIQUEchiave per garantire che i valori SEO fossero unici. Vorrei anche aggiungere un KEYindice alla colonna SEO originale per velocizzare la ricerca.

Questo ha funzionato. Ho avuto varchar (256) e ho dovuto cambiarlo in varchar (250).
MaRmAR

25

La risposta sul motivo per cui ricevi un messaggio di errore ha già ricevuto risposta da molti utenti qui. La mia risposta è su come ripararlo e usarlo così com'è.

Fare riferimento da questo link .

  1. Apri il client MySQL (o il client MariaDB). È uno strumento da riga di comando.
  2. Chiederà la tua password, inserisci la password corretta.
  3. Seleziona il tuo database usando questo comando use my_database_name;

Database modificato

  1. set global innodb_large_prefix=on;

Query OK, 0 righe interessate (0.00 sec)

  1. set global innodb_file_format=Barracuda;

Query OK, 0 righe interessate (0,02 sec)

  1. Vai al tuo database su phpMyAdmin o qualcosa del genere per una facile gestione. > Seleziona database> Visualizza struttura tabella > Vai alla scheda Operazioni . > Cambia ROW_FORMAT in DYNAMIC e salva le modifiche.
  2. Vai alla scheda struttura della tabella> Fai clic sul pulsante Unico .
  3. Fatto. Ora non dovrebbe avere errori.

Il problema di questa correzione è se si esporta db su un altro server (ad esempio da localhost a host reale) e non è possibile utilizzare la riga di comando MySQL in quel server. Non puoi farlo funzionare lì.


se sei ancora un errore dopo aver inserito la query sopra, prova ad andare su "phpmyadmin"> imposta la "collation" secondo le tue preferenze (per me uso "utf8_general_ci")> fai clic su applica (anche se è già utf8)
Anthony Kal

Non sto usando uno strumento che funzioni con le tue istruzioni, ma lo sto ancora votando per cercare di aiutare le persone a risolvere il problema. Ci sono infinite spiegazioni di ciò che causa il problema, ma notevolmente poco su come risolverlo effettivamente.
Teekin,

20
Specified key was too long; max key length is 767 bytes

Hai ricevuto quel messaggio perché 1 byte equivale a 1 carattere solo se usi il latin-1set di caratteri. Se si utilizza utf8, ogni carattere verrà considerato 3 byte quando si definisce la colonna chiave. Se si utilizza utf8mb4, ogni carattere verrà considerato di 4 byte quando si definisce la colonna chiave. Pertanto, è necessario moltiplicare il limite di caratteri del campo chiave per, 1, 3 o 4 (nel mio esempio) per determinare il numero di byte che il campo chiave sta tentando di consentire. Se stai usando uft8mb4, puoi definire solo 191 caratteri per un campo chiave primario nativo, InnoDB. Basta non violare 767 byte.


17

Sostituisci utf8mb4con utf8nel tuo file di importazione.

inserisci qui la descrizione dell'immagine


Perché esattamente uno dovrebbe farlo? Inoltre, se questo ha degli aspetti negativi (che presumo), dovresti menzionarlo
Nico Haase,

16

potresti aggiungere una colonna di md5 di colonne lunghe


Tieni presente che ciò non ti consentirà di eseguire scansioni dell'intervallo su queste colonne. Le lunghezze dei prefissi su VARCHAR ti permetteranno di mantenere questo tratto, causando allo stesso tempo corrispondenze forse spurie nell'indice (e la scansione e la ricerca di righe per eliminarli) (vedi la risposta accettata). (Questo è essenzialmente un indice hash implementato manualmente, che purtroppo MysQL non supporta le tabelle InnoDB.)
Thanatos

Non ho potuto usare gli indici dei prefissi perché avevo bisogno di mantenere la compatibilità con H2 a scopo di test e ho scoperto che usando una colonna di hash funziona bene. Consiglio vivamente di utilizzare una funzione resistente alle collisioni come SHA1 anziché MD5 per impedire agli utenti malintenzionati di creare collisioni. Una collisione dell'indice potrebbe essere sfruttata per perdere dati se una delle tue query verifica solo il valore hash e non il valore della colonna completa.
Little Mike,

13

Abbiamo riscontrato questo problema durante il tentativo di aggiungere un indice UNIQUE a un campo VARCHAR (255) utilizzando utf8mb4. Mentre il problema è già ben delineato qui, volevo aggiungere alcuni consigli pratici su come lo abbiamo capito e risolto.

Quando si utilizza utf8mb4, i caratteri contano come 4 byte, mentre in utf8 potrebbero essere come 3 byte. I database InnoDB hanno un limite che gli indici possono contenere solo 767 byte. Pertanto, quando si utilizza utf8, è possibile memorizzare 255 caratteri (767/3 = 255), ma utilizzando utf8mb4, è possibile memorizzare solo 191 caratteri (767/4 = 191).

Sei assolutamente in grado di aggiungere indici regolari per i VARCHAR(255)campi utilizzando utf8mb4, ma ciò che accade è che la dimensione dell'indice viene automaticamente troncata a 191 caratteri, come unique_keyqui:

Schermata di Sequel Pro che mostra un indice troncato a 191 caratteri

Questo va bene, perché gli indici regolari vengono utilizzati solo per aiutare MySQL a cercare più rapidamente i dati. Non è necessario indicizzare l'intero campo.

Quindi, perché MySQL tronca automaticamente l'indice per gli indici regolari, ma genera un errore esplicito quando si tenta di farlo per indici univoci? Bene, affinché MySQL sia in grado di capire se il valore inserito o aggiornato esiste già, deve effettivamente indicizzare l'intero valore e non solo una parte di esso.

Alla fine della giornata, se si desidera avere un indice univoco su un campo, l'intero contenuto del campo deve rientrare nell'indice. Per utf8mb4, ciò significa ridurre la lunghezza del campo VARCHAR a 191 caratteri o meno. Se non hai bisogno di utf8mb4 per quella tabella o quel campo, puoi riportarlo su utf8 ed essere in grado di mantenere i tuoi 255 campi di lunghezza.


11

Ecco la mia risposta originale:

Ho appena lasciato il database e ricreato in questo modo, e l'errore è sparito:

drop database if exists rhodes; create database rhodes default CHARACTER set utf8 default COLLATE utf8_general_ci;

Tuttavia, non funziona per tutti i casi.

In realtà è un problema di utilizzo degli indici su colonne VARCHAR con il set di caratteri utf8(o utf8mb4), con colonne VARCHAR che hanno più di una certa lunghezza di caratteri. Nel caso di utf8mb4quella determinata lunghezza è 191.

Per ulteriori informazioni su come utilizzare gli indici lunghi nel database MySQL, consultare la sezione Indice lungo in questo articolo: http://hanoian.com/content/index.php/24-automate-the-converting-a-mysql-database- personaggio-set-a-utf8mb4


Risolto il problema per l'installazione di openmeetings (A proposito, mi hai salvato la notte :-)
Ludo

11

5 soluzioni alternative:

Il limite è stato aumentato in 5.7.7 (MariaDB 10.2.2?). E può essere aumentato con un po 'di lavoro in 5.6 (10.1).

Se stai raggiungendo il limite a causa del tentativo di utilizzare SET DI CARATTERI utf8mb4. Quindi, procedi in uno dei seguenti modi (ognuno ha uno svantaggio) per evitare l'errore:

  Upgrade to 5.7.7 for 3072 byte limit -- your cloud may not provide this;
  Change 255 to 191 on the VARCHAR -- you lose any values longer than 191 characters (unlikely?);
  ALTER .. CONVERT TO utf8 -- you lose Emoji and some of Chinese;
  Use a "prefix" index -- you lose some of the performance benefits.
  Or... Stay with older version but perform 4 steps to raise the limit to 3072 bytes:

SET GLOBAL innodb_file_format=Barracuda;
SET GLOBAL innodb_file_per_table=1;
SET GLOBAL innodb_large_prefix=1;
logout & login (to get the global values);
ALTER TABLE tbl ROW_FORMAT=DYNAMIC;  -- (or COMPRESSED)

- http://mysql.rjweb.org/doc.php/limits#767_limit_in_innodb_indexes


10

Ho risolto questo problema con:

varchar(200) 

sostituito con

varchar(191)

tutti i varchar che hanno più di 200 li sostituiscono con 191 o li impostano come testo.


Questo è ciò che ha funzionato anche per me. Ho avuto un varchar (250), ma i dati non sono mai stati così lunghi. Modificato in varchar (100). Grazie per l'idea :)
Arun Basil Lal,

7

Ho fatto qualche ricerca su questo argomento alla fine ho ottenuto alcune modifiche personalizzate

Per MySQL workbench Versione 6.3.7 Interfase grafica disponibile

  1. Avviare Workbench e selezionare la connessione.
  2. Vai a gestione o Istanza e seleziona File delle opzioni.
  3. Se Workbench ti chiede il permesso di leggere il file di configurazione e poi lo consenti premendo OK due volte.
  4. Al centro viene visualizzata la finestra del file delle opzioni dell'amministratore.
  5. Vai alla scheda InnoDB e controlla innodb_large_prefix se non è stato verificato nella sezione Generale.
  6. impostare il valore dell'opzione innodb_default_row_format su DYNAMIC.

Per le versioni inferiori a 6.3.7 le opzioni dirette non sono disponibili, quindi è necessario andare con il prompt dei comandi

  1. Avviare CMD come amministratore.
  2. Vai al direttore in cui è installato il server mysql La maggior parte dei casi si trova in "C: \ Programmi \ MySQL \ MySQL Server 5.7 \ bin", quindi il comando è "cd \" "cd Programmi \ MySQL \ MySQL Server 5.7 \ bin".
  3. Ora esegui il comando mysql -u userName -p databasecheema Ora ha richiesto la password del rispettivo utente. Fornire la password e accedere al prompt mysql.
  4. Dobbiamo impostare alcune impostazioni globali inserire i comandi seguenti uno per uno impostare global innodb_large_prefix = on; set global innodb_file_format = barracuda; set global innodb_file_per_table = true;
  5. Ora alla fine dobbiamo modificare ROW_FORMAT della tabella richiesta per impostazione predefinita COMPACT, dobbiamo impostarlo su DYNAMIC.
  6. utilizzare il seguente comando alter table table_name ROW_FORMAT = DYNAMIC;
  7. Fatto

Non riesco a trovarlo: 6. imposta il valore dell'opzione innodb_default_row_format su DYNAMIC.
Adrian Cid Almaguer,

se uso set global innodb_default_row_format = DYNAMIC;vedo questo messaggio: ERRORE 1193 (HY000): variabile di sistema sconosciuta 'innodb_default_row_format'
Adrian Cid Almaguer

come hai ricevuto l'errore da workbench a cmd? L'ho fatto dal banco di lavoro che ha l'opzione direttamente.
Abhishek,

Lo faccio da CMD perché non vedo l'opzione in Workbench
Adrian Cid Almaguer,

1
Vedo il problema che questo var è stato introdotto nella v5.7.9 e ho la versione v5.6.33, grazie
Adrian Cid Almaguer,

7

Per laravel da 5,7 a 6,0

I passaggi da seguire

  1. Vai a App\Providers\AppServiceProvider.php.
  2. Aggiungi questo al provider use Illuminate\Support\Facades\Schema;in alto.
  3. All'interno della funzione Boot Aggiungi questo Schema::defaultStringLength(191);

tutto qui, divertiti.


Ha funzionato anche per Laravel 5.8.
Neo

Questa è una cattiva soluzione. Motivo: gli indici non sono pensati per essere infinitamente lunghi. Quando si applica un indice univoco a qualcosa, si desidera che l'indice sia fissato con il più delle volte. Ciò significa che NON DOVREBBE fare cose come emailuniche, ma dovresti hash e-mail e renderlo unico. A differenza dei dati di stringa grezzi, gli hash hanno una larghezza fissa e possono essere indicizzati e resi unici senza problemi. Invece di capire il problema, stai diffondendo terribili pratiche che non si adattano.
NB

5

cambia la tua raccolta. Puoi usare utf8_general_ci che supporta quasi tutti


"Quasi" è un buon suggerimento che questa non è una soluzione a lungo termine
Nico Haase,

4

Il solo passaggio utf8mb4a utf8durante la creazione di tabelle ha risolto il mio problema. Ad esempio: CREATE TABLE ... DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;a CREATE TABLE ... DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;.


4

Per risolvere questo, questo funziona per me come un fascino.

ALTER DATABASE dbname CHARACTER SET utf8 COLLATE utf8_general_ci;

Confermo che il mio problema è stato anche il confronto del database. Non ho alcuna spiegazione per questo. Uso mysql v5.6.32 e le regole di confronto DB erano utf8mb4_unicode_ci.
Mahyard,

2

Sulla base della colonna indicata di seguito, quelle 2 colonne di stringa variabile utilizzano le utf8_general_ciregole di confronto (il utf8set di caratteri è implicito).

In MySQL, utf8charset utilizza un massimo di 3 byte per ciascun personaggio. Pertanto, dovrebbe allocare 500 * 3 = 1500 byte, che è molto maggiore dei 767 byte consentiti da MySQL. Ecco perché ricevi questo errore 1071.

In altre parole, è necessario calcolare il conteggio dei caratteri in base alla rappresentazione dei byte del set di caratteri poiché non tutti i set di caratteri sono rappresentati da un singolo byte (come si presumeva). IE utf8in MySQL utilizza al massimo 3 byte per carattere, 767 / 3≈255 caratteri e per utf8mb4, una rappresentazione al massimo di 4 byte, 767 / 4≈191 caratteri.

È anche noto che MySQL

column1 varchar(20) utf8_general_ci
column2  varchar(500) utf8_general_ci

1

Ho trovato questa query utile per rilevare quali colonne avevano un indice che violava la lunghezza massima:

SELECT
  c.TABLE_NAME As TableName,
  c.COLUMN_NAME AS ColumnName,
  c.DATA_TYPE AS DataType,
  c.CHARACTER_MAXIMUM_LENGTH AS ColumnLength,
  s.INDEX_NAME AS IndexName
FROM information_schema.COLUMNS AS c
INNER JOIN information_schema.statistics AS s
  ON s.table_name = c.TABLE_NAME
 AND s.COLUMN_NAME = c.COLUMN_NAME 
WHERE c.TABLE_SCHEMA = DATABASE()
  AND c.CHARACTER_MAXIMUM_LENGTH > 191 
  AND c.DATA_TYPE IN ('char', 'varchar', 'text')

1

Si prega di verificare se sql_modeè come

sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES

se lo è, cambia in

sql_mode=NO_ENGINE_SUBSTITUTION

O

riavviare il server modificando il file my.cnf (inserendo quanto segue)

innodb_large_prefix=on

1

Nel mio caso, ho riscontrato questo problema durante il backup di un database utilizzando i caratteri di output / input di reindirizzamento di Linux. Pertanto, cambio la sintassi come descritto di seguito. PS: utilizzando un terminale Linux o Mac.

Backup (senza il> reindirizzamento)

# mysqldump -u root -p databasename -r bkp.sql

Ripristina (senza <reindirizzamento)

# mysql -u root -p --default-character-set=utf8 databasename
mysql> SET names 'utf8'
mysql> SOURCE bkp.sql

L'errore "Chiave specificata era troppo lungo; la lunghezza massima della chiave è 767 byte" è semplicemente scomparso.


1

Lunghezze dell'indice e MySQL / MariaDB


Laravel utilizza il set di caratteri utf8mb4 per impostazione predefinita, che include il supporto per la memorizzazione di "emoji" nel database. Se si esegue una versione di MySQL precedente alla versione 5.7.7 o MariaDB precedente alla versione 10.2.2, potrebbe essere necessario configurare manualmente la lunghezza della stringa predefinita generata dalle migrazioni per consentire a MySQL di creare gli indici per esse. Puoi configurarlo chiamando il metodo Schema :: defaultStringLength nel tuo AppServiceProvider:

use Illuminate\Support\Facades\Schema;

/**
 * Bootstrap any application services.
 *
 * @return void
 */
public function boot()
{
    Schema::defaultStringLength(191);
}

In alternativa, è possibile abilitare l'opzione innodb_large_prefix per il database. Fare riferimento alla documentazione del database per istruzioni su come abilitare correttamente questa opzione.

Riferimento dal blog: https://www.scratchcode.io/specified-key-too-long-error-in-laravel/

Riferimento dalla documentazione ufficiale di laravel: https://laravel.com/docs/5.7/migrations


0

Se stai creando qualcosa di simile:

CREATE TABLE IF NOT EXISTS your_table (
  id int(7) UNSIGNED NOT NULL AUTO_INCREMENT,
  name varchar(256) COLLATE utf8mb4_bin NOT NULL,
  PRIMARY KEY (id),
  UNIQUE KEY name (name)
) ENGINE=INNODB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=1 ROW_FORMAT=FIXED;

dovrebbe essere qualcosa di simile

CREATE TABLE IF NOT EXISTS your_table (
      id int(7) UNSIGNED NOT NULL AUTO_INCREMENT,
      name varchar(256) COLLATE utf8mb4_bin NOT NULL,
      PRIMARY KEY (id)
    ) ENGINE=INNODB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=1 ROW_FORMAT=FIXED;

ma devi controllare l'unicità di quella colonna dal codice o aggiungere una nuova colonna come MD5 o SHA1 della colonna varchar


3
Quindi la tua chiave unica è andata persa. Penso che il modo migliore sia semplicemente ridurre la lunghezza del nome a 191.
haudoing

1
Perché verificare l'univocità a livello di codice se è la funzionalità DB nativa?
Paweł Tomkiel,

0

A causa delle limitazioni del prefisso, si verificherà questo errore. 767 byte è la limitazione del prefisso dichiarata per le tabelle InnoDB nelle versioni MySQL precedenti alla 5.7. È lungo 1.000 byte per le tabelle MyISAM. In MySQL versione 5.7 e successive questo limite è stato aumentato a 3072 byte.

Eseguire quanto segue sul servizio che fornisce l'errore dovrebbe risolvere il problema. Questo deve essere eseguito nella CLI MYSQL.

SET GLOBAL innodb_file_format=Barracuda;
SET GLOBAL innodb_file_per_table=on;
SET GLOBAL innodb_large_prefix=on;

-1

Modificare CHARSET del campo indice in questione su "latin1",
ovvero ALTER TABLE tbl CHANGE myfield myfield varchar (600) SET DI CARATTERI latin1 DEFAULT NULL;
latin1 richiede un byte per un carattere anziché quattro


5
E se tentasse di inserire caratteri non latini1 ?
Paweł Tomkiel,

4
Questa è la cosa peggiore da fare. Non farlo mai.
Sebas,

1
nel mio caso è su una colonna che memorizza i nomi dei percorsi con solo caratteri esadecimali ... quindi questa potrebbe essere una soluzione per qualcuno. dipende davvero da cosa vuoi conservare ...
codewandler

Ho dovuto ridimensionare questo dato, poiché l'uso di latin1 non è una soluzione nel 2016 AD. Ho ancora orribili incubi sul tempo in cui abbiamo dovuto convertire un database da latin1 a utf8 nel 2007. Ugh. Non carino. Affatto.
Scommetti su Lamed il

Ho avuto lo stesso problema su un indice univoco su due colonne in cui memorizzo gli indirizzi bitcoin e gli ID transazione. Questi saranno sempre caratteri ASCII, quindi userò latin1 su queste colonne. Upvoting.
alexg

-2

Se hai modificato di innodb_log_file_sizerecente, prova a ripristinare il valore precedente che ha funzionato.

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.