7

Is there anyway to have cake do a multi-row insert in a single query without writing raw SQL to do this? The saveMany and saveAssociated options will only save multiple rows in a single transaction, but that transaction contains multiple insert statements so these methods are clearly not a solution to write heavy applications.

Thanks for reading.

5 Answers 5

3

Yes

Though it's not a common practice to do so in app-land code, and doing so removes the possibility to use almost any application logic (validation rules, behaviors, events etc.). You can see an example of doing this in the way fixtures are loaded:

$db = ConnectionManager::getDataSource('default');

$table = "stuffs";
$fields = array('id', 'name');
$values = array(
    array(1, 'one'),
    array(2, 'two'),
    ...
);

$result = $db->insertMulti($table, $fields, $values);

You may also find this repository useful (either directly or as a basis for your code) which loads fixture files into your app database - using multi-inserts.

Sign up to request clarification or add additional context in comments.

2 Comments

it appears this still inserts a single row at a time wrapped up in a single transaction...
Hah! Didn't notice that. If you're doing this often enough for it to make the difference, as noted in the comment for the big-data-behavior-answer, make sure your chosen solution is escaping values appropriately.
2

Yes, Big_Data is good idea for inserting bulk. But as AD7six note, it still use basic value quoting and does not return insert ids. And base on your ideas, i wrote small script to inserting bulk in a single query, using default CakePHP quoting and returning ids of inserted records.

    $count = count($records);
    $dbSource = $this->getDataSource();
    $table = $dbSource->fullTableName($this->table);
    $fields = $dbSource->prepareFields($this, array('fields' => array_keys($records[0])));
    $values = array();
    foreach ($records as $index => $record) {
        if (!is_array($record) || !$record) {
            return null;
        }
        foreach ($record as $column => $value) {
            $values[$index][$column] = $dbSource->value($value, $this->getColumnType($column));
        }
        $values[$index] = '(' . implode(',', $values[$index]) . ')';
    }

    $query = 'INSERT INTO %s (%s) VALUES %s;';

    $query = sprintf($query, $table, implode(',', $fields), implode(',', $values));
    if (!$dbSource->execute($query)) {
        return false;
    }
    $lastInsertId = $dbSource->getConnection()->lastInsertId();
    $insertIds = array();
    for ($i = 0; $i < $count; $i++) {
        $insertIds[] = $lastInsertId + $i;
    }
    return $insertIds;

Comments

0

Someone pointed me towards the Big Data Behavior https://github.com/jmillerdesign/CakePHP_Big_Data

1 Comment

Careful =). That behavior has a (possibly) handy API, but IS writing raw sql. If your data isn't simple you're going to get sql syntax errors - it only does basic value quoting. Also looks like it doesn't let you do anything except full row insert/updates. If you want to use it anyway I suggest updating to simply call insertMulti, unescaped raw sql queries are a problem waiting to happen.
0

If you are using CakePHP 3.0 you can check the answer to this question: How to use insert in query builder insert multiple records?

If you are using CakePHP 2 you will have to use raw SQL like this:

$sql = "INSERT INTO `people` (`name`,`title`) VALUES ";
foreach($people as $person){
    list($name,$title) = $person;
    $sql.= "('$name','$title'),";
}
$this->query(substr($sql,0,-1));

Source: Inserting Multiple Rows with CakePHP 3

Comments

-1

yes you can use like below

The getDataSource() method is static in CakePHP 2.x, so you should be able to use:

$db = ConnectionManager::getDataSource('default');
$db->rawQuery($some_sql);

here i am posting method to do. you have to create some SQL statement manually to insert multiple row in one time.

Please let me know if i can help you more.

1 Comment

I know how to do this with traditional SQL, I want to stay within my framework. Raw SQL is last resort. I found this: github.com/jmillerdesign/CakePHP_Big_Data

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.