2012-07-26 20 views
13

मेरी तालिका में दो कुंजी हैं, एक ऑटो वृद्धिशील आईडी (प्राथमिक) है, दूसरा आइटम (अद्वितीय) का नाम है।PHP MySQL एक ही तालिका के भीतर एक पंक्ति की प्रतिलिपि बनाएँ ... प्राथमिक और अद्वितीय कुंजी

क्या इस तालिका में एक पंक्ति डुप्लिकेट करना संभव है? मैंने कोशिश की है:

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

और जहाँ तक आइटम नाम के रूप में (अद्वितीय) फ़ील्ड जाता है, क्या आइटम नाम पर (Copy) जोड़ने का कोई तरीका है, क्योंकि यह फ़ील्ड भी अद्वितीय होना चाहिए?

+1

आईडी को छोड़कर सभी पंक्तियों का चयन करने का प्रयास करें, मान लें कि आपकी आईडी ऑटो वृद्धि है, यह स्वचालित रूप से अपडेट हो जाएगी। – databyss

+0

@ डाटाबेस जो काम करेगा, लेकिन मैं एक वैकल्पिक विधि की तलाश में हूं, क्योंकि इस तालिका में कुछ सौ कॉलम हैं। – Norse

+0

कॉलम नाम कॉपी और पेस्ट करें। – databyss

उत्तर

36

आईडी स्तंभ को छोड़कर, स्पष्ट रूप से सभी स्तंभों का चयन करें:

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

आपका अगला सवाल शायद हो जाएगा:

वहाँ स्पष्ट रूप से सभी स्तंभों लिस्टिंग के बिना यह करने के लिए कोई तरीका है?

उत्तर: नहीं, मुझे ऐसा नहीं लगता है।

+0

कॉलम को स्पष्ट रूप से सूचीबद्ध किए बिना ऐसा करने के लिए मार्क के उत्तर को देखें। –

19

आप वास्तव में मार्क के जवाब में की तरह सभी तालिका स्तंभ को सूचीबद्ध नहीं करना चाहते हैं, तो आप इस कोशिश कर सकते हैं:

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

+1 एर ... दिलचस्प ... :-) –

+0

यह उदाहरण मेरे लिए काम किया। मैंने अभी सुनिश्चित किया है कि जब मैंने इसे एकाधिक उपयोगकर्ताओं के साथ उपयोग किया, तो मैंने temp_tbl में एक अतिरिक्त हिस्सा जोड़ा, इसलिए यह उस उपयोगकर्ता के लिए अद्वितीय था। मैंने निम्न पंक्ति भी जोड़ा: अद्यतन temp_tbl SET field_that_needs_to_use_a_title = CONCAT ('डिप्लिकेट', field_that_needs_to_use_a_title) जहां आईडी = '9 1 9 8'; –

0

कहो तालिका user(id,email,user) है और आप MAX(id)+1 उपयोग नहीं कर सकते, क्योंकि आप एक WHERE खंड है: ध्यान में

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

भालू हालांकि है कि आप हमेशा स्तंभ नाम जब सम्मिलित करें का उपयोग कर निर्दिष्ट करना चाहिए।

1

कई कॉलम वाले टेबल के लिए, मैं फ़ियस विचार के समान एक (हाँ, धीमी) विधि का उपयोग करता हूं।
मैंने इसे पूर्णता के लिए यहां रखा है।

के मान लेते हैं, टेबल 'tbl' कोई 'आईडी'

आईडी INT की तरह परिभाषित किया गया है नहीं NULL AUTO_INCREMENT प्राथमिक कुंजी

तो फिर तुम क्लोन कर सकते हैं/इन चरणों का पालन करके एक पंक्ति कॉपी:

  1. एक tmp तालिका बनाने

टेम्पलेट टेबल बनाएं tbl_tmp LIKE tbl;

  1. सम्मिलित एक या अधिक प्रविष्टियों आप/कॉपी

INSERT INTO tbl से चयन tbl_tmp * क्लोन करने के लिए चाहते हैं, जहां ...;

  1. tbl_tmp आईडी INT संशोधित 'आईडी'

ALTER तालिका से AutoIncrement टैग निकालना;

  1. ड्रॉप प्राथमिक सूचकांक

ALTER तालिका tbl_tmp प्राथमिक कुंजी छोड़;

  1. अद्यतन अपने अद्वितीय सूचकांक और 0 पर सेट 'आईडी' (0 काम करने के लिए कदम 6. के लिए आवश्यक)

अद्यतन tbl_tmp सेट unique_value = ?, आईडी = 0;

  1. 'आईडी' ऑटोजनरेटेड किया जा रहा है 'tbl' में अपने संशोधित पंक्तियां कॉपी।

tbl चुनें * tbl_tmp से में डालने;

  1. सफाई (या बस DB कनेक्शन बंद)

ड्रॉप तालिका tbl_tmp;

यदि आपको क्लोन की आवश्यकता है/अन्य तालिकाओं में कुछ निर्भर डेटा कॉपी करें, तो प्रत्येक पंक्ति के लिए उपरोक्त करें। चरण 6 के बाद आप अंतिम डाली गई कुंजी प्राप्त कर सकते हैं और इसे क्लोन/उसी प्रक्रिया का उपयोग करके अन्य तालिकाओं के भीतर निर्भर पंक्तियों की प्रतिलिपि बना सकते हैं।

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 होना चाहिए। मुझे यकीन है कि यह भी सुधार किया जा सकता है, लेकिन मैं इसका उपयोग कर रहा हूं और यह बहुत अच्छी तरह से काम करता है।

2

प्रश्न शीर्षक यह बताता है कि आप इसे PHP से करना चाहते हैं।

मुझे एक ही समस्या का सामना करना पड़ा है और यदि आप अपनी टेबल संरचना (कॉलम जोड़ें/हटाएं) बदलते हैं तो सभी कॉलम नामों को लिखना कठिन और कठिन है ... और मुझे उन समाधानों को पसंद नहीं है जो temp का उपयोग करते हैं टेबल। यहां तक ​​कि

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

आप कर सकते हैं:: अच्छा काम करता है और कोई रखरखाव की आवश्यकता (मैं डेटाबेस का उपयोग के लिए meekrodb लाइब्रेरी का उपयोग अस्वीकरण) -

मैं PHP से भेजे गए दो प्रश्नों के साथ इस समस्या को हल करने का निर्णय लिया दोबारा डालने से पहले आंतरिक डेटा पर अधिक कुशलताएं (अनदेखा करने के लिए अन्य कॉलम अनसेट करें, मानों को संपादित करें, आदि) करें।

1

मुझे आश्चर्य है कि किसी ने क्वेरी बनाने के लिए phpMyAdmin का उपयोग करके उल्लेख नहीं किया है। क्योंकि इससे सभी कॉलम जोड़ने में तेज़ी होगी और फिर आप आईडी को ऊपर या ऊपर उल्लिखित रूप में उल्लिखित कर सकते हैं जैसा कि ऊपर उल्लिखित है।

यह यह करने के लिए

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

धन्यवाद एक महान रखरखाव मुक्त समाधान प्रदान करने के लिए hobailey को अब तक का सबसे सरल उपाय कर रहा है।

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

सुंदर नहीं है लेकिन नौकरी करता है! क्या लाइन '$ mysqli-> real_escape_string ($ r [$ col])' मान आवश्यक है कि मान पहले से ही डेटाबेस में हैं? –

+1

हां भागने की आवश्यकता है - पाठ में उद्धरण के साथ इसे आज़माएं - या पीडीओ/बाध्य पैराम्स का उपयोग करें – anoldermark

0

मैं अपनी घटनाओं तालिका में एक पंक्ति नकल करना चाहता था और मार्क समाधान बहुत उपयोगी पाया:

यहाँ कोड मैं का उपयोग कर, mysqli के लिए अद्यतन किया जाता है जो समाप्त हो गया है। मैंने इसे थोड़ा छोटा बना दिया।

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).'")'; 
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(); 
} 
+0

इंपोड्स गलत तरीके से हैं! - - - - - - - - - - - - - - - - यह होना चाहिए: $ sql = sprintf ("$ तालिका (% s) मान (% s) में डालने", फटना (',' , $ cols), implode (',', $ मान)); - - - - - अन्यथा यह एक अच्छा समाधान है – anoldermark

+0

इस माध्यमिक टिप्पणी को हटा नहीं सकता - मुझे ऊपर लाइन ब्रेक की आवश्यकता है – anoldermark

0

पीएचपी में एक अन्य समाधान एक विशिष्ट तालिका (ओं)/उदाहरण के बिना एक ही तालिका में प्राथमिक कुंजी - और बिना "अस्थायी तालिका" और "से ... स्तंभ दिखाएं" - विधि:

$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(); 

सम्मिलित एक का चयन करें बयान है, इसलिए मान बयान में प्रत्यक्ष नहीं कर रहे हैं -> कोई समस्या नहीं "real_escape_string" या उसके जैसा कुछ।

संबंधित मुद्दे