简体   繁体   中英

LOAD DATA INFILE - Show number of rows imported gives wrong value

I've been trying to import a csv file into a mysql database using LOAD DATA INFILE.

Everything is working more or less correctly, but when I use mysqli_info() or mysqli_affected_rows() they each show that no rows have been imported for the query. Even though I see the rows are being correctly imported.

A simplified version of what I am trying to do (Fewer columns that I am actually importing):

$server = 'localhost';
$username = 'root';
$password = 'password123';
$database = 'database_name';

$connect = new mysqli($server, $username, $password, $database);

$files = scandir('imports/');

foreach($files as $file) {
   $import = 
        "LOAD DATA INFILE 'imports/$file'
        IGNORE INTO TABLE table_name
        FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '\"'
        LINES TERMINATED BY '\n'
        IGNORE 1 LINES
        (@id, @name, @address, @product)
        set id=@id, name=@name, address=@address, product=@product";

    if(! $connect->query($import)) {
        echo 'Failed';
    }

    $connect->query($import);

    echo mysqli_affected_rows($connect);
}

mysqli_affected_rows() returns 0, while mysqli_info() states all rows have been skipped. Any idea why it's not displaying correctly?

Hopefully that's enough information. Thanks!

Edit:

I've been a bit too busy to work on this over the past few days, but I have decided that although it doesn't specifically answer my question Drew's answer of importing into a temporary table first seems to make the most sense so I have decided to go with that.

Further clarification of my comment: I would not be relying on $connect->affected_rows as ever a Rosetta stone for info. It is broken half the time. I would not be relying on $connect->affected_rows as ever a Rosetta stone for info. It is broken half the time.

This is one recommendation. Perform your LOAD DATA INFILE into a worktable, not your final desired table. Once that is performed, you have successfully escaped the limitations of that functionality and can enjoy the fruits of Insert on Duplicate Key Update (IODKU).

With the latter when I want to know counts, I get an assigned batch number from a control table. If you need help with that, let me know.

But I am stepping back to the point of having the data in the worktable now, with a batch number in hand. I then perform the IODKU from the worktable into the final table with the batch number coming along for the ride into a column in the final table (yes, I can tweak the schema to do that, perhaps you cannot). To get around any schema changes to existing table, and to find cases or allow for a row having multiple batch id's having hit it, a simple association table with id's can be used. An intersect table if you will.

If concurrency is an issue (multiple users likely able to do this concurrently), then a locking strategy (ideally INNODB row-level locking) is employed. If used, make it fast.

I then fetch my count off the final table (or intersect table) where batch id = my batch number in hand.

See also this answer from Jan.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM