Bao gồm các tiêu đề khi sử dụng SELECT INTO OUTFILE?


117

Có thể bao gồm các tiêu đề bằng cách nào đó khi sử dụng MySQL INTO OUTFILEkhông?

Câu trả lời:


166

Bạn sẽ phải tự mình viết mã những tiêu đề đó. Cái gì đó như:

SELECT 'ColName1', 'ColName2', 'ColName3'
UNION ALL
SELECT ColName1, ColName2, ColName3
    FROM YourTable
    INTO OUTFILE '/path/outfile'

14
Nhưng nó sẽ không hoạt động nếu có một ORDER BYtrong SELECTmệnh đề. Dòng tiêu đề có thể nằm ở bất kỳ đâu trong tệp được tạo tùy thuộc vào thứ tự.
COil

Xem một vài câu trả lời bên dưới để biết ý tưởng về cách sử dụng ORDER BY và cũng như câu trả lời của matt để biết cách nhanh chóng nhận được tất cả ColName1, ColName2, v.v. Các tiện ích bổ sung rất hữu ích cho câu trả lời tuyệt vời này!
Andrew T

1
Câu trả lời này có vẻ đúng, tôi thậm chí đã sử dụng nó gần như mù quáng trên máy chủ nhà phát triển của mình ... Nếu không có tiêu đề cột, mất khoảng 50 giây để kết xuất 240 triệu dòng. Với UNION ALL này, máy chủ đang gặp rắc rối lớn khi cố gắng tạo một bảng tạm thời trước khi kết xuất mọi thứ, đã hơn 10 phút rồi và vẫn đang chờ bảng tạm thời được ghi trên đĩa! Hãy nhận biết điều đó! Bạn chắc chắn muốn thêm tên cột theo cách khác, ngay cả khi nó có nghĩa là mở tệp sau đó bằng ngôn ngữ lập trình khác.
Salketer

Điều này dường như chỉ hoạt động nếu tất cả các cột của YourTable là một kiểu dữ liệu ký tự, điều này có ý nghĩa. Nếu không, bạn sẽ nhận được lỗi vô ích: "Các câu lệnh SELECT đã sử dụng có một số cột khác nhau".
TheBamf

1
Đây là một trong những lý do tại sao tôi đang xem xét chuyển sang một DBMS khác.
e18r

85

Giải pháp được cung cấp bởi Joe Steanelli có hiệu quả, nhưng việc tạo danh sách các cột là bất tiện khi hàng chục hoặc hàng trăm cột có liên quan. Đây là cách lấy danh sách cột của bảng my_table trong 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

Bây giờ bạn có thể sao chép và dán hàng kết quả làm câu lệnh đầu tiên trong phương thức của Joe.


2
Điều này trả về tất cả các cột được nối với nhau trong một trường. Tôi không thể kết hợp điều đó với một câu lệnh chọn khác trả về nhiều trường. Tuy nhiên, điều này thực sự hữu ích để lấy một dòng tôi có thể sao chép và dán làm tiêu đề của tệp outfile của tôi.
tmoore82

1
Ý tưởng là sao chép trường đơn kết quả và dán trường đó vào câu lệnh UNION của bạn thay vì nhập thủ công vào column1, column2, v.v. khi sử dụng phương pháp của Joe (câu trả lời được chấp nhận) để bạn có thể nhận được danh sách các cột nhanh hơn!
Andrew T

Tôi đang tìm cách xuất tất cả lược đồ bảng / trường của mình. Câu trả lời này kết hợp với câu trả lời được chấp nhận đã tạo ra một mẹo nhỏ!
Rémi Breton

@Chris ORDER BY ORDINAL_POSITIONxử lý điều đó
matt

1
ORDER BY ORDINAL_POSITION nên là một phần của GROUP_CONCAT () gọi, như trongGROUP_CONCAT(CONCAT('"',COLUMN_NAME,'"') order BY ORDINAL_POSITION)
Apuleius

15

Đối với lựa chọn phức tạp với ORDER BY, tôi sử dụng như sau:

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';

Giải pháp này hoạt động tốt khi đặt hàng truy vấn thứ hai (phức tạp); nếu bạn không làm theo cách này, bạn sẽ đặt hàng cột đầu tiên cũng không mong muốn. Đề xuất hay @evilguc!
Aaron

Không làm việc với tôi, sau khi làm UNION ALL thứ tự của cột id là điều sai lầm
Mohanad Kaleia

6

Bạn có thể sử dụng câu lệnh đã soạn sẵn với câu trả lời của lucek và xuất bảng động với tên cột trong 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;

Cảm ơn lucek.


6

Điều này sẽ cho bạn biết các cột có thứ tự và / hoặc một giới hạn

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
Chỉ cần lưu ý rằng bố cục truy vấn này cũng hoạt động đối với tôi trong MariaDB 10.1; các bố cục khác được đề xuất trong chủ đề này thì không.
Lập trình viên

Bật các tiêu đề trên dưới cùng đối với một số lý do, nhưng hoạt động tốt để bật mà lại trên đầu trang trong một ứng dụng bảng tính, lạ nhưng cổ vũ
Dmitri DB

Tôi cũng bị kẹt khi sử dụng mariaDB. với việc trích xuất chỉ 100 khách hàng tiềm năng, tốc độ này nhanh hơn 14 giây so với việc chạy câu trả lời được chấp nhận. Đầu tiên vượt qua với chấp nhận: Query OK, 100 rows affected (14.72 sec) Thứ hai vượt qua với bạnQuery OK, 101 rows affected (0.00 sec)
Casper Wilkes

6

Tôi chỉ cần thực hiện 2 truy vấn, đầu tiên để nhận kết quả truy vấn (giới hạn 1) với tên cột (không có mã cứng, không có vấn đề với Nối, Thứ tự theo, tên cột tùy chỉnh, v.v.) và thứ hai để tự tạo truy vấn và kết hợp các tệp thành một CSV tập tin:

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

5

Tôi gặp phải vấn đề tương tự khi thực hiện truy vấn mysql trên các bảng lớn trong NodeJS. Cách tiếp cận mà tôi đã làm theo để đưa tiêu đề vào tệp CSV của mình như sau

  1. Sử dụng truy vấn OUTFILE để chuẩn bị tệp không có tiêu đề

        SELECT * INTO OUTFILE [FILE_NAME] FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED 
        BY '\"' LINES TERMINATED BY '\n' FROM [TABLE_NAME]
  2. Tìm nạp tiêu đề cột cho bảng được sử dụng trong điểm 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. Nối các tiêu đề cột vào tệp được tạo ở bước 1 bằng cách thêm gói npm trước tệp

Việc thực thi từng bước được kiểm soát bằng các lời hứa trong NodeJS.


3

Đây là một cheat thay thế nếu bạn đã quen thuộc với Python hoặc R và bảng của bạn có thể vừa với bộ nhớ.

Nhập bảng SQL vào Python hoặc R và sau đó xuất từ ​​đó dưới dạng CSV và bạn sẽ nhận được tên cột cũng như dữ liệu.

Đây là cách tôi thực hiện bằng cách sử dụng R, yêu cầu thư viện 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')

Đó là một chút gian lận nhưng tôi thấy đây là một giải pháp nhanh chóng khi số lượng cột của tôi quá dài để sử dụng phương pháp concat ở trên. Lưu ý: R sẽ thêm cột 'row.names' ở đầu CSV, vì vậy bạn sẽ muốn bỏ cột đó nếu bạn cần dựa vào CSV để tạo lại bảng.


2

Vì vậy, nếu tất cả các cột trong my_tablelà kiểu dữ liệu ký tự , chúng ta có thể kết hợp các câu trả lời hàng đầu (của Joe, matt và evilguc) với nhau, để tự động thêm tiêu đề trong một truy vấn SQL 'đơn giản', ví dụ:

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';

trong đó vài dòng cuối cùng tạo ra csv.

Lưu ý rằng điều này có thể chậm nếu my_tablerất lớn.


nó có lỗi "Các câu lệnh SELECT đã sử dụng có một số cột khác nhau". Thưa ngài
Bowei Liu

1

Tôi nghĩ nếu bạn sử dụng UNION thì nó sẽ hoạt động:

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

Tôi không biết cách nào để chỉ định trực tiếp tiêu đề bằng cú pháp INTO OUTFILE.


1
UNION ALL sẽ an toàn hơn và nhanh hơn.
toxalot

1

Trên thực tế, bạn có thể làm cho nó hoạt động ngay cả với ORDER BY.

Chỉ cần một số thủ thuật theo thứ tự theo câu lệnh - chúng tôi sử dụng câu lệnh trường hợp và thay thế giá trị tiêu đề bằng một số giá trị khác được đảm bảo sắp xếp đầu tiên trong danh sách (rõ ràng điều này phụ thuộc vào loại trường và bạn đang sắp xếp ASC hay DESC)

Giả sử bạn có ba trường, name (varchar), is_active (bool), date_something_happens (date) và bạn muốn sắp xếp hai trường thứ hai giảm dần:

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

Vì chức năng 'bao gồm tiêu đề' dường như chưa được tích hợp sẵn và hầu hết các "giải pháp" ở đây cần phải nhập tên cột theo cách thủ công và / hoặc thậm chí không tính đến các liên kết, tôi khuyên bạn nên giải quyết vấn đề .

  • Giải pháp thay thế tốt nhất mà tôi tìm thấy cho đến nay là sử dụng một công cụ tốt (tôi sử dụng HeidiSQL ).
    Đặt yêu cầu của bạn, chọn lưới, chỉ cần nhấp chuột phải và xuất thành tệp. Nó có tất cả các tùy chọn cần thiết để xuất khẩu sạch sẽ, đáp ứng được hầu hết các nhu cầu.

  • Cùng ý tưởng, cách tiếp cận của user3037511 hoạt động tốt và có thể được tự động hóa dễ dàng .
    Chỉ cần khởi chạy yêu cầu của bạn bằng một số dòng lệnh để lấy tiêu đề của bạn. Bạn có thể lấy dữ liệu bằng CHỌN VÀO ĐẦU RA ... hoặc bằng cách chạy truy vấn không giới hạn, quyền chọn của bạn.

    Lưu ý rằng chuyển hướng đầu ra đến một tệp hoạt động giống như một sự quyến rũ trên cả Linux VÀ Windows.


Điều này khiến tôi muốn làm nổi bật rằng 80% thời gian, khi tôi muốn sử dụng CHỌN TỪ INFILE hoặc CHỌN VÀO OUTFILE, tôi lại sử dụng một thứ khác do một số hạn chế (ở đây, sự vắng mặt của 'tùy chọn tiêu đề', trên AWS-RDS, các quyền còn thiếu, v.v.)

Do đó, tôi không trả lời chính xác cho câu hỏi của op ... nhưng nó sẽ đáp ứng nhu cầu của anh ấy :)
EDIT: và để thực sự trả lời câu hỏi của anh ấy: không
Kể từ 2017-09-07, bạn chỉ không thể bao gồm tiêu đề nếu bạn dính với lệnh SELECT INTO OUTFILE
: |


1

một ví dụ từ cảm biến tên bảng cơ sở dữ liệu của tôi với các cột (id, thời gian, đơn vị)

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

Tôi đang viết mã của mình bằng PHP và gặp một chút khó khăn khi sử dụng các hàm concat và union, đồng thời cũng không sử dụng các biến SQL, bất kỳ cách nào tôi có thể làm cho nó hoạt động, đây là mã của tôi:

//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);

0

Đây là một cách để lấy động tiêu đề tiêu đề từ tên cột.

/* 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;

1
Tôi nên nói khá là một giải pháp. Thông qua nó cho mục đích của tôi. Cảm ơn!
Denis Kulagin

0

Tôi muốn thêm vào câu trả lời do Sangam Belose cung cấp. Đây là mã của anh ấy:

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

Tuy nhiên, nếu bạn chưa thiết lập "secure_file_priv"các biến bên trong, nó có thể không hoạt động. Đối với điều đó, hãy kiểm tra thư mục được đặt trên biến đó bằng cách:

SHOW VARIABLES LIKE "secure_file_priv"

Đầu ra sẽ như thế này:

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)

Bạn có thể thay đổi biến này hoặc thay đổi truy vấn để xuất tệp ra đường dẫn mặc định hiển thị.


0

MySQL một mình không đủ để làm điều này một cách đơn giản. Dưới đây là một tập lệnh PHP sẽ xuất các cột và dữ liệu sang CSV.

Nhập tên cơ sở dữ liệu của bạn và các bảng ở gần đầu.

<?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() );
}

?>

Bạn sẽ cần đây là thư mục mà bạn muốn xuất ra. MySQL cần có khả năng ghi vào thư mục.

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

Bạn có thể chỉnh sửa các tùy chọn xuất CSV trong truy vấn:

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

Ở cuối, có một lệnh gọi thực thi tới GZip CSV.


-1
CHỌN 'ColName1', 'ColName2', 'ColName3'
ĐOÀN KẾT TẤT CẢ
CHỌN ColName1, ColName2, ColName3
    TỪ YourTable
    INTO OUTFILE 'c: \\ datasheet.csv' CÁC LĨNH VỰC ĐƯỢC CHẤM DỨT BỞI ',' TÙY CHỌN ĐƯỢC CHO PHÉP BỞI '"' CÁC DÒNG ĐƯỢC CHẤM DỨT BỞI '\ n' 
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.