在这个问题的底部,最后一个代码终于起作用了!
尝试实现这一点(使用PHP/MMySQL导入CSV数据)。我一定快到了。。。
注1:我的$sql直接来自于复制/粘贴phpmyadmin(生成php代码),并且在phpmyadmin中运行得很好。
注2:如果我对$sql="DELETE FROM dbase"这一行进行注释,代码运行得很好(并且表已清理)。
所以,如果我知道我的sql是正确的,并且我的代码可以运行其他sql,为什么下面的不运行?!我得到:
调用非对象上的成员函数execute()-对于行
$stmt->execute();
完整代码:
<?php
$mysqli = new mysqli('localhost','root','pass','dbase');
/* check connection */
if (mysqli_connect_errno()) {
printf("Connect failed: %sn", mysqli_connect_error());
exit();
}
$sql = "LOAD DATA INFILE './myfile.csv' INTO TABLE tabn"
. " 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: %sn", 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:\xamplep/htdocs/myfile.csv"加载到表选项卡字段"终止于","终止于的行"\r\n"忽略1行
准备失败:(1295)已准备好的语句协议yethobject(mysqli)#1(19){["affected_rows"]=>int(-1)["client_info"]=>string(79)"mysqlnd 5.0.11-dev-20120503-$Id:40933630edef551dfaca71298a83fad8d03d62d4$"["client_version"]=>int(50011 error"]=>字符串(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"正常运行时间:7993个线程:2个问题:865个慢速查询:0个打开:75个刷新表:1个打开表:每秒68个查询平均值: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: %sn", 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默认的反斜杠。有序只会记录工作。天知道我是怎么想出来的。。。
利用答案中提供的许多调试代码。我想检查sql是否正确的一种有效方法是回显(
echo $sql
)它并在sql提示符中复制/粘贴。不要相信phpmyadmin的"创建phpPHP代码"功能。请记住"准备好的stmts不支持LOAD DATA"
编辑可能的解决方案:准备好的stmt不支持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 'rn'"
. " 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.您可能看到的其他错误
文件权限不足或文件位置目录不正确
phpMyAdmin是非常沙盒的,它的工作方式与mysqli/php完全不同。
从MySQL文档中处理以下内容,并阅读本节内容。就像我说的,LOAD。。FILE是一个非常敏感的操作,有很多限制。LOAD...FILE
MySQL文档
出于安全原因在读取位于服务器上的文本文件时,文件必须位于数据库目录中或可读所有人。此外,要在服务器文件上使用LOAD DATA INFOILE,您必须FILE特权。请参阅第6.2.1节"MySQL提供的权限"。对于非LOCAL加载操作,如果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或mysqli-php客户端中发生了任何"魔术",它将通过使用mysql-cli客户端来显示,因为其中两个客户端将成功,而一个客户端将失败(与您的假设相比)。
我以前遇到过类似的问题,它最终成为MySQL转义分隔符的奇怪方式,所以我希望您能正确地转义TERMINATED BY
参数。
Homer6的状态,可能还有:
$sql = "LOAD DATA INFILE './myfile.csv' INTO TABLE tab"
. " FIELDS TERMINATED BY ','"
. " LINES TERMINATED BY '\r\n'"
. " IGNORE 1 LINES";
可能还需要检查文件的路径。我不知道是什么。/是相对于查询中的。也许不是PHP文件的位置。
您必须使用MySQL的根用户如果它仍然无法运行,请使用此代码检查错误输出
var_dump(mysqli_error($conn));