Kode PHP untuk mengonversi kueri MySQL ke CSV [ditutup]

128

Apa cara paling efisien untuk mengonversi kueri MySQL ke CSV di PHP?

Akan lebih baik untuk menghindari file temp karena ini mengurangi portabilitas (jalur dir dan pengaturan izin sistem file diperlukan).

CSV juga harus menyertakan satu baris teratas nama bidang.

Reilly Beacom
sumber
73
Mengapa pertanyaan ini ditutup tidak konstruktif? Yang ini bagus dan sangat jelas.
14
@Alec Karena beberapa moderator di sini adalah supermoderator, Anda tahu ... "Dengan kekuatan super datang tanggung jawab besar!" - Paman Ben
finitenessofinfinity
18
@finitenessofinfinity daya rusak, daya absolut rusak mutlak. Stackoverflow adalah contoh yang bagus untuk itu.
16
Saya memberikan suara untuk membuka kembali pertanyaan ini!
TN888
9
Enam bulan kemudian dan saya menggunakan jawaban untuk ini di situs web saya. Bisakah ini dibuka kembali?
Jon

Jawaban:

138
SELECT * INTO OUTFILE "c:/mydata.csv"
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
LINES TERMINATED BY "\n"
FROM my_table;

( dokumentasi untuk ini ada di sini: http://dev.mysql.com/doc/refman/5.0/en/select.html )

atau:

$select = "SELECT * FROM table_name";

$export = mysql_query ( $select ) or die ( "Sql error : " . mysql_error( ) );

$fields = mysql_num_fields ( $export );

for ( $i = 0; $i < $fields; $i++ )
{
    $header .= mysql_field_name( $export , $i ) . "\t";
}

while( $row = mysql_fetch_row( $export ) )
{
    $line = '';
    foreach( $row as $value )
    {                                            
        if ( ( !isset( $value ) ) || ( $value == "" ) )
        {
            $value = "\t";
        }
        else
        {
            $value = str_replace( '"' , '""' , $value );
            $value = '"' . $value . '"' . "\t";
        }
        $line .= $value;
    }
    $data .= trim( $line ) . "\n";
}
$data = str_replace( "\r" , "" , $data );

if ( $data == "" )
{
    $data = "\n(0) Records Found!\n";                        
}

header("Content-type: application/octet-stream");
header("Content-Disposition: attachment; filename=your_desired_name.xls");
header("Pragma: no-cache");
header("Expires: 0");
print "$header\n$data";
Geoff
sumber
5
secara teknis, ini terpisah;)
John Douthat
5
Perhatikan penggunaan garis miring maju dengan SELECT INTO OUTFILEgenap pada Windows.
Johan
1
Hai ini berfungsi dengan baik untuk format xls tetapi Jika saya mencoba menyimpan sebagai file CSV itu menunjukkan semua hasil dalam 1 kolom. Saya ingin menyimpan ini sebagai file csv.
vinod reddy
Di antara dua di atas mana yang lebih baik, lebih aman dan mengapa?
Chella
1
Saya cenderung menyarankan opsi kedua lebih aman karena `SELECT INTO OUTFILE mengharuskan pengguna mysql memiliki akses ke sistem file untuk mengubah file yang berpotensi risiko besar.
Jeepstone
91

Lihatlah pertanyaan / jawaban ini . Ini lebih ringkas daripada @ Geoff, dan juga menggunakan fungsi fputcsv bawaan.

$result = $db_con->query('SELECT * FROM `some_table`');
if (!$result) die('Couldn\'t fetch records');
$num_fields = mysql_num_fields($result);
$headers = array();
for ($i = 0; $i < $num_fields; $i++) {
    $headers[] = mysql_field_name($result , $i);
}
$fp = fopen('php://output', 'w');
if ($fp && $result) {
    header('Content-Type: text/csv');
    header('Content-Disposition: attachment; filename="export.csv"');
    header('Pragma: no-cache');
    header('Expires: 0');
    fputcsv($fp, $headers);
    while ($row = $result->fetch_array(MYSQLI_NUM)) {
        fputcsv($fp, array_values($row));
    }
    die;
}
Jrgns
sumber
1
Milik Anda tidak memiliki tajuk kolom.
Paolo Bergantino
15
Jika ada orang yang sebodoh saya, jangan ganti php://outputdengan nama file yang sebenarnya atau coba tutup dengan fclosedi akhir: itu bukan file asli, hanya alias untuk aliran output. Bagaimanapun jawaban ini bekerja dengan sempurna untuk saya, terima kasih Jrgns!
J.Steve
@ J.Steve My kesenangan :)
Jrgns
10
Menggunakan mysqli: gist.github.com/jaredrummler/2bfcf48b48d3fefd50c2
Jared Rummler
1
mysql_num_fields () tidak berfungsi untuk saya dan tajuk tidak dibuat. Apakah fungsi ini sudah usang atau semacamnya?
Doug
20

Lihatlah dokumentasi tentang sintaks SELECT ... INTO OUTFILE.

SELECT a,b,a+b INTO OUTFILE '/tmp/result.txt'
  FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
  LINES TERMINATED BY '\n'
  FROM test_table;
nickf
sumber
18

Pembaruan untuk @jrgns (dengan beberapa perbedaan sintaksis sedikit) solusi.

$result = mysql_query('SELECT * FROM `some_table`'); 
if (!$result) die('Couldn\'t fetch records'); 
$num_fields = mysql_num_fields($result); 
$headers = array(); 
for ($i = 0; $i < $num_fields; $i++) 
{     
       $headers[] = mysql_field_name($result , $i); 
} 
$fp = fopen('php://output', 'w'); 
if ($fp && $result) 
{     
       header('Content-Type: text/csv');
       header('Content-Disposition: attachment; filename="export.csv"');
       header('Pragma: no-cache');    
       header('Expires: 0');
       fputcsv($fp, $headers); 
       while ($row = mysql_fetch_row($result)) 
       {
          fputcsv($fp, array_values($row)); 
       }
die; 
} 
John M
sumber
Untuk beberapa alasan $ fp mengembalikan false kepada saya.
Volatil3
Untuk MySQL modern, Anda dapat menggunakan: $ header [] = mysqli_fetch_field_direct ($ result, $ i) -> name;
Ben di CA
Dan ubah fungsi mysql_ lainnya menjadi fungsi mysqli_.
Ben di CA
6

Jika Anda ingin agar unduhan ditawarkan sebagai unduhan yang dapat dibuka langsung di Excel, ini dapat bekerja untuk Anda: (disalin dari proyek lama saya yang belum dirilis)

Fungsi-fungsi ini mengatur header:

function setExcelContentType() {
    if(headers_sent())
        return false;

    header('Content-type: application/vnd.ms-excel');
    return true;
}

function setDownloadAsHeader($filename) {
    if(headers_sent())
        return false;

    header('Content-disposition: attachment; filename=' . $filename);
    return true;
}

Yang ini mengirimkan CSV ke aliran menggunakan hasil mysql

function csvFromResult($stream, $result, $showColumnHeaders = true) {
    if($showColumnHeaders) {
        $columnHeaders = array();
        $nfields = mysql_num_fields($result);
        for($i = 0; $i < $nfields; $i++) {
            $field = mysql_fetch_field($result, $i);
            $columnHeaders[] = $field->name;
        }
        fputcsv($stream, $columnHeaders);
    }

    $nrows = 0;
    while($row = mysql_fetch_row($result)) {
        fputcsv($stream, $row);
        $nrows++;
    }

    return $nrows;
}

Yang ini menggunakan fungsi di atas untuk menulis CSV ke file, diberikan oleh $ filename

function csvFileFromResult($filename, $result, $showColumnHeaders = true) {
    $fp = fopen($filename, 'w');
    $rc = csvFromResult($fp, $result, $showColumnHeaders);
    fclose($fp);
    return $rc;
}

Dan di sinilah keajaiban terjadi;)

function csvToExcelDownloadFromResult($result, $showColumnHeaders = true, $asFilename = 'data.csv') {
    setExcelContentType();
    setDownloadAsHeader($asFilename);
    return csvFileFromResult('php://output', $result, $showColumnHeaders);
}

Sebagai contoh:

$result = mysql_query("SELECT foo, bar, shazbot FROM baz WHERE boo = 'foo'");
csvToExcelDownloadFromResult($result);
John Douthat
sumber
1
Terima kasih john, kode yang sangat berguna. Harus memodifikasi garis untuk fungsi csvFromResult. alih-alih while ($ row = mysql_fetch_row ($ result)) {fputcsv ($ stream, $ row); $ rows ++; }, saya harus menggunakan while ($ row = mysql_fetch_row ($ result)) {$ data [] = $ row; // fputcsv ($ stream, $ row); // $ rows ++; } foreach ($ data as $ d) {fputcsv ($ stream, $ d); }. terima kasih lagi untuk kode yang luar biasa.
codingbbq
3
// Export to CSV
if($_GET['action'] == 'export') {

  $rsSearchResults = mysql_query($sql, $db) or die(mysql_error());

  $out = '';
  $fields = mysql_list_fields('database','table',$db);
  $columns = mysql_num_fields($fields);

  // Put the name of all fields
  for ($i = 0; $i < $columns; $i++) {
    $l=mysql_field_name($fields, $i);
    $out .= '"'.$l.'",';
  }
  $out .="\n";

  // Add all values in the table
  while ($l = mysql_fetch_array($rsSearchResults)) {
    for ($i = 0; $i < $columns; $i++) {
      $out .='"'.$l["$i"].'",';
    }
    $out .="\n";
  }
  // Output to browser with appropriate mime type, you choose ;)
  header("Content-type: text/x-csv");
  //header("Content-type: text/csv");
  //header("Content-type: application/csv");
  header("Content-Disposition: attachment; filename=search_results.csv");
  echo $out;
  exit;
}
Wayne
sumber