Копирование строк из нескольких таблиц с помощью php и mysql - PullRequest
2 голосов
/ 30 ноября 2011

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

<?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 = 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);

Первые 2 запроса работают как положено, однако последний (элементы INSERT INTO) - нет. Это потому, что он выбирает варианты из старой кампании и вставляет в столбец var старые идентификаторы вместо ранее вставленных новых. Очевидно, это потому, что запрос построен таким образом, но как мне получить идентификаторы из новых вариантов без цикла, чтобы вставить их в элементы. (Или я слишком много параноик, и мой первоначальный подход в порядке?)

Чтобы быть более понятным с моим вопросом - как мне сделать это без цикла 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

Извините за мои грамматические ошибки (я только что приступил к работе и мне нужен кофе)

Большое спасибо:)

Ответы [ 2 ]

0 голосов
/ 27 апреля 2012

Не совсем уверен, что я понял, о чем вы спрашиваете, потому что, по сути, ваш вопрос содержал слишком много информации для причины. Я постараюсь ответить только на ваш последний вопрос:

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

Опять же, не будь резким, если я упустил смысл:)

Итак, вы вставляете несколько строк, а затем, основываясь на их идентификаторах, хотите вставить их в другую таблицу? Так что, если вы используете систему только вы, простой подход - просто взять идентификаторы вставленных строк, как, например, если вы знаете количество вставленных строк, просто взять последние n строк? Или добавьте еще один столбец с уникальным идентификатором, чтобы вы могли только извлечь из него. Затем, имея идентификаторы в массиве, соедините их двоеточием и, наконец, ваш запрос должен выглядеть следующим образом:

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 -принимать вставленные идентификаторы -insert -принимайте вставленные идентификаторы -соединение - присоединиться к идентификаторам - используйте запрос

И я понятия не имею, как работает запрос с чем-то вроде этого:

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, чтобы уменьшить количество текста, отправляемого в sql, и особенно количество вызываемых запросов. Если количество строк велико, количество потраченного времени будет смехотворно огромным.

0 голосов
/ 30 ноября 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...