diff --git a/MysqliDb.php b/MysqliDb.php index b6fd491b..1e0d1347 100644 --- a/MysqliDb.php +++ b/MysqliDb.php @@ -679,6 +679,48 @@ public function insert($tableName, $insertData) return $this->_buildInsert($tableName, $insertData, 'INSERT'); } + /** + * Insert method to add several rows at once + * + * @param string $tableName The name of the table. + * @param array $multiInsertData Two-dimensinal Data-array containing information for inserting into the DB. + * @param array $dataKeys Optinal Table Key names, if not set in insertDataSet. + * + * @return bool|array Boolean indicating the insertion failed (false), else return id-array ([int]) + */ + public function insertMulti($tableName, array $multiInsertData, array $dataKeys = null) + { + // only auto-commit our inserts, if no transaction is currently running + $autoCommit = (isset($this->_transaction_in_progress) ? !$this->_transaction_in_progress : true); + $ids = array(); + + if($autoCommit) { + $this->startTransaction(); + } + + foreach ($multiInsertData as $insertData) { + if($dataKeys !== null) { + // apply column-names if given, else assume they're already given in the data + $insertData = array_combine($dataKeys, $insertData); + } + + $id = $this->insert($tableName, $insertData); + if(!$id) { + if($autoCommit) { + $this->rollback(); + } + return false; + } + $ids[] = $id; + } + + if($autoCommit) { + $this->commit(); + } + + return $ids; + } + /** * Replace method to add new row * diff --git a/index.php b/index.php index 49db33c6..97c9c4a4 100644 --- a/index.php +++ b/index.php @@ -118,7 +118,7 @@ function action_mod () { '> -
+
diff --git a/readme.md b/readme.md index 80c16c6c..347746d1 100644 --- a/readme.md +++ b/readme.md @@ -144,6 +144,43 @@ $db->onDuplicate($updateColumns, $lastInsertId); $id = $db->insert ('users', $data); ``` +Insert multiple datasets at once +```php +$data = Array( + Array ("login" => "admin", + "firstName" => "John", + "lastName" => 'Doe' + ), + Array ("login" => "other", + "firstName" => "Another", + "lastName" => 'User', + "password" => "very_cool_hash" + ) +); +$ids = $db->insertMulti('users', $data); +if(!$ids) { + echo 'insert failed: ' . $db->getLastError(); +} else { + echo 'new users inserted with following id\'s: ' . implode(', ', $ids); +} +``` + +If all datasets only have the same keys, it can be simplified +```php +$data = Array( + Array ("admin", "John", "Doe"), + Array ("other", "Another", "User") +); +$keys = Array("login", "firstName", "lastName"); + +$ids = $db->insertMulti('users', $data, $keys); +if(!$ids) { + echo 'insert failed: ' . $db->getLastError(); +} else { + echo 'new users inserted with following id\'s: ' . implode(', ', $ids); +} +``` + ### Replace Query Replace() method implements same API as insert(); @@ -713,7 +750,7 @@ else echo 'Update failed. Error: '. $db->getLastError(); ``` -### Query exectution time benchmarking +### Query execution time benchmarking To track query execution time setTrace() function should be called. ```php $db->setTrace (true); diff --git a/tests/mysqliDbTests.php b/tests/mysqliDbTests.php index 58b3fd22..bd35bc30 100644 --- a/tests/mysqliDbTests.php +++ b/tests/mysqliDbTests.php @@ -396,8 +396,8 @@ function createTable ($name, $data) { } unset ($cnt); -$data = $db->get('users'); -if (count($data) != 3) { +$users = $db->get('users'); +if (count($users) != 3) { echo "copy with subquery data count failed"; exit; } @@ -444,6 +444,47 @@ function createTable ($name, $data) { exit; } +$expectedIDs = [ + 'users' => [5, 6, 7], + 'products' => [6,7,8,9,10], +]; + +// multi-insert test with autoincrement +foreach ($data as $name => $datas) { + + // remove previous entries to ensure avoiding PRIMARY-KEY collisions here + $db->delete($name); + + // actual insertion test + $ids = $db->insertMulti($name, $datas); + + // check results + if(!$ids) { + echo "failed to multi-insert: ".$db->getLastQuery() ."\n". $db->getLastError(); + exit; + } elseif($ids !== $expectedIDs[$name]) { + pretty_print($ids); + echo "multi-insert succeeded, but unexpected id's: ".$db->getLastQuery() ."\n". $db->getLastError(); + exit; + } +} + +// skip last user here, since it has other keys than the others +unset($data['users'][2]); + +// multi-insert test with autoincrement and overriding column-names +foreach ($data as $name => $datas) { + + // remove previous entries to ensure avoiding PRIMARY-KEY collisions here + $db->delete($name); + + // actual insertion test + if(!$db->insertMulti($name, $datas, array_keys($datas[0]))) { + echo "failed to multi-insert: ".$db->getLastQuery() ."\n". $db->getLastError(); + exit; + } +} + /// //TODO: insert test $db->delete("users");