[英]Copying rows from multiple tables with php and mysql
我正在為一個應用程序構建復制活動功能,而我的操作方式是使用循環使用php瀏覽所有選定的行,獲取其ID並再次循環以插入具有相同數據但列值已更改的新行。 這是我目前的最佳方法:
<?php
$id = Url::find('id');
//Copy campaign row
$cid = $this->Db->Query("
INSERT INTO campaigns (`user_id`, `tid`, `featured`, `opt`, `title`, `uri`, `cpi`, `payout`, `cat`, `domain`, `created`, `disabled`, `completed`, `featured_pos`)
SELECT `user_id`, `tid`, `featured`, `opt`, CONCAT(`title`,' - Copy'), `uri`, `cpi`, `payout`, `cat`, `domain`, `created`, `disabled`, `completed`, `featured_pos` FROM campaigns WHERE id = :id
",array(':id' => array(DB::INT => $id)),true);
//Copy variants
$vars = $this->Db->selectAll(array('cid' => $id), 'variations');
if(!empty($vars)) {
for($i = 0; $i < count($vars); $i++) {
$old[] = $vars[$i]['id']; //Copy source
$vid[] = $this->Db->Query("
INSERT INTO variations (`ordering`, `disabled`, `cid`, `height`, `width`, `bgcolor`, `head`,`title`, `keywords`, `description`, `link`)
SELECT `ordering`, `disabled`, :cid, `height`, `width`, `bgcolor`, `head`, `title`, `keywords`, `description`, `link` FROM variations WHERE id = :id
",array(
':id' => array(DB::INT => $vars[$i]['id']),
':cid' => array(DB::INT => $cid)
),true);
}
}
//Copy elements
if(isset($vid)) {
for($i = 0; $i < count($vid); $i++) {
$this->Db->Query("
INSERT INTO elements (`name`, `var`, `type`, `left`, `top`, `width`, `height`, `z-index`, `html`, `css`)
SELECT `name`, :vid, `type`, `left`, `top`, `width`, `height`, `z-index`, `html`, `css` FROM elements WHERE var = :id
",array(
':vid' => array(DB::INT => $vid[$i]),
':id' => array(DB::INT => $old[$i])
),true);
}
}
echo "OK";
?>
但是我確定這不是最好的方法,因為它執行太多的查詢。 我已經升級了腳本,但是我不知道如何使用新版本的新ID將行復制到elements表中。 新腳本:
$id = Url::find('id');
$cid = $this->Db->Query("
INSERT INTO campaigns (`user_id`, `featured`, `title`, `domain`, `created`, `disabled`, `featured_pos`)
SELECT :user, `featured`, CONCAT(`title`,' - Copy'), `domain`, `created`, `disabled`, `featured_pos` FROM campaigns WHERE id = :id
",array(':id' => array(DB::INT => $id), ':user' => array(DB::INT => $this->session->user['id'])),true);
//Copy variants
$this->Db->Query("
INSERT INTO variations (`ordering`, `disabled`, `cid`, `height`, `width`, `bgcolor`, `head`,`title`, `keywords`, `description`, `link`)
SELECT `ordering`, `disabled`, :id, `height`, `width`, `bgcolor`, `head`, `title`, `keywords`, `description`, `link` FROM variations WHERE cid = :oid
",array(
':id' => array(DB::INT => $cid), //new id
':oid' => array(DB::INT => $id) //old id
),true);
$this->Db->Query("
INSERT INTO elements (`name`, `var`, `html`, `type`)
SELECT e.name, v.id, e.html, e.type FROM elements AS e, variations AS v
WHERE v.cid = :cid AND e.var = v.id
",array(
':cid' => array(DB::INT => $id)
),true);
前兩個查詢按預期工作,但是最后一個(INSERT INTO元素)無效。 這是因為它從舊廣告系列中選擇了變體,然后將舊ID插入到var列中,而不是之前插入的新ID。 顯然,這是因為查詢是通過這種方式構建的,但是如何從新版本中獲取ID,而無需循環將其插入到元素中。 (或者我是否過於偏執並且我最初的方法還不錯?)
為了更清楚地說明我的問題-如何在沒有php循環的情況下執行此操作:
INSERT INTO elements (`name`, `var`, `html`, `type`)
SELECT e.name, (new v.id from the previous query and not the same one as in WHERE clause), e.html, e.type FROM elements AS e, variations AS v
WHERE v.cid = :cid AND e.var = v.id
抱歉我的語法錯誤(我剛上班需要喝杯咖啡)
非常感謝 :)
不太確定我是否理解您的要求,因為事實上,您的問題中包含太多的原因信息。 我將嘗試僅回答您的最后一個問題:
INSERT INTO elements (`name`, `var`, `html`, `type`)
SELECT e.name, (new v.id from the previous query and not the same one as in WHERE clause), e.html, e.type FROM elements AS e, variations AS v
WHERE v.cid = :cid AND e.var = v.id
同樣,如果我錯過了重點,請不要苛刻:)
因此,您要插入一堆行,然后基於這些ID要將其插入到不同的表中? 因此,如果只有您(誰在使用系統),那么簡單的方法就是獲取插入行的ID,例如,如果您知道插入行的數量,那么僅獲取最后n行? 或添加具有唯一ID的另一列,因此您只能從中獲取。 然后將ID放入數組中,並用冒號將它們連接起來,最后,您的查詢應如下所示:
INSERT INTO elements (`name`, `var`, `html`, `type`)
SELECT e.name, (new v.id from the previous query and not the same one as in WHERE clause), e.html, e.type FROM elements AS e, variations AS v
WHERE v.cid IN($c_ids) AND e.var IN($v_ids)
因此,總而言之:-insert-獲取插入的c id -insert-獲取插入的v id -join c ids -join v id-使用查詢
而且我不知道查詢如何與以下內容一起工作:
INSERT INTO campaigns (`user_id`, `featured`, `title`, `domain`, `created`, `disabled`, `featured_pos`)
SELECT :user, `featured`, CONCAT(`title`,' - Copy'), `domain`, `created`, `disabled`, `featured_pos` FROM campaigns WHERE id = :id
",array(':id' => array(DB::INT => $id)
我確實希望它不會一一插入1000行。 但是,如果這樣做的話(我想您對此很偏執),請在php中使用joins,這樣可以減少發送到sql的文本量,尤其是減少調用的查詢量。 如果行數很多,那么花費的時間將非常可觀。
如果這是您需要遵循的常規過程,那么按照我的觀點,最好定義一個函數,並在該函數內部使用您的邏輯。 由於函數是預編譯的,因此執行速度很快。 而在前端只需調用該函數。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.