1) A typo on NogDog's part: he fetches the first row in order to get the keys (for the column headers), but doesn't output its values. Assuming you can't know what the fields are (and so put them in an array to start with, and use them in the SELECT statement), then [man]mysql_list_fields[/man] will get a list of fields in a given table.
2) You'll end up with temp files filling your filesystem if you don't delete them (incidentally, [man]tmpfile[/man] does the job of creating a temp file and should handle deleting it when it's finished with).
You could also avoid using the temp file completely by writing to the STDOUT handle
fputcsv(STDOUT, ...
You'll need to output the headers first, of course. The down side is that these headers include the Content-Length, and obviously that isn't known until the content has been created. That apparent catch-22 can be avoided by buffering the output.
ob_start();
// write the CSV, using STDOUT as the resource handle to write to
$content_length = ob_get_length();
// Headers
ob_end_flush();