Подтвердить что ты не робот

PHP MySQL Скопируйте строку в ту же таблицу... с помощью ключа Primary и Unique

В моей таблице есть две клавиши, одна - идентификатор auto incrementing id (PRIMARY), другой - имя элемента (UNIQUE).

Можно ли дублировать строку в этой же таблице? Я пробовал:

INSERT INTO items
SELECT * FROM items WHERE id = '9198'

Это дает ошибку Duplicate entry '9198' for key 'PRIMARY'

Я также пробовал:

INSERT INTO items
SELECT * FROM items WHERE id = '9198'
ON DUPLICATE KEY UPDATE id=id+1

Что дает ошибка Column 'id' in field list is ambiguous

И что касается поля имени элемента (UNIQUE), есть ли способ добавить (Copy) к имени элемента, так как это поле также должно быть уникальным?

4b9b3361

Ответ 1

Выделить все столбцы явно, кроме столбца id:

INSERT INTO items
(col1, col2, ..., coln)
SELECT col1, col2, ..., coln
FROM items
WHERE id = '9198'

Возможно, ваш следующий вопрос:

Есть ли способ сделать это без однозначного перечисления всех столбцов?

Ответ: Нет, я так не думаю.

Ответ 2

Если вы действительно не хотите перечислять все столбцы таблицы, как в ответе Mark, вы можете попробовать следующее:

CREATE TEMPORARY TABLE temp_tbl SELECT * FROM items WHERE id = '9198';
UPDATE temp_tbl SET id = id + 1;
INSERT INTO items SELECT * FROM temp_tbl;
DROP TABLE temp_tbl;

Не красиво, не быстро. Но работает.

Ответ 3

В качестве альтернативы, если вы не хотите явно писать все столбцы (и не хотите начинать создавать/удалять таблицы), вы можете просто получить столбцы таблицы и автоматически построить запрос:

//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

Обратите внимание, что это использует обесцененный код MySQL, и он должен быть MySQLi. Я уверен, что это также можно улучшить, но это то, что я использую, и оно работает очень хорошо.

Ответ 4

Благодаря 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

Ответ 5

В заголовке вопроса указано, что вы хотите сделать это с PHP.

Я столкнулся с той же проблемой, и все имена столбцов утомительны и сложны в обслуживании, если вы меняете структуру таблиц (добавлять/удалять столбцы)... и мне не нравятся решения, использующие временные таблицы,

Я решил решить эту проблему с двумя запросами, отправленными с PHP - отлично работает и не требует обслуживания (отказ от ответственности: я использую библиотеку meekrodb для доступа к базе данных):

//get the data as an associative array
$row = DB::queryFirstRow("SELECT * FROM your_table WHERE id=%i",$id);
if ($row){
    unset($row["id"]); //unset the primary key
    DB::insert("your_table",$row);
    return DB::insertId();
} else {
    return false;
}

Вы можете даже выполнить больше манипуляций с внутренними данными (отключить другие столбцы, чтобы игнорировать, редактировать значения и т.д.) перед повторной установкой.

Ответ 6

Для таблиц со многими столбцами я использую метод (да, медленный), аналогичный идее Phius. Я поставил его здесь только для полноты.

Предположим, что таблица 'tbl' имеет 'id', определенный как

id INT NOT NULL AUTO_INCREMENT PRIMARY KEY

Затем вы можете клонировать/копировать строку, выполнив следующие шаги:

  • создать таблицу tmp

СОЗДАТЬ ВРЕМЕННЫЙ ТАБЛИЦ tbl_tmp LIKE tbl;

  • Вставьте одну или несколько записей, которые вы хотите клонировать/копировать.

INSERT INTO tbl_tmp SELECT * FROM tbl WHERE...;

  • удалить тег AUTOINCREMENT с 'id'

ALTER TABLE tbl_tmp MODIFY id INT;

  • удалить основной индекс

ALTER TABLE tbl_tmp DROP PRIMARY KEY;

  • обновите свои уникальные индексы и установите "id" на 0 (0 необходимо для выполнения шага 6.)

UPDATE tbl_tmp SET unique_value =?, id = 0;

  • скопируйте измененные строки в 'tbl' с автогенерированием id.

INSERT INTO tbl SELECT * FROM tbl_tmp;

  • очистка (или просто закрыть соединение с БД)

ТАБЛИЦА DROP tbl_tmp;

Если вам также нужно клонировать/копировать некоторые зависимые данные в других таблицах, выполните указанные выше действия для каждой строки. После шага 6 вы можете получить последний вставленный ключ и использовать его для клонировать/копировать зависимые строки в других таблицах, используя ту же процедуру.

Ответ 7

Я удивлен, что кто-то не упомянул об использовании phpMyAdmin для создания запроса. Поскольку это ускорит добавление всех столбцов, а затем вы просто установите id равным null или o, как указано выше, wlf.

Это, безусловно, самый простой способ сделать это

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

Ответ 8

Скажите, что таблица user(id,email,user), и поскольку у вас есть предложение WHERE, вы не можете использовать MAX(id)+1:

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

Помните, что при использовании INSERT вы всегда должны указывать имена столбцов.

Ответ 9

Я хотел скопировать строку в таблицу событий и нашел решение 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).'")'; 

Ответ 10

Это общая функция для копирования записи любой таблицы:

/**
 * @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();
}