14

我正在做一个上传 CSV 并更新 MySQL 表的项目。在我的 sql 插入语句的末尾,我有一个“重复键更新...”语句。

我的问题是,PDO rowCount() 似乎为更新的行返回 2x。例如,当我第一次上传 CSV 时,我总共得到 100 行(csv 行的计数)并且 rowCount 返回 100,这是有道理的,因为我插入了 100 行。

但是,如果我再次上传同一个文件,所有 100 行都会更新(我更新了一个 unix 时间戳),并且 rowCount 返回 200。我认为这是因为 rowCount 为每次更新返回 2,而为插入返回 1。

我的假设正确吗?有没有人遇到过这个问题,有没有不涉及 100 个单独的插入语句的解决方案?我希望能够显示 csv 中的总行数、插入的新行总数和更新的总行数。

$sql = 'INSERT INTO projects (' . implode($fields,',') . ') VALUES';
    $rowCount = count($csvData);
    $tmp = array();
    for( $i = 0; $i < $rowCount; $i++ ){
        $placeholders = array();
        foreach( $fields as $key=>$val ){

            /* do some post processing for special characters */
            switch($val){
                case 'description':
                    $value = !empty($csvData[$i][$_POST[$val]]) ? $csvData[$i][$_POST[$val]] : NULL;
                    array_push($tmp,$value);
                break;
                case 'country':
                    $value = !empty( $csvData[$i][$_POST[$val]] ) ?  implode(' ',array_unique(explode(' ', $csvData[$i][$_POST[$val]]))) : NULL;
                    $value = str_replace(array(',','.','\''),'',$value);
                    array_push($tmp,$value);
                break;
                case 'add_unixtime':
                    array_push($tmp,time());
                break;
                case 'project_type':
                    array_push($tmp,strtolower($formData['project_type']));
                break;
                default:
                    $value = !empty($csvData[$i][$_POST[$val]]) ? str_replace(array(',','.','\''),'',$csvData[$i][$_POST[$val]]) : NULL;
                    array_push($tmp,$value);
                break;
            }
            array_push($placeholders,'?');
        }
        $sql .= ' (' . implode($placeholders,',') . '),';
    }
    /*  
        detect duplicate projects based on project_number & project_type
        mysql unique index created with (project_number + project_type)
        if duplicate found, update row
    */
    $sql = rtrim($sql,',');
    $sql .= 'ON DUPLICATE KEY UPDATE';
    foreach($fields as $key=>$val){
        $sql .= ' ' . $val . ' = VALUES(' . $val . '),';
    }
    $sql = rtrim($sql,',');

    /* update database */
    $query = $this->dbc->prepare($sql);
    if( $query->execute($tmp) ){
        $result = array('total_rows'=>$rowCount,'modified_rows'=>$query->rowCount());
    }

    /* return result */
    return $result;

这是为 3 行插入生成的查询。

INSERT INTO projects (project_number, project_value, project_name, 
    address1, address2, city, state, zip, country, description,  
    project_type, add_unixtime ) 
VALUES (?,?,?,?,?,?,?,?,?,?,?,?), 
        (?,?,?,?,?,?,?,?,?,?,?,?), 
        (?,?,?,?,?,?,?,?,?,?,?,?)  
    ON DUPLICATE KEY UPDATE 
        project_number = VALUES(project_number), 
        project_value = VALUES(project_value), 
        project_name = VALUES(project_name), 
        address1 = VALUES(address1), address2 = VALUES(address2), 
        city = VALUES(city), state = VALUES(state), zip = VALUES(zip), 
        country = VALUES(country), description = VALUES(description), 
        project_type = VALUES(project_type), 
        add_unixtime = VALUES(add_unixtime); 
4

1 回答 1

13

根据 MySQL 手册:

使用 ON DUPLICATE KEY UPDATE 时,如果将行作为新行插入,则每行的受影响行值为 1,如果更新现有行,则为 2,如果将现有行设置为其当前值,则为 0。

http://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html

于 2013-02-01T17:34:13.810 回答