2013-06-19 17 views
5

Ho una tabella che contiene percorsi relativi ai file reali su HDD. ad esempio:MySQL può controllare che il file esista?

SELECT * FROM images --> 
id | path 
1 | /files/1.jpg 
2 | /files/2.jpg 

Posso creare una query per selezionare tutti i record che puntano a file inesistenti? Ho bisogno di controllarlo esattamente dal server MySql, senza usare un'iterazione in PHP-client.

+0

Questo è un pessimo design. –

+0

Non credo che MySQL abbia alcun tipo di accesso al file system per questo genere di cose. Dovrai utilizzare una lingua esterna per raggiungere questo obiettivo. – ethrbunny

+0

Bogdan Burim, perché male?È meglio mettere i dati delle immagini nel campo BINARY o cosa? – WindBridges

risposta

3

MYSQL gestisce solo il database, quindi non è possibile per il licenziatario attivare un'istruzione SQL per verificare l'HDD se il file esiste. È necessario scorrere le righe e controllarlo con PHP.

+0

grazie. Ho pensato che potrebbe essere se mysql ha feticci come LOAD DATA INFILE ecc. In altre parole può accedere ai file dell'utente, quindi può avere qualcosa da controllare se il file esiste. – WindBridges

+0

Oppure puoi archiviare i tuoi file nel tuo database come BLOB di oggetti grandi binari e controllare se esistono nel database – RafaSashi

10

vorrei andare con una query come questa:

SELECT id, path, ISNULL(LOAD_FILE(path)) as not_exists 
FROM images 
HAVING not_exists = 1 

La funzione LOAD_FILE tenta di caricare il file come una stringa, e restituisce NULL quando non riesce.

Si prega di notare che un errore in questo caso potrebbe essere dovuto al fatto che mysql semplicemente non può leggere quella posizione specifica, anche se il file esiste realmente.

EDIT:

Come @ostrokach rilevare nei commenti, questo non è SQL standard, anche se MySQL permette, di seguire lo standard potrebbe essere:

SELECT * 
FROM images 
WHERE LOAD_FILE(PATH) IS NULL 
+0

Non riesco a far funzionare tutto questo per me stesso. Esistono infatti tutti i file restituiti. Cosa potrebbe significare che questa posizione locale non è leggibile da MySQL? http://stackoverflow.com/questions/27495830/retrieve-a-list-of-missing-files-from-field-using-mysql?noredirect=1#comment43423726_27495830 –

+0

Potrebbe essere che l'utente che esegue il daemon MySQL non può accedere al cartella (e) contenente questi file. –

+0

La parte 'HAVING not_exists = 1' è sbagliata, dal momento che non stai raggruppando per non_esiste. Se si desidera selezionare solo le righe per le quali esiste un file, è necessario fare qualcosa del tipo: 'ID SELECT, percorso FROM immagini WHERE LOAD_FILE (percorso) è NULL'; – ostrokach

0

Non è possibile utilizzare magazzino MySQL. Tuttavia è possibile scrivere UDF (funzione definita dall'utente), probabilmente in C, caricarlo usando l'istruzione CREATE FUNCTION e usarlo da MySQL come si farebbe con qualsiasi funzione incorporata.

+0

Per quello che so, le funzioni create su mysql usano solo SQL. –

+1

@MatteoTassinari Leggere le risorse collegate. È possibile creare "funzioni memorizzate" scritte in SQL ed è possibile creare "funzioni definite dall'utente" che vengono compilate in una libreria condivisa e caricate in fase di runtime. –

+0

Sembra che mi sia sbagliato allora, mi dispiace, e grazie per averlo indicato :) –

3

Il comando MySQL LOAD_FILE ha requisiti molto severi sui file che può aprire. Dai documenti MySQL:

[LOAD_FILE] Legge il file e restituisce il contenuto del file come una stringa. Per utilizzare questa funzione, il file deve trovarsi sull'host del server, è necessario specificare il nome percorso completo del file e si deve avere il privilegio FILE. Il file deve essere leggibile da tutti e la sua dimensione inferiore a max_allowed_packet byte. Se la variabile di sistema secure_file_priv è impostata su un nome di directory non vuoto, il file da caricare deve trovarsi in quella directory.

Quindi, se il file non può essere raggiunto dall'utente mysql o uno qualsiasi degli altri requisiti non sono soddisfatti, LOAD_FILE tornerà Null.


È possibile ottenere un elenco di ID che corrispondono ai file mancanti utilizzando awk:

 
mysql db_name --batch -s -e "SELECT id, path FROM images" \ 
    | awk '{if(system("[ -e " $2 " ]") == 1) {print $1}}' \ 
    >> missing_ids.txt 

o semplicemente usando bash:

 
mysql db_name --batch -s -e "SELECT id, path FROM images" \ 
    | while read id path ; if [[ -e "$path" ]] ; then echo $id ; done 
    >> missing_ids.txt 

Questo ha anche il vantaggio di essere molto più veloce di LOAD_FILE.

+0

Se il nome del file contiene una parentesi rotonda "()", questo comando genera errori. C'è un modo per aggirare questo in modo che possa gestire qualsiasi tipo di nome file? – CarstenSchmitz

+0

@CarstenSchmitz Ho aggiunto un esempio di utilizzo del ciclo while di bash. Potresti provare a usare quello. – ostrokach