24

私のテーブルには 2 つのキーがあります。1 つは自動インクリメント ID (PRIMARY)、もう 1 つはアイテムの名前 (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)、このフィールドも一意でなければならないため、アイテム名に追加する方法はありますか?

4

14 に答える 14

51

id 列を除くすべての列を明示的に選択します。

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

次の質問はおそらく次のとおりです。

すべての列を明示的にリストせずにこれを行う方法はありますか?

答え: いいえ、そうは思いません。

于 2012-07-26T01:05:39.147 に答える
28

Markの回答のようにすべてのテーブル列を一覧表示したくない場合は、次の方法を試すことができます。

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;

美しくなく、速くもありません。しかし、動作します。

于 2012-07-26T01:28:11.360 に答える
5

優れたメンテナンスフリーのソリューションを提供してくれた 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
于 2015-08-08T20:18:06.937 に答える
4

または、すべての列を明示的に書き込みたくない場合 (およびテーブルの作成/削除を開始したくない場合) は、テーブルの列を取得してクエリを自動的に作成できます。

//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 である必要があることに注意してください。それも改善できると確信していますが、それは私が使用しているものであり、非常にうまく機能します。

于 2013-12-02T13:33:46.300 に答える
1

多くの列を持つテーブルの場合、Phius のアイデアに似た (はい、遅い) メソッドを使用します。
完全を期すためにここに置きます。

テーブル「tbl」には次のように定義された「id」があると仮定しましょう

id INT NOT NULL AUTO_INCREMENT 主キー

次に、次の手順に従って行を複製/コピーできます。

  1. 一時テーブルを作成する

一時テーブル tbl_tmp を tbl のように作成します。

  1. クローン/コピーするエントリを 1 つ以上挿入します

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

  1. 「id」から AUTOINCREMENT タグを削除します

ALTER TABLE tbl_tmp MODIFY id INT;

  1. プライマリ インデックスを削除する

ALTER TABLE tbl_tmp DROP PRIMARY KEY;

  1. 一意のインデックスを更新し、「id」を 0 に設定します (ステップ 6. を機能させるには 0 が必要です)。

UPDATE tbl_tmp SET unique_value=?,id=0;

  1. 「id」が自動生成された状態で、変更した行を「tbl」にコピーします。

tbl SELECT * FROM tbl_tmp; に挿入します。

  1. クリーンアップ (または単に DB 接続を閉じます)

DROP TABLE tbl_tmp;

他のテーブルの依存データを複製/コピーする必要がある場合は、各行に対して上記を実行します。手順 6 の後、最後に挿入されたキーを取得し、これを使用して、同じ手順を使用して他のテーブル内の依存行を複製/コピーできます。

于 2013-11-26T14:29:22.767 に答える
1

phpMyAdmin を使用してクエリを作成することについて誰も言及していないことに驚いています。これにより、すべての列をすばやく追加できるため、上記の wlf で説明したように、id を null または o に設定するだけです。

これは、これを行う最も簡単な方法です

INSERT INTO users SELECT 0,email,user FROM users WHERE id=10
于 2015-04-20T16:40:05.250 に答える
0

イベント テーブルの行をコピーしたかったのですが、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).'")'; 
于 2016-01-24T14:04:56.837 に答える
0

テーブルがuser(id,email,user)and であるとします。WHERE使用できない句があるためですMAX(id)+1

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

ただし、INSERT を使用するときは常に列名を指定する必要があることに注意してください。

于 2012-10-23T22:24:18.057 に答える
0

これは、任意のテーブルのレコードをコピーするための一般的な関数です。

/**
 * @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();
}
于 2016-12-28T21:31:22.117 に答える
0

私はこれを使用します... temp_tbl に主キー列を削除するため、ID の重複に問題はありません

CREATE TEMPORARY TABLE temp_tbl SELECT * FROM table_to_clone;
ALTER TABLE temp_tbl DROP COLUMN id;
INSERT INTO table_to_clone SELECT NULL, temp_tbl.* FROM temp_tbl;
DROP TABLE temp_tbl;
于 2022-02-16T20:23:14.800 に答える