Подтвердить что ты не робот

Исчерпана память PDO

Это обычная проблема, но у меня нет выбора кодировать ее так, чтобы получить соответствующий заголовок и тело в файле Excel.

здесь, как он начинается

Когда запрос был сделан для печати, я сначала начал делать запрос для извлечения заголовков в базе данных

SELECT instruments.in_id, instrument_parameters.ip_id,
CASE WHEN gv_x_ipid = -1 THEN 'datetime' ELSE '' END xlabel,
CASE WHEN ip_label LIKE '%Reservoir%' THEN 0 ELSE in_order END legendIndex,
CASE WHEN in_name = 'General' THEN ip_label ELSE in_name END ylabel            
FROM graph_plot
LEFT JOIN attributes gptype ON gp_type = gptype.at_id
LEFT JOIN graph_value ON gp_id = gv_gpid
LEFT JOIN instrument_parameters ON gv_y_ipid = ip_id
LEFT JOIN attributes pmunit ON ip_unit = pmunit.at_id
LEFT JOIN instrument_reading yvalue ON gv_y_ipid = iv_ipid
LEFT JOIN instruments ON iv_inid = in_id
WHERE gp_diid = :di_id AND 
      gp_type = :rpt_type AND 
      iv_status = 'Y' AND
      iv_inid in (".implode(",", $coll->inid).") AND
      gv_y_ipid in (".implode(",", $coll->ipid).")
GROUP BY ylabel
ORDER BY legendIndex

и это приведет к количеству заголовков, которые я сделаю так, чтобы это было

DATE | Instrument1 | Instrument2 | Instrument3

Instrument? будет динамическим, основанным на запросе выше. Я храню это в новой переменной. Но исходная переменная, содержащая результаты базы данных, остается неизменной.

Позже, используя те же параметры, :di_id и :rpt_type, еще несколько дополнительных параметров startDt и endDt, чтобы сделать еще один запрос, чтобы вернуть длинный список доступных дат в базе данных. Это основано на startDt и endDt.

$sql2 = "SELECT iv_reading FROM instrument_reading WHERE iv_inid = :inid AND iv_ipid = :ipid AND iv_date = :dt AND iv_status = 'Y'";    

Когда он закончит получение дат, я делаю два цикла, как этот

foreach ($dates as $key => $dt) {       
    foreach ($resp as $InstNo => $InstRow) {
        try {
            $stmt2->execute(array(':dt' => $dt, ':inid' => $InstRow->in_id, ':ipid' => $InstRow->ip_id));
            $rowDb = $stmt2->fetch(PDO::FETCH_NUM, PDO::FETCH_ORI_NEXT);
        } catch(PDOException $e) {
            echo '{"error":{"text":"'. $e->getMessage() .'"}}'; 
        }
    }
}

Во-первых, он начинает цитировать дату, а затем начинает цикл заголовков (на основе запроса, сделанного непосредственно перед получением дат). Моя проблема я всегда застрял здесь

$stmt2->execute(array(':dt' => $dt, ':inid' => $InstRow->in_id, ':ipid' => $InstRow->ip_id));

Как вы думаете? Есть ли лучший способ справиться с этим?

Для вашей информации я использую Slim и PHPExcel. PHPExcel может иметь проблемы с памятью, и я думаю перейти к Spout, но документы все еще касаются базового материала.

4b9b3361

Ответ 1

В вашем SQL вы можете рассмотреть предложение limit, чтобы упростить загрузку памяти следующим образом:

$handle = fopen("file.csv", "wb");
$statement = "
SELECT  instruments.in_id, instrument_parameters.ip_id,
       CASE WHEN gv_x_ipid = -1 THEN 'datetime' ELSE '' END xlabel,
       CASE WHEN ip_label LIKE '%Reservoir%' THEN 0 ELSE in_order END legendIndex,
       CASE WHEN in_name = 'General' THEN ip_label ELSE in_name END ylabel
    FROM  graph_plot
    LEFT JOIN  attributes gptype ON gp_type = gptype.at_id
    LEFT JOIN  graph_value ON gp_id = gv_gpid
    LEFT JOIN  instrument_parameters ON gv_y_ipid = ip_id
    LEFT JOIN  attributes pmunit ON ip_unit = pmunit.at_id
    LEFT JOIN  instrument_reading yvalue ON gv_y_ipid = iv_ipid
    LEFT JOIN  instruments ON iv_inid = in_id
    WHERE  gp_diid = :di_id
      AND  gp_type = :rpt_type
      AND  iv_status = 'Y'
      AND  iv_inid in (".implode(",", $coll->inid).")
      AND  gv_y_ipid in (".implode(",", $coll->ipid).")
    GROUP BY  ylabel
    ORDER BY  legendIndex
    LIMIT  250
";
$prep = $dbh->prepare($statement);
for ($i = 0; $prep -> rowCount < 250; $i+= 250) {
    fputcsv(prep->fetchAll());
    $prep = $dbh->prepare($statement.' OFFSET'.$i);
}
fclose($handle);

В качестве альтернативы вы можете использовать system и вызвать SELECT INTO, установите разрешения (если необходимо) и Боб вашего дяди.

Ответ 2

Вы не завершили цикл fetch.

$rowDb = $stmt2->fetch(PDO::FETCH_NUM, PDO::FETCH_ORI_NEXT);

получает строку "next" или закрывает "курсор" и завершает работу.

Ожидаете ли вы получить ровно одну строку? Если да, рассмотрите возможность делать fetchAll. (Предупреждение: набор результатов может быть дополнительным уровнем в массивах.)