Index: /branches/version-2_13-dev/data/class/helper/SC_Helper_CSV.php
===================================================================
--- /branches/version-2_13-dev/data/class/helper/SC_Helper_CSV.php	(revision 23362)
+++ /branches/version-2_13-dev/data/class/helper/SC_Helper_CSV.php	(revision 23375)
@@ -21,4 +21,7 @@
     public $arrSubnaviName;
 
+    /** ヘッダーを出力するか (cbOutputCSV 用) */
+    private $output_header = false;
+
     /**
      * デフォルトコンストラクタ.
@@ -208,4 +211,12 @@
     public function cbOutputCSV($data)
     {
+        // 1行目のみヘッダーを出力する
+        if ($this->output_header) {
+            $line = $this->sfArrayToCsv(array_keys($data));
+            $line = mb_convert_encoding($line, 'SJIS-Win');
+            $line .= "\r\n";
+            fwrite($this->fpOutput, $line);
+            $this->output_header = false;
+        }
         $line = $this->sfArrayToCsv($data);
         $line = mb_convert_encoding($line, 'SJIS-Win');
@@ -222,21 +233,14 @@
      * @param  integer $sql         SQL文
      * @param  array   $arrVal      プリペアドステートメントの実行時に使用される配列。配列の要素数は、クエリ内のプレースホルダの数と同じでなければなりません。
-     * @param  string  $file_head   ファイル名の頭に付ける文字列
-     * @param  array   $arrHeader   ヘッダ出力列配列
-     * @param  boolean $is_download true:ダウンロード用出力までさせる false:CSVの内容を返す(旧方式、メモリを食います。）
+     * @param  string       ファイル名の頭に付ける文字列
+     * @param  array|null   ヘッダ出力列配列。null の場合、SQL 文の列名を出力する。
+     * @param  boolean      true:ダウンロード用出力までさせる false:CSVの内容を返す(旧方式、メモリを食います。）
      * @return mixed   $is_download = true時 成功失敗フラグ(boolean) 、$is_downalod = false時 string
      */
-    public function sfDownloadCsvFromSql($sql, $arrVal = array(), $file_head = 'csv', $arrHeader = array(), $is_download = false)
+    public function sfDownloadCsvFromSql($sql, $arrVal = array(), $file_head = 'csv', $arrHeader = null, $is_download = false)
     {
         $objQuery =& SC_Query_Ex::getSingletonInstance();
 
-        // ヘッダ構築
-        if (is_array($arrHeader)) {
-            $header = $this->sfArrayToCsv($arrHeader);
-            $header = mb_convert_encoding($header, 'SJIS-Win');
-            $header .= "\r\n";
-        }
-
-        //テンポラリファイル作成
+        // テンポラリファイル作成
         // TODO: パフォーマンス向上には、ストリームを使うようにすると良い
         //  環境要件がPHPバージョン5.1以上になったら使うように変えても良いかと
@@ -244,6 +248,25 @@
         $tmp_filename = tempnam(CSV_TEMP_REALDIR, $file_head . '_csv');
         $this->fpOutput = fopen($tmp_filename, 'w+');
-        fwrite($this->fpOutput, $header);
+        $this->output_header = false;
+
+        // ヘッダー構築
+        if (is_array($arrHeader)) {
+            $header = $this->sfArrayToCsv($arrHeader);
+            $header = mb_convert_encoding($header, 'SJIS-Win');
+            $header .= "\r\n";
+            fwrite($this->fpOutput, $header);
+        } elseif (is_null($arrHeader)) {
+            // ループバック内でヘッダーを出力する
+            $this->output_header = true;
+        }
+
         $objQuery->doCallbackAll(array(&$this, 'cbOutputCSV'), $sql, $arrVal);
+
+        // コールバック内でヘッダー出力する場合、0行時にヘッダーを生成できない。
+        // コールバックが呼ばれていない場合、念のため CRLF を出力しておく。
+        // XXX WEB画面前提で、アラート表示する流れのほうが親切かもしれない。
+        if ($this->output_header) {
+            fwrite($this->fpOutput, "\r\n");
+        }
 
         fclose($this->fpOutput);
@@ -257,5 +280,5 @@
         }
 
-        //テンポラリファイル削除
+        // テンポラリファイル削除
         unlink($tmp_filename);
 
Index: /branches/version-2_13-dev/data/class/pages/admin/contents/LC_Page_Admin_Contents_CsvSql.php
===================================================================
--- /branches/version-2_13-dev/data/class/pages/admin/contents/LC_Page_Admin_Contents_CsvSql.php	(revision 23124)
+++ /branches/version-2_13-dev/data/class/pages/admin/contents/LC_Page_Admin_Contents_CsvSql.php	(revision 23375)
@@ -352,24 +352,10 @@
     public function lfDoCsvOutput($sql_id)
     {
+        $objCSV = new SC_Helper_CSV_Ex();
+
         $arrData = $this->lfGetSqlList('sql_id = ?', array($sql_id));
-        $sql = 'SELECT ' . $arrData[0]['csv_sql'] . ' ';
-
-        // TODO: ヘッダ取得 SQL内にLIMIT文がある場合はLIMIT句は追加しないので重いかも
-        $objQuery =& SC_Query_Ex::getSingletonInstance();
-
-        $arrHeader = array();
-        if (!preg_match('/ LIMIT /', $sql)) {
-            $head_sql = $sql . ' LIMIT 0';
-        } else {
-            $head_sql = $sql;
-        }
-        $arrData = $objQuery->getQueryDefsFields($head_sql, array(), true);
-        if (!SC_Utils_Ex::isBlank($arrData)) {
-            foreach ($arrData as $key => $val) {
-                $arrHeader[] = $key;
-            }
-        }
-        $objCSV = new SC_Helper_CSV_Ex();
-        $objCSV->sfDownloadCsvFromSql($sql, array(), 'contents', $arrHeader, true);
+        $sql = 'SELECT ' . $arrData[0]['csv_sql'];
+
+        $objCSV->sfDownloadCsvFromSql($sql, array(), 'contents', null, true);
         SC_Response_Ex::actionExit();
     }
