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

Внизу этого вопроса заключительный кодекс, который окончательно сработал!

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

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

note2: Если я прокомментирую строку $sql="DELETE FROM dbase", код будет работать нормально (и таблица будет очищена).

Так что, если я знаю, что мой 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();
?>

ТКС заранее!

РЕДАКТИРОВАТЬ:

Сделано ниже изменений и до сих пор не работает!

новый код:

<?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();
?>

Когда я запускаю браузер, я вижу следующее:

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

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

Не удалось подготовиться: (1295) Эта команда не поддерживается в протоколе подготовленного оператора yetobject(mysqli)#1 (19) { ["disabled_rows"]=> int(-1) ["client_info"]=> string(79) "mysqlnd 5.0.11-dev - 20120503 - $Id: 40933630edef551dfaca71298a83fad8d03d62d4 $" ["client_version"]=> int(50011) ["connect_errno"]=> int(0) ["connect_error"]=> NULL ["errno"]=> int(1295) ["error"]=> string(68) "Эта команда еще не поддерживается в подготовленном протоколе операторов" ["error_list"]=> array(0) { } ["field_count"]=> int(1) ["host_info"]=> string(20) "localhost via TCP/IP" ["info"]=> NULL ["insert_id"]=> int(0) ["server_info"]=> string(6) "5.6.11" ["server_version"]=> int(50611) ["stat"]=> string(133) "Время работы: 7993 Тем: 2 Вопросы: 865 Медленные запросы: 0 Открытия: 75 Сброс таблиц: 1 Открытых таблиц: 68 запросов в секунду avg: 0.108" ["sqlstate"]=> string(5) "00000" ["protocol_version"]=> int(10) ["thread_id"]=> int(117) ["warning_count"]=> int(0) }

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

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

РЕДАКТИРОВАТЬ 3.

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

<?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-slash вместо обратной косой черты в windows-default. Orderwise просто отметит работу. Бог знает, как я понял это...

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

  • имейте в виду, что "подготовленные stmts не поддерживают загрузку данных"

4 ответа

Решение

РЕДАКТИРОВАТЬ для вероятного решения: подготовленные stmts не поддерживают LOAD DATA ,

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

Так:

//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 мы запрещаем LOAD FILE, но это говорит мне о том, что механизм успешно проанализировал и попытался выполнить запрос.

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

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

$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. Другие возможные ошибки, которые вы увидите

Недостаточно FILE privs или неправильный каталог файла Loc

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

Обратитесь к следующему в MySQL Docs и прочтите этот раздел. Как я уже сказал, LOAD..FILE - очень чувствительная операция с множеством ограничений. LOAD...FILE MySQL Docs

По соображениям безопасности при чтении текстовых файлов, расположенных на сервере, файлы должны либо находиться в каталоге базы данных, либо быть доступными для чтения всем. Кроме того, чтобы использовать LOAD DATA INFILE для файлов сервера, вы должны иметь привилегию FILE. См. Раздел 6.2.1, "Права, предоставляемые MySQL". Для не локальных операций загрузки, если системной переменной secure_file_priv задано непустое имя каталога, загружаемый файл должен находиться в этом каталоге.

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

/* 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 параметры правильно.

Что говорит Гомер6, и, вероятно,

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

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

Вы должны использовать root-пользователя MySQL. Если он по-прежнему не запускается, используйте этот код для проверки вывода ошибок.

      var_dump(mysqli_error($conn));
Другие вопросы по тегам