Código PHP para convertir una consulta MySQL a CSV [cerrado]


128

¿Cuál es la forma más eficiente de convertir una consulta MySQL a CSV en PHP, por favor?

Sería mejor evitar los archivos temporales, ya que esto reduce la portabilidad (se requieren rutas de directorio y configuración de permisos del sistema de archivos).

El CSV también debe incluir una línea superior de nombres de campo.


74
¿Por qué se cerró esta pregunta por no ser constructiva? Este está bien y perfectamente claro.

14
@Alec Porque algunos moderadores aquí son supermoderadores, ya sabes ... "¡Los superpoderes conllevan una gran responsabilidad!" - Tío Ben
finitenessofinfinity

18
@finitenessofinfinity el poder corrompe, el poder absoluto corrompe absolutamente. Stackoverflow es un excelente ejemplo de eso.

16
¡Voto para reabrir esta pregunta!
TN888

9
Seis meses después y estoy usando las respuestas a esto en mi sitio web. ¿Se puede reabrir esto?
Jon

Respuestas:


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

( la documentación para esto está aquí: http://dev.mysql.com/doc/refman/5.0/en/select.html )

o:

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

5
técnicamente, esto está separado por tabuladores;)
John Douthat

5
Tenga en cuenta el uso de barras inclinadas SELECT INTO OUTFILEincluso en Windows.
Johan

1
Hola, esto funciona bien para el formato xls, pero si trato de guardar como archivo CSV, muestra todos los resultados en 1 columna. Quiero guardar esto como archivo csv.
vinod reddy

Entre los dos anteriores, ¿cuál es mejor, más seguro y por qué?
Chella

1
Yo tendería a sugerir que la segunda opción es más segura ya que `SELECT INTO OUTFILE requiere que el usuario de mysql tenga acceso al sistema de archivos para cambiar archivos, lo cual es un riesgo potencialmente grande.
Jeepstone

91

Mira esta pregunta / respuesta . Es más conciso que el de @ Geoff y también usa la función fputcsv incorporada.

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

1
El suyo no tiene los encabezados de columna.
Paolo Bergantino

15
En caso de que alguien más sea tan estúpido como yo, no lo reemplace php://outputcon un nombre de archivo real ni intente cerrarlo con un fcloseal final: no es un archivo real, solo un alias para el flujo de salida. De todos modos, esta respuesta funcionó perfectamente para mí, ¡gracias Jrgns!
J.Steve

@ J.Steve Mi placer :)
Jrgns


1
mysql_num_fields () no funciona para mí y los encabezados no se generan. ¿Esta función está obsoleta o algo así?
Doug

20

Mire la documentación sobre la sintaxis 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;

18

Una actualización de la solución @jrgns (con algunas ligeras diferencias de sintaxis).

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

Por alguna razón, $ fp me devuelve falso.
Volatil3

Para MySQL moderno, puede usar: $ encabezados [] = mysqli_fetch_field_direct ($ resultado, $ i) -> nombre;
Ben en CA

Y cambie las otras funciones mysql_ por funciones mysqli_.
Ben en CA

6

Si desea que la descarga se ofrezca como una descarga que se pueda abrir directamente en Excel, esto puede funcionar para usted: (copiado de un antiguo proyecto mío inédito)

Estas funciones configuran los encabezados:

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

Este envía un CSV a una secuencia usando un resultado de 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;
}

Este usa la función anterior para escribir un CSV en un archivo, dado por $ filename

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

Y aquí es donde ocurre la magia;)

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

Por ejemplo:

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

1
Gracias john código muy útil. Tuve que modificar una línea para la función csvFromResult. en lugar de while ($ fila = mysql_fetch_row ($ resultado)) {fputcsv ($ flujo, $ fila); $ filas ++; }, tuve que usar while ($ fila = mysql_fetch_row ($ resultado)) {$ datos [] = $ fila; // fputcsv ($ flujo, $ fila); // $ filas ++; } foreach ($ datos como $ d) {fputcsv ($ flujo, $ d); }. gracias de nuevo por un código tan maravilloso.
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;
}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.