php在DUPLICATE KEY UPDATE上也显示1062:键“ PRIMARY”的重复条目

时间:2018-06-22 09:19:10

标签: php json on-duplicate-key mysql-error-1062

有一个在线数据库。该数据库在本地和在线具有相同的架构,并具有25个以上的表。我正在通过JSON文件发送INSERT或UPDATE记录。 id是所有表的关键字段。 JSON文件可能包含要插入的新id记录和要更新整个在线表字段的旧id字段。

以下是在线counters表。

+-------+---------+---------------+---------------------+---------------------+------------+
| id    | name    | description   | added_on            | last_updated        | department |
+-------+---------+---------------+---------------------+---------------------+------------+
| 1     | A       | Bill          | 2018-02-18 21:48:28 | 2018-02-18 15:08:34 | 1          |
| 2     | B       | SAKTHY        | 2018-06-21 12:49:30 | 2018-02-18 12:49:40 | 1          |
| 3     | C       |               | 2018-02-18 21:48:28 | 2018-02-18 21:48:28 | 1          |
+-------+---------+---------------+---------------------+---------------------+------------+

以下数据通过JSON文件传递到在线数据库。

[
  {
    "tableName": "bank_accounts",
    "rows": []
  },
  {
    "tableName": "counters",
    "rows": [
      {
        "id": "2",
        "name": "B",
        "description": "SAKTHY",
        "added_on": "2018-06-21T12:49:30",
        "last_updated": "2018-02-18T12:49:40",
        "department": "1"
      },
      {
        "id": "5",
        "name": "E",
        "description": "SAKTHY2",
        "added_on": "2018-06-21T12:50:21",
        "last_updated": "2018-06-21T14:52:18",
        "department": "1"
      },
      {
        "id": "6",
        "name": "SAKTHY3",
        "description": "Sample Friday",
        "added_on": "2018-06-22T10:47:18",
        "last_updated": "2018-06-22T10:47:18",
        "department": "1"
      }
    ]
  },
  {
    "tableName": "customers",
    "rows": []
  }
]

要将记录INSERTUPDATE存入在线数据库,将使用此php脚本(感谢@Sloan Thrasher,@ lovepreet-singh)。

<?php
    try
    {
        $connect = mysqli_connect("localhost", "username", "password", "database"); 
        $query = '';
        $table_data = '';
        $filename = "sample.json";

        $data = file_get_contents($filename);
        $array = json_decode($data, true); 

        foreach($array as $set) 
        {
            $tblName = $set['tableName'];
            if(sizeof($set['rows']) > 0) 
            {
                $query = '';
                $colList = array();
                $valList = array();
                //  Get list of column names
                foreach($set['rows'][0] as $colName => $dataval) 
                {
                    $colList[] = "`".$colName."`";
                }
                $query .= "INSERT INTO `".$tblName."` \n";
                $query .= "(".implode(",",$colList).")\nVALUES\n";
                //  Go through the rows for this table.
                foreach($set['rows'] as $idx => $row) 
                {
                    $colDataA = array();
                    //  Get the data values for this row.
                    foreach($row as $colName => $colData) 
                    {
                        $colDataA[] = "'".$colData."'";
                    }
                    $valList[] = "(".implode(",",$colDataA).")";
                }
                //  Add values to the query.
                $query .= implode(",\n",$valList)."\n";

                //  If id column present, add ON DUPLICATE KEY UPDATE clause
                if(in_array("id", $colList)) 
                {
                    $query .= "ON DUPLICATE KEY UPDATE\n\t SET ";
                    $tmp = array();
                    foreach($colList as $idx => $colName) 
                    {
                        //$tmp[] = $colName." = new.".$colName." ";
                        $tmp[] = $colName." = VALUE(".$colName.") ";    //  Changed this line to get value from current insert row data
                    }
                    $query .= implode(",",$tmp)."\n";
                } 
                else 
                {
                    echo "<p><b>`id`</b> column not found. <i>ON DUPLICATE KEY UPDATE</i> clause <b>NOT</b> added.</p>\n";
                    echo "<p>Columns Found:<pre>".print_r($colList, true)."</pre></p>\n";
                }
                echo "<p>Insert query:<pre>$query</pre></p>";
                $r = mysqli_query($connect, $query);  

                echo mysqli_errno($connect) . ": " . mysqli_error($connect) . "\n";

                echo "<h1>".mysqli_affected_rows($connect). " Rows appended in .$tblName.</h1>";
            } 
            else 
            {
                echo "<p>No rows to insert for .$tblName.</p>";
            }
        }
    } 

    catch(Exception $e)
    {   
        echo $e->getMessage();  
    }
?>

但是我在浏览器中得到了以下SQL回显。在这种情况下,在线数据库不会更新或插入新记录。

No rows to insert for .bank_accounts.

`id` column not found. ON DUPLICATE KEY UPDATE clause NOT added.

Columns Found:

Array
(
    [0] => `id`
    [1] => `name`
    [2] => `description`
    [3] => `added_on`
    [4] => `last_updated`
    [5] => `department`
)
Insert query:

INSERT INTO `counters` 
(`id`,`name`,`description`,`added_on`,`last_updated`,`department`)
VALUES
('2','B','SAKTHY','2018-06-21T12:49:30','2018-02-18T12:49:40','1'),
('5','E','SAKTHY2','2018-06-21T12:50:21','2018-06-21T14:52:18','1'),
('6','SAKTHY3','Sample Friday','2018-06-22T10:47:18','2018-06-22T10:47:18','1')

1062: Duplicate entry '2' for key 'PRIMARY'

-1 Rows appended in .counters.

No rows to insert for .customers.

3 个答案:

答案 0 :(得分:1)

尝试替换脚本的这一部分:

if(in_array("id", $colList))
{
    $query .= "ON DUPLICATE KEY UPDATE\n\t SET ";
    $tmp = array();
    foreach($colList as $idx => $colName)
    {
        //$tmp[] = $colName." = new.".$colName." ";
        $tmp[] = $colName." = VALUE(".$colName.") ";    //  Changed this line to get value from current insert row data
    }
    $query .= implode(",",$tmp)."\n";
}
else
{
    echo "<p><b>`id`</b> column not found. <i>ON DUPLICATE KEY UPDATE</i> clause <b>NOT</b> added.</p>\n";
    echo "<p>Columns Found:<pre>".print_r($colList, true)."</pre></p>\n";
}

与:

$query .= "ON DUPLICATE KEY UPDATE\n\t ";
$tmp = array();
foreach($colList as $idx => $colName)
{
    //$tmp[] = $colName." = new.".$colName." ";
    $tmp[] = $colName." = VALUES(".$colName.") ";    //  Changed this line to get value from current insert row data
}
$query .= implode(",",$tmp)."\n";

答案 1 :(得分:1)

您遇到的问题是,在代码中,您具有以下内容:

$colList[] = "`".$colName."`";

然后您要检查:

if(in_array("id", $colList))

在添加到数组时,您在第in_array部分中未搜索的列名周围打了勾。

$colList附加项更改为:

$colList[] = $colName;

或将数组搜索为:

if(in_array("`id`", $colList))

答案 2 :(得分:1)

您的问题出在支票

if(in_array("id", $colList))

将其更改为

if(in_array("`id`", $colList))

也要更改

$tmp[] = $colName." = VALUE(".$colName.") ";

$tmp[] = "{$colName} = {$colName}";

编辑:下面您将找到我的代码版本。希望这会有所帮助:

<?php
try
{
    $connect  = mysqli_connect("localhost", "username", "password", "database"); 
    $filename = "sample.json";
    $dataSets = json_decode(file_get_contents($filename), true);

    if (is_null($dataSets)) {
        throw new Exception(json_last_error_msg());
    }

    foreach($dataSets as $dataSet)
    {
        $tblName     = $dataSet['tableName'];
        $dataSetRows = $dataSet['rows'];

        if (!$dataSetRows) {
            echo "<p>No rows to insert for . $tblName . </p>";
            continue;
        }

        foreach($dataSetRows as $dataSetRow){

            $colList = array_keys($dataSetRow);
            $valList = array_values($dataSetRow);

            $query = "INSERT INTO {$tblName} (" . implode(",", $colList) . ") VALUES (\"" . implode('","', $valList) . '")';

            if(in_array("id", $colList)) {

                $query .= " ON DUPLICATE KEY UPDATE ";

                array_walk($dataSetRow, function($val, $col) use (&$query){
                    if($col !=='id') {
                        $query .= "{$col} = \"{$val}\",";
                    };
                });
            }

            $query = rtrim($query, ',');

            echo "<p>Insert query:<pre>$query</pre></p>";

            mysqli_query($connect, $query);

            echo mysqli_errno($connect) . ": " . mysqli_error($connect) . "\n";

            echo "<h1>".mysqli_affected_rows($connect). " Rows appended in .$tblName.</h1>";
        }
    }
} catch(Exception $e) {
    echo $e->getMessage();
}