Импорт данных CSV с использованием синтаксиса PHP/MySQL-Mysqli


В НИЖНЕЙ ЧАСТИ ЭТОГО ВОПРОСА ОКОНЧАТЕЛЬНЫЙ КОД, КОТОРЫЙ НАКОНЕЦ-ТО СРАБОТАЛ!

Попытка реализовать это ( Импорт данных CSV с использованием PHP/MySQL). Я, должно быть, почти на месте...

Примечания 1: мой $sql пришел прямо из copy/paste phpmyadmin (генерировать php-код) и отлично работал в phpmyadmin.

Примечание 2: Если я прокомментирую строку $sql= "УДАЛИТЬ ИЗ базы данных", код будет работать нормально (и таблица будет очищена).

Итак, если я знаю, что мой sql верен, и мой код может выполняться другие sqls, почему ниже не запускается?! Я получаю:

Вызов функции-члена execute() для не-объекта - для строки

$stmt->execute();

Полный код:

<?php
$mysqli  =  new mysqli('localhost','root','pass','dbase');
/* check connection */
if (mysqli_connect_errno()) {
printf("Connect failed: %s\n", mysqli_connect_error());
exit();
}

$sql = "LOAD DATA INFILE \'./myfile.csv\' INTO TABLE tab\n"
. " FIELDS TERMINATED BY \',\'\n"
. " LINES TERMINATED BY \'\\r\\n\'\n"
. " IGNORE 1 LINES";

//$sql="DELETE FROM dbase";

$stmt=$mysqli->prepare($sql);
$stmt->execute(); 
$stmt->close();
$mysqli->close();
?>

Tks заранее!

ИЗМЕНИТЬ:

Внесенные ниже изменения и все еще не работают!

Новый код:

<?php

$mysqli  =  new mysqli('localhost','root','pass','dbase');
/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

/* return name of current default database */
if ($result = $mysqli->query("SELECT DATABASE()")) {
    $row = $result->fetch_row();
    printf("Default database is %s.\n", $row[0]);
    $result->close();
}

$sql = "LOAD DATA INFILE 'C:/xampp/htdocs/myfile.csv' INTO TABLE tab
        FIELDS TERMINATED BY ','
    LINES TERMINATED BY '\\r\\n'
    IGNORE 1 LINES";

echo "<br>";
echo "<br>";
echo $sql;
echo "<br>";
echo "<br>";
$stmt=$mysqli->prepare($sql);

/* Prepared statement, stage 1: prepare */
if (!($stmt = $mysqli->prepare($sql))) 
{    echo "Prepare failed: (" . $mysqli->errno . ") " . $mysqli->error;
}


// NOTE HERE WE'RE DUMPING OUR OBJ TO SEE THAT IT WAS 
// CREATED AND STATUS OF PREPARE AND THEN KILLING SCRIPT   
var_dump($mysqli);
exit();

//$sql="DELETE FROM intrasdump

$stmt=$mysqli->prepare($sql);
$stmt->execute(); 
$stmt->close();
$mysqli->close();
?>

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

База данных по умолчанию - имя базы данных.

ЗАГРУЗИТЬ ФАЙЛ ДАННЫХ'C:/xampp/htdocs/myfile.csv 'В ПОЛЯ вкладки ТАБЛИЦЫ ЗАВЕРШЕНЫ ПО ',' СТРОКАМ, ЗАКАНЧИВАЮЩИМСЯ НА '\r\n', ИГНОРИРУЙТЕ 1 СТРОКУ

Не удалось подготовить: (1295) Эта команда еще не поддерживается в протоколе подготовленной инструкции. Объект (mysqli)#1(19) {["affected_rows"]=>int(-1) ["client_info"]=>строка(79) "mysqlnd 5.0.11-dev-20120503 - $Id: 40933630edef551dfaca71298a83fad8d03d62d4$" ["client_version"]=>int(50011 ) ["connect_errno"]=>int(0) ["connect_error"]=>NULL ["errno"]=>int(1295) ["ошибка"]=>строка(68) "Эта команда не поддерживается в подготовленном протокол оператора еще"["список ошибок"]=>массив(0) {} ["field_count"]=> int(1) ["host_info"]=>строка(20) "локальный хост через TCP/IP" ["информация"]=>NULL ["insert_id"]=>int(0) ["server_info"]=>строка(6) "5.6.11" ["server_version"]=>int(50611) ["статистика"]=>строка(133) "Время безотказной работы : 7993 Темы: 2 Вопроса: 865 Медленных запросов: 0 Открывается: 75 Заполненных таблиц: 1 Открытые таблицы: 68 запросов в секунду в среднем: 0,108" ["sqlstate"]=>строка(5) "00000" ["protocol_version"]=>int(10) ["thread_id"]=>int(117) ["warning_count"]=> int(0)}

Примечание: Если я скопирую и вставлю строку sql, приведенную выше, в приглашение mysql, она будет работать просто отлично. Это должно означать, что и проблема с местоположением файла, и сама строка sql в порядке, нет???

Как это может быть так сложно?!

ПРАВКА 3.

Tks для всех ответов и комментариев. Окончательная версия кода ниже работает:

<?php

$mysqli  =  new mysqli('localhost','root','pass','dbname');
/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

$sql = "LOAD DATA INFILE 'C:/xampp/htdocs/myfile.csv' INTO TABLE tab
        FIELDS TERMINATED BY ','
        LINES TERMINATED BY '\\r\\n'
        IGNORE 1 LINES";

//Try to execute query (not stmt) and catch mysqli error from engine and php error
if (!($stmt = $mysqli->query($sql))) {
    echo "\nQuery execute failed: ERRNO: (" . $mysqli->errno . ") " . $mysqli->error;
};
?>

Полезные примечания:

  • Обратите внимание, что в пути к файлу используется frw-косая черта вместо обратной косой черты Windows по умолчанию. Упорядоченно будет просто обратите внимание на работу. Одному Богу известно, как я до этого додумался...

  • Воспользуйтесь преимуществами множества отладочных кодов, предлагаемых в ответах. я думаю, что один из эффективных способов проверить, правильно ли ваш sql повторяет (echo $sql) его и копирует/вставляет в вашу строку sql. не доверяйте функциональности phpmyadmin "создание php кода PHP".

  • Имейте в виду, что "Подготовленные stmt не поддерживают ЗАГРУЗКУ ДАННЫХ'

Author: Community, 2013-12-07

3 answers

ОТРЕДАКТИРУЙТЕ возможное решение: Подготовленные stmts не поддерживают LOAD DATA.

Если вы используете mysqli_query - вместо mysqli->prepare..->выполнить(); это должно сработать.

Итак:

//Connect as normal above
$sql = "LOAD DATA INFILE '/myfile.csv' INTO TABLE tab"
. " FIELDS TERMINATED BY ','"
. " LINES TERMINATED BY '\r\n'"
. " IGNORE 1 LINES";

//$sql="DELETE FROM dbase";
// $stmt = $mysqli->query($sql);
// Integrate other posters good recc to catch errors:

//Try to execute query (not stmt) and catch mysqli error from engine and php error
if (!($stmt = $mysqli->query($sql))) {
    echo "\nQuery execute failed: ERRNO: (" . $mysqli->errno . ") " . $mysqli->error;
}

По-прежнему полезно использовать var_dump($mysqli) здесь, чтобы увидеть результат, в котором мне отказали в доступе, так как в моем env мы запрещаем ЗАГРУЖАТЬ ФАЙЛ, но это говорит мне, что движок успешно проанализировал и попытался выполнить запрос.

Вам нужно получить более подробную информацию об ошибках, есть немного, что может произойти, вот как я будет копаться в:

Процесс диагностики, чтобы добраться до этой точки:

$sql = "LOAD DATA INFILE ...";
echo $sql;
$stmt=$mysqli->prepare($sql);

// NOTE HERE WE'RE DUMPING OUR OBJ TO SEE THAT IT WAS 
// CREATED AND STATUS OF PREPARE AND THEN KILLING SCRIPT   
var_dump($mysqli);
exit();

Результаты на моей коробке (не лучшее представление):

  object(mysqli)#1 (18) {
  ...
  string(68) "This command is not supported in the 
              prepared statement protocol yet"

2. Другие возможные ошибки, которые вы увидите

Недостаточный доступ к ФАЙЛАМ или Неправильный каталог расположения файлов

PhpMyAdmin довольно изолирован и будет работать совершенно иначе, чем mysqli/php.

Обратитесь к следующему из документов MySQL и прочитайте этот раздел. Как я и сказал, ЗАГРУЗКА..ФАЙЛА - очень чувствительная операция с множеством ограничений. LOAD...FILE Документы MySQL

По соображениям безопасности при чтении текстовых файлов, расположенных на сервере, файлы должны либо находиться в каталоге базы данных, либо быть читаемыми всеми. Кроме того, чтобы использовать файл ЗАГРУЗКИ ДАННЫХ в файлах сервера, у вас должны быть права доступа к файлам. См. Раздел 6.2.1, "Привилегии, предоставляемые MySQL". Для нелокальных операций загрузки, если системная переменная secure_file_priv имеет значение непустое имя каталога, загружаемый файл должен находиться в этом каталоге.

 1
Author: cerd, 2013-12-07 19:35:26

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

/* Prepared statement, stage 1: prepare */
if (!($stmt = $mysqli->prepare("INSERT INTO test(id) VALUES (?)"))) {
    echo "Prepare failed: (" . $mysqli->errno . ") " . $mysqli->error;
}

Источник: http://www.php.net/manual/en/mysqli.quickstart.prepared-statements.php

Я бы также проверил путь для команды LOAD DATA INFILE. Phpmyadmin может устанавливать другую переменную пути. Если вы попытаетесь временно указать абсолютный путь unix (и убедитесь, что у mysql есть соответствующие разрешения для этого каталога), это может устранить проблему.

Однако в любом случае вам следует выведите ошибку из клиента mysql, чтобы дать вам лучшее представление о том, что вызывает проблему.

Наконец, я бы попытался выполнить команду непосредственно в клиенте командной строки MySQL. Если в phpmysql или php-клиенте mysqli происходит какое-либо "волшебство", оно проявится при использовании клиента mysql cli, поскольку два клиента преуспеют там, где один потерпит неудачу (по сравнению с вашими предположениями).

Я уже сталкивался с подобной проблемой раньше, и это оказалось странным способом MySQL избежать разделитель, поэтому я хотел бы убедиться, что вы правильно избегаете параметров TERMINATED BY.

 2
Author: Homer6, 2013-12-07 00:52:56

Что утверждает Homer6, и, вероятно:

$sql = "LOAD DATA INFILE './myfile.csv' INTO TABLE tab"
. " FIELDS TERMINATED BY ','"
. " LINES TERMINATED BY '\\r\\n'"
. " IGNORE 1 LINES";

Возможно, также потребуется проверить путь к файлу. Я не знаю, к чему относится ./ в запросе. Возможно, не расположение PHP-файлов.

 0
Author: AbraCadaver, 2013-12-07 00:51:56