È ansible avere indici basati su funzioni in MySQL?

Ricordo che in Oracle è ansible indicizzare in base a una funzione, ad esempio SUBSTRING(id,1,8) .

MySQL supporta questo? Se no, c’è qualche alternativa?

No, non in senso generale, non credo nemmeno che 5.6 abbia questa funzionalità. È ansible utilizzare solo la parte principale di una colonna (questa funzionalità è in uso da molto tempo), ma non una che parte dal secondo o dai caratteri successivi o da qualsiasi altra funzione più complessa.

Ad esempio, il seguente crea un indice usando i primi cinque caratteri di un nome:

 create index name_first_five on cust_table (name(5)); 

Per espressioni più complesse, è ansible ottenere un effetto simile disponendo di un’altra colonna con i dati indicizzabili, quindi utilizzando i trigger di inserimento / aggiornamento per assicurarsi che sia popolata correttamente.

A parte lo spazio sprecato per i dati ridondanti, è praticamente la stessa cosa.

E, anche se tecnicamente viola 3NF, questo è mitigato dall’uso di trigger per mantenere i dati sincronizzati (questo è qualcosa che viene spesso fatto per prestazioni aggiuntive).

MySQL non supporta questo, ma c’è un’alternativa.

1. Da MySQL 5.7.6

Puoi utilizzare una colonna generata automaticamente per contenere la sottostringa con un indice su di essa:

 CREATE TABLE SomeTable ( id CHAR(10), sub_id CHAR(8) AS SUBSTRING(id, 1, 8) STORED, INDEX(sub_id) ) 

Come ha notato Benjamin , InnoDB supporta indici secondari su colonne virtuali, pertanto la parola chiave STORED può essere omessa. In effetti, gli indici secondari su colonne virtuali possono essere preferibili. Maggiori informazioni qui: Indici secondari e colonne generate

2. Prima di MySQL 5.7.6

Puoi utilizzare una colonna aggiornata da un trigger con un indice su di esso:

 CREATE TABLE SomeTable ( id CHAR(10), sub_id CHAR(8) , INDEX(sub_id) ); CREATE TRIGGER TR_SomeTable_INSERT_sub_id BEFORE INSERT ON SomeTable FOR EACH ROW SET NEW.sub_id = SUBSTRING(NEW.id, 1, 8); CREATE TRIGGER TR_SomeTable_UPDATE_sub_id BEFORE UPDATE ON SomeTable FOR EACH ROW SET NEW.sub_id = SUBSTRING(NEW.id, 1, 8); 

Questo è ansible a partire da MySQL 5.7.5 usando le nuove colonne generate .