Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/289.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PHP MySQL在同一个表中复制一行。。。使用主键和唯一键_Php_Mysql_Duplicates_Row - Fatal编程技术网

PHP MySQL在同一个表中复制一行。。。使用主键和唯一键

PHP MySQL在同一个表中复制一行。。。使用主键和唯一键,php,mysql,duplicates,row,Php,Mysql,Duplicates,Row,我的表有两个键,一个是自动递增的id(主),另一个是项的名称(唯一) 可以在同一个表中复制一行吗?我试过: INSERT INTO items SELECT * FROM items WHERE id = '9198' 这将导致键“PRIMARY”的重复条目“9198”出现错误 我也尝试过: INSERT INTO items SELECT * FROM items WHERE id = '9198' ON DUPLICATE KEY UPDATE id=id+1 字段列表中“id”列的错误

我的表有两个键,一个是自动递增的id(主),另一个是项的名称(唯一)

可以在同一个表中复制一行吗?我试过:

INSERT INTO items
SELECT * FROM items WHERE id = '9198'
这将导致键“PRIMARY”的重复条目“9198”出现错误

我也尝试过:

INSERT INTO items
SELECT * FROM items WHERE id = '9198'
ON DUPLICATE KEY UPDATE id=id+1
字段列表中“id”列的错误
不明确


至于项目名称(唯一)字段,是否有方法将
(复制)
附加到项目名称,因为该字段也必须是唯一的?

明确选择除id列以外的所有列:

INSERT INTO items
(col1, col2, ..., coln)
SELECT col1, col2, ..., coln
FROM items
WHERE id = '9198'
你的下一个问题可能是:

有没有一种方法可以在不显式列出所有列的情况下执行此操作


回答:不,我不这么认为。

如果你真的不想像马克的回答那样列出所有的表列,你可以尝试以下方法:

CREATE TEMPORARY TABLE temp_tbl SELECT * FROM items WHERE id = '9198';
SELECT @maxId := MAX(id) + 1 FROM items;
UPDATE temp_tbl SET id = @maxId;
INSERT INTO items SELECT * FROM temp_tbl;
DROP TABLE temp_tbl;

不漂亮,不快。但是有效。

假设该表是
user(id,email,user)
,因为您有
WHERE
子句,所以不能使用
MAX(id)+1

INSERT INTO users SELECT 0,email,user FROM users WHERE id=10

请记住,在使用INSERT时,您应该始终指定列名。

对于包含许多列的表,我使用类似于Phius idea的(是的,速度慢)方法。
我把它放在这里只是为了完整

假设表'tbl'有一个'id'定义如下

id INT非空自动增量主键

然后,您可以通过以下步骤克隆/复制行:

  • 创建一个tmp表
  • 创建像tbl一样的临时表tbl\U tmp

  • 插入一个或多个要克隆/复制的条目
  • 插入tbl_tmp,从tbl中选择*,其中

  • 从“id”中删除自动增量标记
  • 更改表tbl_tmp修改id INT

  • 删除主索引
  • ALTER TABLE tbl_tmp DROP主键

  • 更新您的唯一索引并将“id”设置为0(步骤6需要0才能工作)
  • 更新tbl_tmp设置唯一值=?,id=0

  • 将修改的行复制到自动生成“id”的“tbl”中
  • 插入tbl,从tbl_tmp中选择*

  • 清理(或仅关闭数据库连接)
  • 升降台tbl_tmp

    如果还需要克隆/复制其他表中的某些从属数据,请执行上述操作 每行。在第6步之后,您可以获取最后一个插入的关键点并使用它来
    使用相同的过程克隆/复制其他表中的依赖行。

    或者,如果不想显式写入所有列(也不想开始创建/删除表),只需获取表的列并自动生成查询:

    //get the columns
    $cols=array();
    $result = mysql_query("SHOW COLUMNS FROM [table]"); 
     while ($r=mysql_fetch_assoc($result)) {
      if (!in_array($r["Field"],array("[unique key]"))) {//add other columns here to want to exclude from the insert
       $cols[]= $r["Field"];
      } //if
    }//while
    
    //build and do the insert       
    $result = mysql_query("SELECT * FROM [table] WHERE [queries against want to duplicate]");
      while($r=mysql_fetch_array($result)) {
        $insertSQL = "INSERT INTO [table] (".implode(", ",$cols).") VALUES (";
        $count=count($cols);
        foreach($cols as $counter=>$col) {
          $insertSQL .= "'".$r[$col]."'";
      if ($counter<$count-1) {$insertSQL .= ", ";}//dont want a , on the last one
        }//foreach
      $insertSQL .= ")";
    
      mysql_query($insertSQL);//execute the query
      }//while
    
    //获取列
    $cols=array();
    $result=mysql\u查询(“显示[表]中的列”);
    而($r=mysql\u fetch\u assoc($result)){
    如果(!in_array($r[“Field”]、array(“[unique key]”)){//在此处添加要从插入中排除的其他列
    $cols[]=$r[“字段”];
    }//如果
    }//当
    //构建并执行插入
    $result=mysql\u query(“从[table]中选择*,其中[querys-on-want-to-duplicate]”;
    而($r=mysql\u fetch\u数组($result)){
    $insertSQL=“插入到[表](“.introde(“,”,$cols)。”)值(“;
    $count=计数($cols);
    foreach($cols作为$counter=>$col){
    $insertSQL.=“'”$r[$col]。“'”;
    
    如果($counter问题标题确实说明您希望从PHP执行此操作

    我也遇到过同样的问题,如果您更改表结构(添加/删除列),写出所有列名既繁琐又难以维护……而且我不喜欢使用临时表的解决方案

    我选择用PHP发送的两个查询来解决这个问题-效果很好,无需维护(免责声明:我使用meekrodb库访问数据库):


    在重新插入之前,您甚至可以对内部数据执行更多操作(取消设置要忽略的其他列、编辑值等)。

    我很惊讶有人没有提到使用phpMyAdmin创建查询。因为这样可以快速添加所有列,然后您只需将id设置为null或o,如wlf所述

    这是迄今为止最简单的方法

    INSERT INTO users SELECT 0,email,user FROM users WHERE id=10
    

    感谢hobailey提供了一个伟大的免维护解决方案

    下面是我最后使用的代码,它是为MySQLi更新的:

    // Get the columns
    $cols = array();
    $result = $mysqli->query("SHOW COLUMNS FROM [TABLE]"); // Change table name
    
    while ($r = $result->fetch_array(MYSQLI_ASSOC)) {
        if (!in_array($r["Field"], array("COLA", "COL4", "COL8"))) { // Edit array with any column names you want to exclude
            $cols[] = $r["Field"];
        }
    }
    
    // Build and do the insert
    $result = $mysqli->query("SELECT * FROM [TABLE] WHERE [SELECTION CRITERIA];"); // Change table name and add selection criteria
    
    while ($r = $result->fetch_array(MYSQLI_ASSOC)) {
    
        $insertSQL = "INSERT INTO [TABLE] (" . implode(", ",$cols) . ") VALUES ("; // Change table name
        $count = count($cols);
    
        foreach($cols as $counter=>$col) {
    // This is where you can add any code to change the value of existing columns
            $insertSQL .= "'" . $mysqli->real_escape_string($r[$col]) . "'";
            if ($counter < ($count - 1)) {
                $insertSQL .= ", ";
            }
        } // END foreach
    
        $insertSQL .= ");";
    
        $mysqli->query($insertSQL);
        if ($mysqli->affected_rows < 1) {
    // Add code if the insert fails
        } else {
    // Add code if the insert is successful
        }
    
    } // END while
    
    //获取列
    $cols=array();
    $result=$mysqli->query(“显示[表]中的列”);//更改表名
    而($r=$result->fetch_数组(MYSQLI_ASSOC)){
    如果(!in_array($r[“Field”]、array(“COLA”、“COL4”、“COL8”)){//使用要排除的任何列名编辑数组
    $cols[]=$r[“字段”];
    }
    }
    //构建并执行插入
    $result=$mysqli->query(“从[表]中选择*其中[选择条件];”;//更改表名并添加选择条件
    而($r=$result->fetch_数组(MYSQLI_ASSOC)){
    $insertSQL=“INSERT INTO[TABLE](“.implode(,”,$cols)。”)值(;//更改表名
    $count=计数($cols);
    foreach($cols作为$counter=>$col){
    //在这里,您可以添加任何代码来更改现有列的值
    $insertSQL.=“'”“$mysqli->real\u escape\u字符串($r[$col])”;
    如果($计数器<($计数-1)){
    $insertSQL.=“,”;
    }
    }//结束foreach
    $insertSQL.=”;”;
    $mysqli->query($insertSQL);
    如果($mysqli->受影响的_行<1){
    //如果插入失败,请添加代码
    }否则{
    //如果插入成功,请添加代码
    }
    }//结束时
    
    我想复制事件表中的一行,发现Mark的解决方案非常有用。我把它缩短了一点

    public static function getColumnsOfTable($table,  $arr_exclude_cols=array()) {
        global $obj_db;
    
        $cols = array();
        $result = $obj_db->query("SHOW COLUMNS FROM `".$table."`");
    
        while ($r = $result->fetch_array(MYSQLI_ASSOC)) {
            if (!in_array($r["Field"], $arr_exclude_cols)) { 
                $cols[] = $r["Field"];
            }
        }
    
        return $cols;
    }
    
    以及复制的代码:

    $cols = Utils::getColumnsOfTable('events', array('event_id'));
    
        $result1 = $obj_db->query('SELECT * FROM `events` WHERE `event_id` = '.$event_id);
        $arr_event = mysqli_fetch_array($result1, MYSQLI_NUM);
        unset($arr_event[0]);
    
        $insertSQL =  'INSERT INTO `events` (`' . implode('`, `',$cols) . '`) VALUES ("'. implode('","', $arr_event).'")'; 
    

    这是复制任何表的记录的常规功能:

    /**
     * @param string $table         Name of table
     * @param array $primaryKey     Which record should be copied? array('nameOfColumnWithUniqueId' => "value")
     * @param array $excludeFields  Which columns should not be copied (e.q. Unique Cols)
     * @param string $database      Name of database
     * @return int                  ID of new inserted record
     */
    function copyMysqlRow($table, $primaryKey, $excludeFields = array(), $database = "usr_web3_2")
    {
        $field = key($primaryKey);
        $value = current($primaryKey);
        $sql = "
            SELECT
                *
            FROM
                $database.$table
            WHERE
              $field = '$value'
        ";
    
        $result = mysql_query($sql);
        $row = mysql_fetch_assoc($result);
    
        $cols = array();
        $values = array();
        foreach ($row AS $col=>$value) {
            if (!in_array($col, $excludeFields)) {
                $cols[] = "`" . $col . "`";
                $values[] = $value === null ? 'null' : "'" . $value . "'";
            }
        }
    
        $sql = sprintf(" INSERT INTO $database.$table (%s) VALUES  (%s) ", implode($cols, ','), implode($values, ','));
    
        mysql_query($sql);
    
        return mysql_insert_id();
    }
    

    PHP中的另一种解决方案,用于复制同一表中的行,但不包含特定列/例如主键,且不包含“临时表”和“显示来自…”方法:

    INSERT是一条SELECT语句,因此该语句中的值不是直接的-->没有问题
    /**
     * @param string $table         Name of table
     * @param array $primaryKey     Which record should be copied? array('nameOfColumnWithUniqueId' => "value")
     * @param array $excludeFields  Which columns should not be copied (e.q. Unique Cols)
     * @param string $database      Name of database
     * @return int                  ID of new inserted record
     */
    function copyMysqlRow($table, $primaryKey, $excludeFields = array(), $database = "usr_web3_2")
    {
        $field = key($primaryKey);
        $value = current($primaryKey);
        $sql = "
            SELECT
                *
            FROM
                $database.$table
            WHERE
              $field = '$value'
        ";
    
        $result = mysql_query($sql);
        $row = mysql_fetch_assoc($result);
    
        $cols = array();
        $values = array();
        foreach ($row AS $col=>$value) {
            if (!in_array($col, $excludeFields)) {
                $cols[] = "`" . $col . "`";
                $values[] = $value === null ? 'null' : "'" . $value . "'";
            }
        }
    
        $sql = sprintf(" INSERT INTO $database.$table (%s) VALUES  (%s) ", implode($cols, ','), implode($values, ','));
    
        mysql_query($sql);
    
        return mysql_insert_id();
    }
    
    $stmt = $db->prepare("select * from table where id = :id;");
    $stmt->bindValue(':id', $_GET['id'], PDO::PARAM_INT);
    $stmt->execute();
    $row = $stmt->fetch(PDO::FETCH_ASSOC);
    unset($row['id']);      //remove primary key
    
    $columns = array_keys($row);
    $query = "insert into table (`".implode('`, `', $columns)."`) select `".implode('`, `', $columns)."` from  data_ticket_serie where id = ".$_GET['id'].";";
    // echo $query;
    $stmt = $db->prepare($query);
    $stmt->execute();
    
    $copy_table_row = array(
        'table'=>'purchase_orders',     //table name
        'primary'=>'purchaseOrderID',   //primary key (or whatever column you're lookin up with index)
        'index'=>4084,                  //primary key index number
        'fields' => array(
            'siteID',             //copy colunm
            ['supplierID'=>21],   //overwrite this column to arbirary value by wrapping it in an array
            'status',             //copy colunm
            ['notes'=>'copied'],  //changes to "copied"
            'dateCreated',        //copy colunm
            'approved',           //copy colunm
        ),
    );
    echo copy_table_row($copy_table_row);
    
    
    
    function copy_table_row($cfg){
        $d=[];
        foreach($cfg['fields'] as $i => $f){
            if(is_array($f)){
                $d['insert'][$i] = "`".current(array_keys($f))."`";
                $d['select'][$i] = "'".current($f)."'";
            }else{
                $d['insert'][$i] = "`".$f."`";
                $d['select'][$i] = "`".$f."`";
            }
        }
        $sql = "INSERT INTO `".$cfg['table']."` (".implode(', ',$d['insert']).")
            SELECT ".implode(',',$d['select'])."
            FROM `".$cfg['table']."`
            WHERE `".$cfg['primary']."` = '".$cfg['index']."';";
        return $sql;
    }
    
    INSERT INTO `purchase_orders` (`siteID`, `supplierID`, `status`, `notes`, `dateCreated`, `approved`)
    SELECT `siteID`,'21',`status`,'copied',`dateCreated`,`approved`
    FROM `purchase_orders`
    WHERE `purchaseOrderID` = '4084';