且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

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

更新时间:2023-01-21 12:15:25

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



如果您使用 mysqli_query - 而不是 mysqli-> code> ..-> execute();这应该工作。



因此:

  //以上正常连接
$ sql =LOAD DATA INFILE/myfile.csv'INTO TABLE选项卡
。 FIELDS TERMINATED BY','
。 LINES TERMINATED BY'\r\\\
'
。 IGNORE 1 LINES;

// $ sql =DELETE FROM dbase;
// $ stmt = $ mysqli-> query($ sql);
//集成其他海报好recc捕获错误:

//尝试执行查询(不是stmt)并捕获mysqli错误从引擎和php错误
if(! $ stmt = $ mysqli-> query($ sql))){
echo\\\
Query execute failed:ERRNO:(。$ mysqli-> errno。)。 $ mysqli-> error;
}

有用的还是var_dump($ mysqli)因为在我的env中我们不允许LOAD FILE,但这告诉我引擎成功解析并尝试执行查询。



你需要得到更好的错误信息,位



诊断过程,以获得此点:

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

//注意这里我们抛弃我们的OBJ看到它是
//创建和准备状态,然后杀死脚本
var_dump($ mysqli);
exit();

我的盒子上的结果(不是***表示): >

  object(mysqli)#1(18){
...
string(68)在
预备语句协议中不支持

2。您将看到的其他可能错误



FILE私人资料不足或档案地址不正确目录 b $ b

phpMyAdmin是很漂亮的沙箱,并且将完全不同于mysqli / php。



从MySQL文档处理以下内容,并阅读本节。像我说的,LOAD..FILE是一个非常敏感的操作,有很多限制。 LOAD ... FILE MySQL文档


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



IN THE BOTTOM OF THIS QUESTION THE FINAL CODE THAT FINALLY WORKED!

Trying to implement this (Importing CSV data using PHP/MySQL). I must be almost there...

notes1: my $sql came straight from copy/paste phpmyadmin (generate php code) and ran just fine in the phpmyadmin.

note2: If I comment the line $sql="DELETE FROM dbase" the code runs just fine (and the table is cleaned).

So if i know my sql is right and my code can run other sqls, why does the below does not run?! Im getting:

Call to a member function execute() on a non-object - for the line

$stmt->execute();

Full code:

<?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 in advance!

EDIT:

Made below changes and still not working!

new code:

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

What i see in my browser when I ran this is the following:

Default database is dbname.

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

Prepare failed: (1295) This command is not supported in the prepared statement protocol yetobject(mysqli)#1 (19) { ["affected_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) "This command is not supported in the prepared statement protocol yet" ["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) "Uptime: 7993 Threads: 2 Questions: 865 Slow queries: 0 Opens: 75 Flush tables: 1 Open tables: 68 Queries per second avg: 0.108" ["sqlstate"]=> string(5) "00000" ["protocol_version"]=> int(10) ["thread_id"]=> int(117) ["warning_count"]=> int(0) }

Note: If I copy paste the sql string echoed above in to mysql prompt, it runs just fine. That should mean that both the file location issue and the sql string itself are fine, no???

how can this be so hard?!

EDIT 3.

Tks for all answers and comments. Final code version below works:

<?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;
};
?>

useful notes:

  • note the file path uses frw-slash instead of windows-default back-slash. Orderwise will just note work. God knows how I figured that one out...

  • take advantage of the many debugging codes offered in the answers. i guess one effective way to check if your sql is right to echo (echo $sql) it and copy/paste in your sql prompt. don't trust phpmyadmin 'create php PHP code' functionality.

  • keep in mind 'Prepared stmts don't support LOAD DATA'

EDIT for Probable Solution: Prepared stmts don't support LOAD DATA.

If you use mysqli_query - instead of mysqli->prepare ..->execute(); this should work.

So:

//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;
}

useful still to var_dump($mysqli) here to see result I got access denied as in my env we disallow LOAD FILE, but that tells me the engine successfully parsed and attempted to execute the query.

You need to get better error info, there is a bit that could be going on, here is how I would dig in:

Diagnosis Process to get to this Point:

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

Results on my Box (not the best representation):

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

2. Other possible errors you would see

Insufficient FILE privs or Improper Directory of file Loc

phpMyAdmin is pretty sandboxed and will work completely differently than mysqli/php.

Address the following from MySQL Docs, and read up on this section. Like I said, LOAD..FILE is a very sensitive operation with a lot of restrictions. LOAD...FILE MySQL Docs

For security reasons, when reading text files located on the server, the files must either reside in the database directory or be readable by all. Also, to use LOAD DATA INFILE on server files, you must have the FILE privilege. See Section 6.2.1, "Privileges Provided by MySQL". For non-LOCAL load operations, if the secure_file_priv system variable is set to a nonempty directory name, the file to be loaded must be located in that directory.