Skip to main content

PHP code to convert a MySQL query to CSV [closed]



What is the most efficient way to convert a MySQL query to CSV in PHP please?





It would be best to avoid temp files as this reduces portability (dir paths and setting file-system permissions required).





The CSV should also include one top line of field names.


Comments

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


    (the documentation for this is here: http://dev.mysql.com/doc/refman/5.0/en/select.html)

    or:

    $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";

    ReplyDelete
  2. Check out this question / answer. It's more concise than @Geoff's, and also uses the builtin fputcsv function.

    $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;
    }

    ReplyDelete
  3. Look at the documentation regarding the SELECT ... INTO OUTFILE syntax.

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

    ReplyDelete
  4. If you'd like the download to be offered as a download that can be opened directly in Excel, this may work for you: (copied from an old unreleased project of mine)

    These functions setup the headers:

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


    This one sends a CSV to a stream using a mysql result

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


    This one uses the above function to write a CSV to a file, given by $filename

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


    And this is where the magic happens ;)

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


    For example:

    $result = mysql_query("SELECT foo, bar, shazbot FROM baz WHERE boo = 'foo'");
    csvToExcelDownloadFromResult($result);

    ReplyDelete
  5. // 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;
    }

    ReplyDelete
  6. By the way, I realise I am replying about a year late to RonP's question, but it has not been answered yet, and others who found this page via Google, like me, may appreciate an answer.

    In reply to RonP's question, if you want each $row output on a separate line, you need to add the line breaks in somewhere. From memory I think these are one of two options:

    \n or \r\n

    The reason for the confusion is that \r\n should work on windows, but linux line breaks are slightly different, and I'm guessing it was \n, but could be wrong. google it! :)

    **Edit: See this for more info on linebreaks: PHP Echo Line Breaks

    From briefly looking at the code, you should replace the following line in csvFromResult():

    fputcsv($stream, $row);


    with:

    fputcsv($stream, $row."\r\n");


    If I'm wrong, please correct me :)

    ReplyDelete
  7. An update to @jrgns (with some slight syntax differences) solution.

    $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;
    }

    ReplyDelete

Post a Comment

Popular posts from this blog

Why is this Javascript much *slower* than its jQuery equivalent?

I have a HTML list of about 500 items and a "filter" box above it. I started by using jQuery to filter the list when I typed a letter (timing code added later): $('#filter').keyup( function() { var jqStart = (new Date).getTime(); var search = $(this).val().toLowerCase(); var $list = $('ul.ablist > li'); $list.each( function() { if ( $(this).text().toLowerCase().indexOf(search) === -1 ) $(this).hide(); else $(this).show(); } ); console.log('Time: ' + ((new Date).getTime() - jqStart)); } ); However, there was a couple of seconds delay after typing each letter (particularly the first letter). So I thought it may be slightly quicker if I used plain Javascript (I read recently that jQuery's each function is particularly slow). Here's my JS equivalent: document.getElementById('filter').addEventListener( 'keyup', function () { var jsStart = (new Date).getTime()...

Is it possible to have IF statement in an Echo statement in PHP

Thanks in advance. I did look at the other questions/answers that were similar and didn't find exactly what I was looking for. I'm trying to do this, am I on the right path? echo " <div id='tabs-".$match."'> <textarea id='".$match."' name='".$match."'>". if ($COLUMN_NAME === $match) { echo $FIELD_WITH_COLUMN_NAME; } else { } ."</textarea> <script type='text/javascript'> CKEDITOR.replace( '".$match."' ); </script> </div>"; I am getting the following error message in the browser: Parse error: syntax error, unexpected T_IF Please let me know if this is the right way to go about nesting an IF statement inside an echo. Thank you.