Domanda

Sto eseguendo localmente un database MySQL per lo sviluppo, ma sto distribuendo su Heroku che utilizza Postgres. Heroku gestisce quasi tutto, ma le mie affermazioni Like insensibili alle maiuscole diventano maiuscole e minuscole. Potrei usare le dichiarazioni iLike, ma il mio database MySQL locale non può gestirlo.

Qual è il modo migliore per scrivere una query senza distinzione tra maiuscole e minuscole compatibile con MySQL e Postgres? O devo scrivere istruzioni Like e iLike separate a seconda del DB con cui sta parlando la mia app?

È stato utile?

Soluzione

select * from foo where upper(bar) = upper(?);

Se si imposta il parametro in maiuscolo nel chiamante, è possibile evitare la seconda chiamata di funzione.

Altri suggerimenti

La morale di questa storia è: non usare uno stack software diverso per lo sviluppo e la produzione. Mai.

Finirai con bug che non puoi riprodurre in sviluppo; i tuoi test saranno inutili. Basta non farlo.

L'uso di un motore di database diverso è fuori discussione: ci saranno MOLTI casi in cui si comporta in modo diverso rispetto a LIKE (inoltre, hai controllato le regole di confronto utilizzate dai database? Sono identiche in OGNI CASO? Se no , puoi dimenticare ORDER BY sulle colonne varchar che funzionano allo stesso modo)

Usa Arel:

Author.where(Author.arel_table[:name].matches("%foo%"))

match utilizzerà l'operatore ILIKE per Postgres e LIKE per tutto il resto.

In Postgres, puoi farlo:

SELECT whatever FROM mytable WHERE something ILIKE 'match this';

Non sono sicuro che ci sia un equivalente per MySQL, ma puoi sempre farlo, il che è un po 'brutto ma dovrebbe funzionare sia in MySQL che in Postgres:

SELECT whatever FROM mytable WHERE UPPER(something) = UPPER('match this');

Esistono diverse risposte, nessuna delle quali è molto soddisfacente.

  • INFERIORE (barra) = INFERIORE (?) funzionerà su MySQL e Postgres, ma probabilmente funzionerà terribilmente su MySQL : MySQL non utilizzerà i suoi indici a causa della funzione INFERIORE. Su Postgres puoi aggiungere un indice funzionale (su INFERIORE (barra) ) ma MySQL non lo supporta.
  • MySQL (a meno che tu non abbia impostato una distinzione tra maiuscole e minuscole fascicolazione ) esegue automaticamente la corrispondenza senza distinzione tra maiuscole e minuscole e usa i suoi indici. ( bar =? ).
  • Dal tuo codice esterno al database, mantieni i campi bar e bar_lower , dove bar_lower contiene il risultato di inferiore (barra) . (Ciò può essere possibile anche utilizzando i trigger del database). (Vedi una discussione di questa soluzione su Drupal ). Questo è goffo ma almeno funziona allo stesso modo su quasi tutti i database.

REGEXP non fa distinzione tra maiuscole e minuscole (se non utilizzato con BINARY) e può essere utilizzato, in questo modo ...

    SELECT id FROM person WHERE name REGEXP 'john';

... per abbinare 'John', 'JOHN', 'john', ecc.

Se stai usando PostgreSQL 8.4 puoi usare il modulo citext per creare campi di testo senza distinzione tra maiuscole e minuscole.

Potresti anche prendere in considerazione il check-in searchlogic , che esegue il LIKE / ILIKE per te.

Puoi anche usare ~ * in postgres se vuoi abbinare una sottostringa all'interno di un blocco. ~ corrisponde alla sottostringa sensibile al maiuscolo / minuscolo, alla ~ sottostringa sensibile al maiuscolo / minuscolo. È un'operazione lenta, ma potrei trovarlo utile per le ricerche.

Select * from table where column ~* 'UnEvEn TeXt';
Select * from table where column ~ 'Uneven text';

Entrambi colpirebbero " Qualche testo non uniforme qui " Solo il primo avrebbe colpito " Some UNEVEN TEXT qui "

La conversione in upper è la migliore in quanto copre la sintassi compatibile per i 3 backend del database Rails più utilizzati. PostgreSQL, MySQL e SQLite supportano tutti questa sintassi. Ha lo svantaggio (minore) che devi mettere in maiuscolo la stringa di ricerca nella tua applicazione o nella stringa delle tue condizioni, rendendola un po 'più brutta, ma penso che la compatibilità che ottieni lo renda utile.

Sia MySQL che SQLite3 hanno un operatore LIKE senza distinzione tra maiuscole e minuscole. Solo PostgreSQL ha un operatore LIKE con distinzione tra maiuscole e minuscole e un operatore ILIKE (per il manuale) specifico di PostgreSQL per le ricerche senza distinzione tra maiuscole e minuscole. Puoi specificare ILIKE insead di LIKE nelle tue condizioni sull'applicazione Rails, ma tieni presente che l'applicazione smetterà di funzionare con MySQL o SQLite.

Una terza opzione potrebbe essere quella di verificare quale motore di database stai usando e modificare la stringa di ricerca di conseguenza. Questo potrebbe essere fatto meglio hackerando / monkeypatching gli adattatori di connessione di ActiveRecord e facendo in modo che l'adattatore PostgreSQL modifichi la stringa di query per sostituire "COME" per " ILIKE " prima dell'esecuzione della query. Questa soluzione è tuttavia la più complicata e alla luce di modi più semplici come mettere in rilievo entrambi i termini, penso che questo non preoccupi lo sforzo (anche se otterresti molti punti brownie per farlo in questo modo).

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top