MySQL INTO OUTFILE
を使用するときに、何らかの方法でヘッダーを含めることは可能ですか?
これらのヘッダーを自分でハードコーディングする必要があります。何かのようなもの:
SELECT 'ColName1', 'ColName2', 'ColName3'
UNION ALL
SELECT ColName1, ColName2, ColName3
FROM YourTable
INTO OUTFILE '/path/outfile'
Joe Steanelliが提供するソリューションは機能しますが、列のリストを作成することは、数十または数百の列が関係する場合は不便です。以下は、テーブルの列リストを取得する方法ですmy_table in 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
これで、結果の行をコピーして、Joeのメソッドの最初のステートメントとして貼り付けることができます。
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';
単純に2つのクエリを作成します。1つ目は列名(ハードコードなし、結合、並べ替え、カスタム列名など)でクエリ出力(制限1)を取得し、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
これにより、列や制限を順序付けることができます
SELECT 'ColName1', 'ColName2', 'ColName3'
UNION ALL
SELECT * from (SELECT ColName1, ColName2, ColName3
FROM YourTable order by ColName1 limit 3) a
INTO OUTFILE '/path/outfile';
Lucekの回答で準備されたステートメントを使用し、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;
Lucekに感謝します。
NodeJSの大きなテーブルでmysqlクエリを実行しているときに、同様の問題に直面しました。 CSVファイルにヘッダーを含めるために従ったアプローチは次のとおりです。
OUTFILEクエリを使用して、ヘッダーのないファイルを準備します
SELECT * INTO OUTFILE [FILE_NAME] FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED
BY '\"' LINES TERMINATED BY '\n' FROM [TABLE_NAME]
ポイント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
prepend-file npm packageを使用して、手順1で作成したファイルに列ヘッダーを追加します
NodeJSのpromiseを使用して、各ステップの実行を制御しました。
これは、PythonまたはRに精通しており、テーブルがメモリに収まる場合の代替のチートです。
SQLテーブルをPythonまたはRにインポートし、そこからCSVとしてエクスポートすると、列名とデータが取得されます。
RMySQLライブラリを必要とするRを使用してそれを行う方法は次のとおりです:
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はCSVの先頭に「row.names」列を追加するので、CSVに依存してテーブルを再作成する必要がある場合は削除することをお勧めします。
my_table
のすべての列が文字データ型である場合、上位の回答(Joe、matt、evilgucによる)を組み合わせて、ヘッダーを1つに自動的に追加します '単純な」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
が非常に大きい場合、これは遅くなることに注意してください。
「include-headers」機能はまだ組み込まれていないようであり、ここでのほとんどの「ソリューション」は列名を手動で入力する必要があり、かつ/または結合を考慮に入れさえしないため、 問題を回避する。
これまでに見つけた最良の代替手段は、適切なツールを使用することです(HeidiSQLを使用します)。
リクエストを入力してグリッドを選択し、右クリックしてファイルにエクスポートします。クリーンなエクスポートに必要なすべてのオプションが用意されており、ほとんどのニーズに対応できます。
同じ考えで、user3037511のアプローチはうまく機能し、簡単に自動化にできます。
ヘッダーを取得するには、コマンドラインでリクエストを起動するだけです SELECT INTO OUTFILE ...を使用してデータを取得するか、制限なしにクエリを実行して、選択することができます。
ファイルへの出力リダイレクトは、LinuxとWindowsの両方で魅力のように機能することに注意してください。
これにより、80%の確率で、SELECT FROM INFILEまたはSELECT INTO OUTFILEを使用する場合、他の何かを使用することになりますいくつかの制限のために(ここでは、「ヘッダーオプション」が存在しない、AWS-RDSに存在しない、権利が欠落している、など)。
したがって、私は正確にopのquestionに答えません...しかし、彼のneeds:)
編集:そして彼の質問に実際に答えるために:no
2017-09-07現在、SELECT INTO OUTFILEコマンドを使用する場合、ヘッダーを含めることはできません:|
データベーステーブル名の例sensor with column(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
私は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);
Sangam Beloseが提供する回答に追加したいと思います。彼のコードは次のとおりです。
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)
この変数を変更するか、クエリを変更して、表示されているデフォルトのパスにファイルを出力できます。
MySQLだけでは、これを簡単に行うことはできません。以下は、列とデータをCSVに出力するPHPスクリプトです。
データベース名とテーブルを上部近くに入力します。
<?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"'
最後に、CSVのGZipへのexec呼び出しがあります。
実際、ORDER BYを使用しても機能させることができます。
Order byステートメントに若干の工夫が必要です-caseステートメントを使用して、ヘッダー値をリスト内で最初にソートされることが保証されている他の値に置き換えます(明らかに、これはフィールドのタイプとASCまたはDESC)
名前(varchar)、is_active(bool)、date_something_happens(date)の3つのフィールドがあり、2番目から2番目の降順でソートするとします。
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
UNIONを使用すれば機能すると思います。
select 'header 1', 'header 2', ...
union
select col1, col2, ... from ...
INTO OUTFILE構文でヘッダーを直接指定する方法がわかりません。
以下は、列名からヘッダータイトルを動的に取得する方法です。
/* 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;