使用PHP / MySQL导入CSV数据 - Mysqli语法

时间:2013-12-07 00:37:36

标签: php sql csv mysqli load-data-infile

在本问题的底部,最终完成的最终法规!

尝试实现此目的(Importing CSV data using 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。

LOAD DATA INFILE'C:/xampp/htdocs/myfile.csv'INTO TABLE tab FIELDS TERMINATED BY','LINIEDATED''r \ n'IGNNORE 1 LINES

准备失败:(1295)准备好的语句protocol yetobject(mysqli)#1(19){[“affected_rows”] =&gt;不支持此命令。 int(-1)[“client_info”] =&gt; string(79)“mysqlnd 5.0.11-dev - 20120503 - $ Id:40933630edef551dfaca71298a83fad8d03d62d4 $”[“client_version”] =&gt; int(50011)[“connect_errno”] =&gt; int(0)[“connect_error”] =&gt; NULL [“errno”] =&gt; int(1295)[“error”] =&gt; string(68)“准备好的语句协议中不支持此命令”[“error_list”] =&gt; array(0){} [“field_count”] =&gt; int(1)[“host_info”] =&gt; string(20)“localhost via TCP / IP”[“info”] =&gt; NULL [“insert_id”] =&gt; int(0)[“server_info”] =&gt; string(6)“5.6.11”[“server_version”] =&gt; int(50611)[“stat”] =&gt; string(133)“Uptime:7993 Threads:2 Questions:865 Slow queries:0 Opens:75 Flush tables:1 Open tables:68 Queries per second avg:0.108”[“sqlstate”] =&gt; string(5)“00000”[“protocol_version”] =&gt; int(10)[“thread_id”] =&gt; int(117)[“warning_count”] =&gt; 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 $sql)它并在你的sql提示符中复制/粘贴。不信任phpmyadmin'创建PHP PHP代码'功能。

  • 请记住'准备好的stmts不支持LOAD DATA'

4 个答案:

答案 0 :(得分:2)

您可能应该使用警卫来检测准备呼叫何时失败:

/* 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命令行客户端执行命令。如果有任何&#34;魔法&#34;发生在phpmysql或mysqli php客户端,它将通过使用mysql cli客户端显示,因为两个客户端将成功,其中一个将失败(与您的假设相比)。

之前我遇到过类似的问题,结果却是MySQL逃避分隔符的奇怪方式,所以我希望看到你正在逃避{{{ 1}}参数正确。

答案 1 :(得分:2)

编辑可能的解决方案:准备好的stmts不支持LOAD DATA

如果您使用mysqli_query - 而不是mysqli->prepare ..-&gt; 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)有用,看看结果我得到访问被拒绝,因为在我的环境中我们不允许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();

我的Box上的结果(不是最佳代表):

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

<强> 2。您可能会看到其他可能的错误

文件权限不足或文件Loc的目录不正确

phpMyAdmin非常沙盒化,与mysqli / php完全不同。

从MySQL Docs中解决以下问题,并阅读本节内容。就像我说的那样,LOAD..FILE是一个非常敏感的操作,有很多限制。 LOAD...FILE MySQL Docs

  

出于安全考虑,在阅读服务器上的文本文件时,   文件必须驻留在数据库目录中或可读   所有。此外,要在服务器文件上使用LOAD DATA INFILE,您必须拥有   FILE权限。请参见第6.2.1节“MySQL提供的权限”。   对于非LOCAL加载操作,如果是secure_file_priv系统变量   设置为非空目录名称,要加载的文件必须是   位于该目录中。

答案 2 :(得分:0)

Homer6所说的,可能是:

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

也可能需要检查文件的路径。我不知道查询中./是相对的。也许不是PHP文件的位置。

答案 3 :(得分:0)

必须使用 MySQL 的 root 用户 如果仍然无法运行,请使用此代码检查错误输出

var_dump(mysqli_error($conn));