26

CodeigniterとActiveRecordsを使用してMySQLテーブルにいくつかの行を挿入しようとしています。

PHPコード

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

ただし、これにより、重複する行がテーブルに挿入される可能性があります。INSERT IGNORE重複データの挿入を処理するために、行が重複している場合は行を挿入しないコマンドを使用する予定です。

問題: Active Recordsで同等のものが見つからずINSERT IGNORE、ActiveRecordクラスを編集したくありません。他に選択肢はありますか?

以下は面白そうですが、次のようにすると、クエリが2回実行されませんか?

$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
4

13 に答える 13

44

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

更新:これはバッチクエリでは機能せず、一度に1行のみです。

于 2012-06-10T04:01:43.177 に答える
8

同様の問題に遭遇したので、私は最終的に、以下のようなもう少し「エレガントな」ソリューションを選択しました。Rocketの回答とトランザクションを使用する完全なinsert_batchクエリ:

$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()ほど高速ではありませんが、もちろん、エントリごとに1つのクエリよりも高速です。それが誰かを助けることを願っています。

于 2013-12-02T08:35:58.870 に答える
7

バッチアップロードの場合、次のようなものが必要になる場合があります。

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

更新: dcostalisのバージョンを使用してください(これの下のコメントで)、それははるかに良くスケーリングします:-)

于 2013-01-10T14:44:00.977 に答える
4

これは基本的にRocketHazmatの提案を修正したものであり、すばらしいものですが、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);
于 2015-10-13T18:58:49.090 に答える
3

2番目のアイデアの手法を使用すると、配列をループして次を使用してクエリを生成できます。

$this->db->query($query_string);
于 2012-06-10T02:16:43.343 に答える
1

この目的のために、私はこのヘルパー関数を作成しました:

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

無視してバッチ挿入とバッチ挿入を行うことができます。行の重複を避けるために、プライマリフィールドのデータベーステーブルに一意のキーを設定する必要があります。

于 2015-06-03T16:05:24.137 に答える
1

解決 :

$sql = $this->db->set($data)->get_compiled_insert($table);
$sql = str_replace('INSERT INTO', 'INSERT IGNORE INTO', $sql);
$this->db->query($sql);

codeigniter3.0.6で動作します:)

于 2018-05-11T20:25:42.587 に答える
1

それでも誰かがinsert_batchでignoreを使用するのに苦労している場合は、

このパスを確認してください

system/database/DB_query_builder.php

機能を検索する

protected function _insert_batch

変化する

INSERT INTO => INSERT IGNORE INTO

後でありがとう。:)

于 2019-02-21T11:10:23.087 に答える
0

強くお勧めしませんが、バッチ挿入を保持するためのハックがあります(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);
}
于 2014-07-10T05:57:47.473 に答える
0

私も同じ問題を抱えていて、私を助けてくれたのは:

開く: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);
}
于 2015-10-28T18:45:49.680 に答える
0

ファイルに追加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);
于 2015-11-17T14:17:04.620 に答える
0

codeigniterでの重複データ挿入を避けるのは難しい作業です。ただし、非常に単純で正確な方法でカスタマイズされたライブラリメソッドを使用して、重複する値の挿入を無視できます。私は次の場所で適切な解決策を見つけました: how-to-avoid-duplicate-data-insertion-in-codeigniter-php

于 2020-01-08T08:58:13.550 に答える
-1

少なくとも1つのフィールドのデータベーステーブルに一意のキーを設定して、行の重複を避けます。

于 2012-06-10T02:10:03.690 に答える