Включить заголовки при использовании SELECT INTO OUTFILE?

117

Можно ли как-нибудь включить заголовки при использовании MySQL INTO OUTFILE?

Бретт
источник

Ответы:

166

Вам придется самостоятельно жестко закодировать эти заголовки. Что-то вроде:

SELECT 'ColName1', 'ColName2', 'ColName3'
UNION ALL
SELECT ColName1, ColName2, ColName3
    FROM YourTable
    INTO OUTFILE '/path/outfile'
Джо Стефанелли
источник
14
Но не получится, если ORDER BYв SELECTпункте есть. Строка заголовка может быть где угодно в сгенерированном файле в зависимости от порядка.
COil
См. Несколько ответов ниже для идей по использованию ORDER BY, а также ответ Мэтта о способе быстро получить все ColName1, ColName2 и т. Д. Очень полезные дополнения к этому замечательному ответу!
Эндрю Т
1
Этот ответ кажется правильным, черт возьми, я даже использовал его почти вслепую на своем сервере разработки ... Без заголовков столбцов требуется около 50 секунд, чтобы выгрузить 240 миллионов строк. С этим UNION ALL у сервера возникают большие проблемы, пытаясь создать временную таблицу перед сбросом всего, прошло уже более 10 минут, и он все еще ждет, когда временная таблица будет записана на диск! Помните об этом! Вы, безусловно, предпочли бы добавить имена столбцов другим способом, даже если это означает открытие файла на другом языке программирования.
Salketer
Это работает, только если все столбцы YourTable являются символьными типами данных, что имеет смысл. В противном случае вы получите бесполезную ошибку: «Используемые операторы SELECT имеют другое количество столбцов».
TheBamf 08
1
Это одна из причин, по которой я подумываю о переходе на другую СУБД.
e18r
85

Решение, предложенное Джо Стеанелли, работает, но создание списка столбцов неудобно, когда задействованы десятки или сотни столбцов. Вот как получить список столбцов таблицы my_table в my_schema .

-- override GROUP_CONCAT limit of 1024 characters to avoid a truncated result
set session group_concat_max_len = 1000000;

select GROUP_CONCAT(CONCAT("'",COLUMN_NAME,"'"))
from INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'my_table'
AND TABLE_SCHEMA = 'my_schema'
order BY ORDINAL_POSITION

Теперь вы можете скопировать и вставить полученную строку в качестве первого оператора в методе Джо.

матовый
источник
2
Это возвращает все столбцы, объединенные в одно поле. Я не могу объединить это с другим оператором select, который возвращает несколько полей. Однако это действительно полезно для получения строки, которую я могу скопировать и вставить в качестве заголовка моего файла Outfile.
tmoore82
1
Идея состоит в том, чтобы скопировать полученное одно поле и вставить его в оператор UNION вместо того, чтобы вручную вводить столбец 1, столбец 2 и т. Д. При использовании метода Джо (принятый ответ), чтобы вы могли быстрее получить список столбцов!
Эндрю Т
Я хотел экспортировать всю мою схему таблиц / полей. Этот ответ в сочетании с принятым сделали свое дело!
Реми Бретон,
@ Крис ORDER BY ORDINAL_POSITIONручки , которые
матовый
1
ORDER BY ORDINAL_POSITION должен быть частью вызова GROUP_CONCAT (), как вGROUP_CONCAT(CONCAT('"',COLUMN_NAME,'"') order BY ORDINAL_POSITION)
Апулей,
15

Для сложного выбора с ORDER BY я использую следующее:

SELECT * FROM (
    SELECT 'Column name #1', 'Column name #2', 'Column name ##'
    UNION ALL
    (
        // complex SELECT statement with WHERE, ORDER BY, GROUP BY etc.
    )
) resulting_set
INTO OUTFILE '/path/to/file';
evilguc
источник
Это решение хорошо работает при заказе второго (сложного) запроса; если вы этого не сделаете, вы закончите заказывать и первый столбец, что нежелательно. Хорошее предложение @evilguc!
Аарон
У меня не сработало, после выполнения UNION ALL порядок столбцов id был перепутан
Моханад Калея
6

Вы можете использовать подготовленный оператор с ответом Лучека и динамически экспортировать таблицу с именем столбца в CSV:

--If your table has too many columns
SET GLOBAL group_concat_max_len = 100000000;
--Prepared statement
SET @SQL = ( select CONCAT('SELECT * INTO OUTFILE \'YOUR_PATH\' FIELDS TERMINATED BY \',\' OPTIONALLY ENCLOSED BY \'"\' ESCAPED BY \'\' LINES TERMINATED BY \'\\n\' FROM (SELECT ', GROUP_CONCAT(CONCAT("'",COLUMN_NAME,"'")),' UNION select * from YOUR_TABLE) as tmp') from INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'YOUR_TABLE' AND TABLE_SCHEMA = 'YOUR_SCHEMA' order BY ORDINAL_POSITION );
--Execute it
PREPARE stmt FROM @SQL;
EXECUTE stmt;

Спасибо лучек.

Vrag
источник
6

Это позволит вам иметь упорядоченные столбцы и / или ограничение

SELECT 'ColName1', 'ColName2', 'ColName3'
UNION ALL
SELECT * from (SELECT ColName1, ColName2, ColName3
    FROM YourTable order by ColName1 limit 3) a
    INTO OUTFILE '/path/outfile';
Дональд Вагнер
источник
1
Замечу, что этот макет запроса работал у меня и в MariaDB 10.1; другие макеты, предложенные в этой ветке, не сделали.
ProgrammerDan
По какой-то причине выскакивает заголовок внизу, но отлично работает, чтобы вернуть его вверх в приложении для работы с электронными таблицами, странно, но радует
Дмитрий ДБ
Я тоже застрял в использовании mariaDB. при извлечении всего 100 отведений это было на 14 секунд быстрее, чем выполнение принятого ответа. Первый проход с принятым: Query OK, 100 rows affected (14.72 sec) Второй проход с вашимQuery OK, 101 rows affected (0.00 sec)
Каспер Уилкс
6

Я просто делаю 2 запроса, первый для получения вывода запроса (ограничение 1) с именами столбцов (без жесткого кода, без проблем с объединениями, упорядочиванием, именами пользовательских столбцов и т. Д.), А второй для создания самого запроса и объединения файлов в один CSV файл:

CSVHEAD=`/usr/bin/mysql $CONNECTION_STRING -e "$QUERY limit 1;"|head -n1|xargs|sed -e "s/ /'\;'/g"`
echo "\'$CSVHEAD\'" > $TMP/head.txt
/usr/bin/mysql $CONNECTION_STRING -e "$QUERY into outfile '${TMP}/data.txt' fields terminated by ';' optionally enclosed by '\"' escaped by '' lines terminated by '\r\n';"
cat $TMP/head.txt $TMP/data.txt > $TMP/data.csv
user3037511
источник
5

Я столкнулся с аналогичной проблемой при выполнении запроса mysql для больших таблиц в NodeJS. Подход, который я использовал для включения заголовков в свой CSV-файл, выглядит следующим образом.

  1. Используйте запрос OUTFILE для подготовки файла без заголовков

        SELECT * INTO OUTFILE [FILE_NAME] FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED 
        BY '\"' LINES TERMINATED BY '\n' FROM [TABLE_NAME]
  2. Получить заголовки столбцов для таблицы, использованной в пункте 1

        select GROUP_CONCAT(CONCAT(\"\",COLUMN_NAME,\"\")) as col_names from 
        INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = [TABLE_NAME] AND TABLE_SCHEMA 
        = [DATABASE_NAME] ORDER BY ORDINAL_POSITION
  3. Добавьте заголовки столбцов в файл, созданный на шаге 1, с помощью пакета npm prepend-file

Выполнение каждого шага контролировалось с помощью обещаний в NodeJS.

рахул шукла
источник
3

Это альтернативный чит, если вы знакомы с Python или R, и ваша таблица может поместиться в памяти.

Импортируйте таблицу SQL в Python или R, а затем экспортируйте оттуда как CSV, и вы получите имена столбцов, а также данные.

Вот как я это делаю с помощью R, требует библиотеки RMySQL:

db <- dbConnect(MySQL(), user='user', password='password', dbname='myschema', host='localhost')

query <- dbSendQuery(db, "select * from mytable")
dataset <- fetch(query, n=-1)

write.csv(dataset, 'mytable_backup.csv')

Это немного обман, но я обнаружил, что это быстрое решение, когда мое количество столбцов было слишком большим для использования метода concat, описанного выше. Примечание: R добавит столбец «row.names» в начало CSV, поэтому вы захотите удалить его, если вам действительно нужно полагаться на CSV для воссоздания таблицы.

Соединение точек
источник
2

Итак, если все столбцы my_tableявляются символьными данными , мы можем объединить главные ответы (Джо, Мэтт и Злогук) вместе, чтобы автоматически добавить заголовок в один «простой» SQL-запрос, например

select * from (
  (select column_name
    from information_schema.columns
    where table_name = 'my_table'
    and table_schema = 'my_schema'
    order by ordinal_position)
  union all
  (select *  // potentially complex SELECT statement with WHERE, ORDER BY, GROUP BY etc.
  from my_table)) as tbl
into outfile '/path/outfile'
fields terminated by ',' optionally enclosed by '"' escaped by '\\'
lines terminated by '\n';

где последняя пара строк делает вывод csv.

Обратите внимание, что это может быть медленным, если my_tableоно очень большое.

TheBamf
источник
он содержит ошибку «Используемые операторы SELECT имеют другое количество столбцов». Сэр
Бовей Лю
1

Я думаю, если вы воспользуетесь UNION, он будет работать:

select 'header 1', 'header 2', ...
union
select col1, col2, ... from ...

Я не знаю, как напрямую указать заголовки с синтаксисом INTO OUTFILE.

Пол В
источник
1
UNION ALL будет безопаснее и быстрее.
toxalot
1

На самом деле вы можете заставить его работать даже с ORDER BY.

Просто нужна хитрость в операторе order by - мы используем оператор case и заменяем значение заголовка некоторым другим значением, которое гарантированно будет отсортировано первым в списке (очевидно, это зависит от типа поля и от того, сортируете ли вы ASC или DESC)

Допустим, у вас есть три поля, name (varchar), is_active (bool), date_something_happens (date), и вы хотите отсортировать вторые два по убыванию:

select 
        'name'
      , 'is_active' as is_active
      , date_something_happens as 'date_something_happens'

 union all

 select name, is_active, date_something_happens

 from
    my_table

 order by
     (case is_active when 'is_active' then 0 else is_active end) desc
   , (case date when 'date' then '9999-12-30' else date end) desc
Саймон Вульф
источник
1

Поскольку функция 'include-headers', похоже, еще не встроена, и для большинства «решений» здесь необходимо вводить имена столбцов вручную и / или даже не принимать во внимание объединения, я бы рекомендовал обойти проблему .

  • Лучшая альтернатива, которую я нашел до сих пор, - это использование приличного инструмента (я использую HeidiSQL ).
    Поместите свой запрос, выберите сетку, щелкните правой кнопкой мыши и экспортируйте в файл. В нем есть все необходимые параметры для чистого экспорта, и он должен удовлетворить большинство потребностей.

  • По той же идее подход user3037511 работает нормально и может быть легко автоматизирован .
    Просто запустите свой запрос с помощью командной строки чтобы получить заголовки. Вы можете получить данные с помощью SELECT INTO OUTFILE ... или выполнив свой запрос без ограничений, на ваш выбор.

    Обратите внимание, что перенаправление вывода в файл работает как шарм как в Linux, так и в Windows.


Это заставляет меня подчеркнуть, что в 80% случаев, когда я хочу использовать SELECT FROM INFILE или SELECT INTO OUTFILE, я в конечном итоге использую что-то еще из-за некоторых ограничений (здесь отсутствие параметров заголовков '' на AWS-RDS, отсутствующие права и т. д.)

Следовательно, я не совсем отвечаю на вопрос оператора ... но он должен отвечать его потребностям :)
РЕДАКТИРОВАТЬ: и на самом деле ответить на его вопрос: нет.
По состоянию на 2017-09-07 вы просто не можете включать заголовки, если вы придерживайтесь команды SELECT INTO OUTFILE
: |

Balmipour
источник
1

пример из моего датчика имени таблицы базы данных с столбцами (id, time, unit)

select ('id') as id, ('time') as time, ('unit') as unit
UNION ALL
SELECT * INTO OUTFILE 'C:/Users/User/Downloads/data.csv'
  FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
  LINES TERMINATED BY '\n'
  FROM sensor
Даянанд СК
источник
0

Я писал свой код на PHP, и у меня были небольшие проблемы с использованием функций concat и union, а также я не использовал переменные SQL, какими бы способами я ни заставил их работать, вот мой код:

//first I connected to the information_scheme DB

$headercon=mysqli_connect("localhost", "USERNAME", "PASSWORD", "information_schema");

//took the healders out in a string (I could not get the concat function to work, so I wrote a loop for it)

    $headers = '';
    $sql = "SELECT column_name AS columns FROM `COLUMNS` WHERE table_schema = 'YOUR_DB_NAME' AND table_name = 'YOUR_TABLE_NAME'";
    $result = $headercon->query($sql);
    while($row = $result->fetch_row())
    {
        $headers = $headers . "'" . $row[0] . "', ";
    }
$headers = substr("$headers", 0, -2);

// connect to the DB of interest

$con=mysqli_connect("localhost", "USERNAME", "PASSWORD", "YOUR_DB_NAME");

// export the results to csv
$sql4 = "SELECT $headers UNION SELECT * FROM YOUR_TABLE_NAME WHERE ... INTO OUTFILE '/output.csv' FIELDS TERMINATED BY ','";
$result4 = $con->query($sql4);
user5671922
источник
0

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

/* Change table_name and database_name */
SET @table_name = 'table_name';
SET @table_schema = 'database_name';
SET @default_group_concat_max_len = (SELECT @@group_concat_max_len);

/* Sets Group Concat Max Limit larger for tables with a lot of columns */
SET SESSION group_concat_max_len = 1000000;

SET @col_names = (
  SELECT GROUP_CONCAT(QUOTE(`column_name`)) AS columns
  FROM information_schema.columns
  WHERE table_schema = @table_schema
  AND table_name = @table_name);

SET @cols = CONCAT('(SELECT ', @col_names, ')');

SET @query = CONCAT('(SELECT * FROM ', @table_schema, '.', @table_name,
  ' INTO OUTFILE \'/tmp/your_csv_file.csv\'
  FIELDS ENCLOSED BY \'\\\'\' TERMINATED BY \'\t\' ESCAPED BY \'\'
  LINES TERMINATED BY \'\n\')');

/* Concatenates column names to query */
SET @sql = CONCAT(@cols, ' UNION ALL ', @query);

/* Resets Group Contact Max Limit back to original value */
SET SESSION group_concat_max_len = @default_group_concat_max_len;

PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
RNickMcCandless
источник
1
Должен сказать, вполне подходящее решение. Принял его для своих целей. Спасибо!
Денис Кулагин
0

Я хотел бы дополнить ответ Сангама Белозе. Вот его код:

select ('id') as id, ('time') as time, ('unit') as unit
UNION ALL
SELECT * INTO OUTFILE 'C:/Users/User/Downloads/data.csv'
  FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
  LINES TERMINATED BY '\n'
  FROM sensor

Однако, если вы не настроили свои "secure_file_priv"переменные, это может не сработать. Для этого проверьте папку, установленную для этой переменной:

SHOW VARIABLES LIKE "secure_file_priv"

Результат должен выглядеть так:

mysql> show variables like "%secure_file_priv%";
+------------------+------------------------------------------------+
| Variable_name    | Value                                          |
+------------------+------------------------------------------------+
| secure_file_priv | C:\ProgramData\MySQL\MySQL Server 8.0\Uploads\ |
+------------------+------------------------------------------------+
1 row in set, 1 warning (0.00 sec)

Вы можете изменить эту переменную или изменить запрос, чтобы выводить файл по указанному по умолчанию пути.

RGregg
источник
0

Для этого недостаточно только MySQL. Ниже приведен сценарий PHP, который выводит столбцы и данные в CSV.

Введите название своей базы данных и таблицы вверху.

<?php

set_time_limit( 24192000 );
ini_set( 'memory_limit', '-1' );
setlocale( LC_CTYPE, 'en_US.UTF-8' );
mb_regex_encoding( 'UTF-8' );

$dbn = 'DB_NAME';
$tbls = array(
'TABLE1',
'TABLE2',
'TABLE3'
);

$db = new PDO( 'mysql:host=localhost;dbname=' . $dbn . ';charset=UTF8', 'root', 'pass' );

foreach( $tbls as $tbl )
{
    echo $tbl . "\n";
    $path = '/var/lib/mysql/' . $tbl . '.csv';

    $colStr = '';
    $cols = $db->query( 'SELECT COLUMN_NAME AS `column` FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = "' . $tbl . '" AND TABLE_SCHEMA = "' . $dbn . '"' )->fetchAll( PDO::FETCH_COLUMN );
    foreach( $cols as $col )
    {
        if( $colStr ) $colStr .= ', ';
        $colStr .= '"' . $col . '"';
    }

    $db->query(
    'SELECT *
    FROM
    (
        SELECT ' . $colStr . '
        UNION ALL
        SELECT * FROM ' . $tbl . '
    ) AS sub
    INTO OUTFILE "' . $path . '"
    FIELDS TERMINATED BY ","
    ENCLOSED BY "\""
    LINES TERMINATED BY "\n"'
    );

    exec( 'gzip ' . $path );

    print_r( $db->errorInfo() );
}

?>

Вам нужно, чтобы это был каталог, в который вы хотите выводить данные. MySQL должен иметь возможность писать в каталог.

$path = '/var/lib/mysql/' . $tbl . '.csv';

Вы можете изменить параметры экспорта CSV в запросе:

INTO OUTFILE "' . $path . '"
FIELDS TERMINATED BY ","
ENCLOSED BY "\""
LINES TERMINATED BY "\n"'

В конце есть вызов exec для GZip CSV.

Коджа Бриз
источник
-1
ВЫБЕРИТЕ 'ColName1', 'ColName2', 'ColName3'
СОЮЗ ВСЕ
ВЫБЕРИТЕ ColName1, ColName2, ColName3
    ОТ YourTable
    INTO OUTFILE 'c: \\ datasheet.csv' ПОЛЯ, ЗАКОНЧЕННЫЕ ',' ДОПОЛНИТЕЛЬНО ЗАКЛЮЧЕНЫ '"' СТРОКИ, ЗАКЛЮЧЕННЫЕ '\ n' 
Манодж Сингх
источник