#mysql #bash #csv #mysqldump #text-parsing
#bash #csv #mysql #синтаксический анализ текста
Вопрос:
Я пытаюсь написать скрипт bash, который, учитывая имя локальной базы данных MySQL, экспортирует данные из всех своих таблиц в CSV-файлы со строкой заголовка, содержащей имена полей. Например, если в базе данных есть таблицы customers
, orders
и inventory
, я хочу создать дамп трех файлов customers.csv
, orders.csv
и inventory.csv
, включая имена полей в заголовках каждого файла.
Поработав с mysqldump, мне удалось создать все нужные мне csv-файлы, но без строки заголовка имени поля. Команда также создает набор файлов .sql, содержащих только структуру таблицы, в командах SQL. После долгих поисков в Google я не могу найти никого, кто смог бы решить эту проблему без «изобретения колеса» и написания собственного скрипта дампа MySQL. mysqldump великолепен, ему просто не хватает этой маленькой функции. И все нужные мне имена полей находятся прямо в этих файлах SQL, нужно просто разобрать их и добавить строку с именами полей к каждому файлу CSV, верно?
Моя проблема: я новичок в написании сценариев оболочки, и я понятия не имею, как это сделать.
Вот команда mysqldump, которую я сейчас использую:
mysqldump --host=localhost --user=myusername --password=mypassword
--tab=/tmp/db/ --verbose mydatabase
--fields-enclosed-by=" --fields-terminated-by=,
допустим, база данных mydatabase содержит таблицы customers
orders
и inventory
. Эта команда создаст шесть файлов в каталоге / tmp / db: customers.sql
, customers.txt
, orders.sql
, orders.txt
inventory.sql
, inventory.txt
,,,,,,,,,,,,,. (текстовые файлы — это файлы CSV, позже мой скрипт изменит расширение файла на .csv)
Файлы .sql выглядят следующим образом (используя клиентов в качестве примера):
-- MySQL dump 10.13 Distrib 5.1.54, for debian-linux-gnu (i686)
--
-- Host: localhost Database: mydatabase
-- ------------------------------------------------------
-- Server version 5.1.54-1ubuntu4
/* (i removed some generated comments here) */;
--
-- Table structure for table `customers`
--
DROP TABLE IF EXISTS `customers`;
/* (i removed some generated comments here) */;
CREATE TABLE `customers` (
`customer_id` int(11) NOT NULL AUTO_INCREMENT,
`first_name` varchar(256) NOT NULL,
`last_name` varchar(256) NOT NULL,
`email` varchar(256) NOT NULL,
`phone` varchar(20) NOT NULL,
`notes` longtext NOT NULL,
PRIMARY KEY (`customer_id`)
) ENGINE=MyISAM AUTO_INCREMENT=1865 DEFAULT CHARSET=latin1;
/* (i removed some generated comments here) */;
-- Dump completed on 2011-05-01 13:03:02
и файлы .txt выглядят так, как вы ожидаете от CSV (строки «data», «like», «this»), но без заголовков имен полей.
Как вы можете видеть, нужные мне имена полей находятся прямо в файлах .sql после «СОЗДАТЬ ТАБЛИЦУ …».
Идеальный скрипт, который я пытаюсь написать, должен выполнять следующее:
- запустите команду mysqldump, которую я подробно описал выше.
- перебирайте все файлы, соответствующие /tmp /db / *.sql, и для каждого:
- проанализируйте имена полей и сгенерируйте «строку», «из», «их», «нравится», «это»
- в соответствующем файле .txt вставьте строку имен полей перед первой строкой.
- переименуйте все файлы .txt в .csv и удалите все файлы .sql.
Какие-нибудь советы? Я буду возиться с этим весь день, пока не разберусь.
Ответ №1:
Я провел простой тест под Windows.
create database if not exists test;
use test;
create table csv_header(
id int not null auto_increment primary key,
fname varchar(50),
lname varchar(50),
dob date)
engine = myisam;
insert into csv_header (fname,lname,dob) values
('nick','smith','2000-12-05'),
('john','white','1990-12-05');
set @str = (select concat("select * from (select ", group_concat(concat("'",column_name,"'"))," union
select * from ", table_name, ") as t into outfile 'd:/",table_name,".txt'
fields terminated by ','
lines terminated by 'rn'")
from information_schema.columns
where table_schema = 'test' and table_name = 'csv_header'
order by ordinal_position);
-- select @str;
prepare stmt from @str;
execute stmt;
deallocate prepare stmt;
И это содержимое моего csv_header.txt:
id,fname,lname,dob
1,nick,smith,2000-12-05
2,john,white,1990-12-05
Если это то, что вы ищете, то просто создать хранимую процедуру с курсором, которая перебирает все таблицы в схеме и делает то же самое для каждой из них. Дайте мне знать. 🙂
Ответ №2:
Я не смог найти способ сделать это, учитывая, что:
- мой сервер БД — это удаленный компьютер с
- нет NFS
- ни возможности записи в общий ресурс на моем локальном сервере.
Я создал стандартный SQL-дамп и преобразовал grep-файл в формат CSV.
Ответ №3:
set group_concat_max_len = 5000;
set @qry = (select concat("select ",group_concat(CONCAT('''', column_name, '''' ) ), " UNION SELECT * FROM " ,table_name, ' INTO OUTFILE ', " '/tmp/test.csv' FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' ESCAPED BY '"' LINES TERMINATED BY '\n' " ) from information_schema.columns where table_schema = database() and table_name = 'spree_users');
prepare stmt from @qry;
execute stmt;
deallocate prepare stmt;