INSERT IGNORE с использованием Codeigniter

Я пытаюсь вставить несколько строк в таблицу MySQL, используя Codeigniter и Active Records.

PHP-код

$data = array('......'); // some rows of data to insert $this->db->insert_batch('my_table', $data); 

Однако это может привести к тому, что в таблицу будут вставлены повторяющиеся строки. Чтобы обрабатывать вставку дублированных данных, я планирую использовать команду INSERT IGNORE чтобы не вставлять строку, если строка является дубликатом.

Проблема: я не могу найти эквивалент INSERT IGNORE в Active Records и не хочу редактировать класс Active Record. Есть ли другие альтернативы?

Следующее выглядит интересным, но если я сделаю следующее, не будет ли запрос выполняться дважды?

 $insert_query = $this->db->insert_batch('my_table', $data); // QUERY RUNS ONCE $insert_query = str_replace('INSERT INTO','INSERT IGNORE INTO',$insert_query); $this->db->query($insert_query); // QUERY RUNS A SECOND TIME 

Solutions Collecting From Web of "INSERT IGNORE с использованием Codeigniter"

Используя технику вашей второй идеи, вы можете сгенерировать запрос, перейдя по массиву и используя:

 $this->db->query($query_string); 

Не используйте insert_batch , поскольку он действительно запускает запрос. Вы хотите, чтобы insert_string

 $insert_query = $this->db->insert_string('my_table', $data); $insert_query = str_replace('INSERT INTO','INSERT IGNORE INTO',$insert_query); $this->db->query($insert_query); 

UPDATE : это не работает для пакетных запросов, только по одной строке за раз.

Для пакетных загрузок вам может понадобиться нечто большее:

 foreach ($data as $data_item) { $insert_query = $this->db->insert_string('my_table', $data_item); $insert_query = str_replace('INSERT INTO', 'INSERT IGNORE INTO', $insert_query); $this->db->query($insert_query); } 

UPDATE: используйте версию dcostalis (в комментариях ниже этого), она будет масштабироваться намного лучше 🙂

Поскольку я также столкнулся с подобной проблемой, я, наконец, выбрал немного более «элегантное» решение, подобное приведенному ниже. Полный запрос insert_batch, который использует ответ Rocket и транзакции:

 $this->db->trans_start(); foreach ($items as $item) { $insert_query = $this->db->insert_string('table_name', $item); $insert_query = str_replace('INSERT INTO', 'INSERT IGNORE INTO', $insert_query); $this->db->query($insert_query); } $this->db->trans_complete(); 

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

Просто нашел это, может помочь http://www.amplio.ch/blog/web-development/codeigniter-active-record-class-and-insert-ignore/ , это, однако,

Не рекомендуется, но вот взломать пакетную вставку (что более эффективно для Mysql)

 // try to insert as usual first $this->db->insert_batch('my_table', $data); // if it fails resort to IGNORE if($this->db->_error_message()) { $sql = $this->db->last_query(); $sql = str_replace('INSERT INTO', 'INSERT IGNORE INTO', $sql); $this->db->query($sql); } 

Для этого я сделал эту вспомогательную функцию:

 function insert_batch_string($table='',$data=[],$ignore=false){ $CI = &get_instance(); $sql = ''; if ($table && !empty($data)){ $rows = []; foreach ($data as $row) { $insert_string = $CI->db->insert_string($table,$row); if(empty($rows) && $sql ==''){ $sql = substr($insert_string,0,stripos($insert_string,'VALUES')); } $rows[] = trim(substr($insert_string,stripos($insert_string,'VALUES')+6)); } $sql.=' VALUES '.implode(',',$rows); if ($ignore) $sql = str_ireplace('INSERT INTO', 'INSERT IGNORE INTO', $sql); } return $sql; } 

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

Это, по сути, модификация предложения Rocket Hazmat, что отлично, но не учитывает тот факт, что str_replace работает со всей строкой и может непреднамеренно повлиять на данные.

 $insert_query = $this->db->insert_string('my_table', $data); $insert_query = preg_replace('/INSERT INTO/','INSERT IGNORE INTO',$insert_query,1); $this->db->query($insert_query); 

добавить в файл DB_query_builder.php

эти 2 функции

 public function insert_ignore_batch($table = '', $set = NULL, $escape = NULL) { if ($set !== NULL) { $this->set_insert_batch($set, '', $escape); } if (count($this->qb_set) === 0) { // No valid data array. Folds in cases where keys and values did not match up return ($this->db_debug) ? $this->display_error('db_must_use_set') : FALSE; } if ($table === '') { if ( ! isset($this->qb_from[0])) { return ($this->db_debug) ? $this->display_error('db_must_set_table') : FALSE; } $table = $this->qb_from[0]; } // Batch this baby $affected_rows = 0; for ($i = 0, $total = count($this->qb_set); $i < $total; $i += 100) { $this->query($this->_insert_ignore_batch($this->protect_identifiers($table, TRUE, $escape, FALSE), $this->qb_keys, array_slice($this->qb_set, $i, 100))); $affected_rows += $this->affected_rows(); } $this->_reset_write(); return $affected_rows; } protected function _insert_ignore_batch($table, $keys, $values) { return 'INSERT IGNORE INTO '.$table.' ('.implode(', ', $keys).') VALUES '.implode(', ', $values); } 

с помощью:

 $this->db->insert_ignore_batch('TableName', $data); 

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

У меня тоже была такая же проблема, что мне помогло:

Открыть: Codeigniter / system / database / DB_query_builder.php :

найти

 protected function _insert_batch($table, $keys, $values) { return 'INSERT INTO '.$table.' ('.implode(', ', $keys).') VALUES '.implode(', ', $values); } 

и заменить на:

 protected function _insert_batch($table, $keys, $values) { return 'INSERT IGNORE INTO '.$table.' ('.implode(', ', $keys).') VALUES '.implode(', ', $values); }