14

CSVをアップロードしてMySQLテーブルを更新するプロジェクトに取り組んでいます。sql insertステートメントの最後に、「onduplicatekeyupdate...」ステートメントがあります。

私の問題は、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 に答える