简体   繁体   English

Laravel - 多插入行和检索 id

[英]Laravel - multi-insert rows and retrieve ids

I'm using Laravel 4, and I need to insert some rows into a MySQL table, and I need to get their inserted IDs back.我正在使用 Laravel 4,我需要在 MySQL 表中插入一些行,并且我需要取回它们插入的 ID。

For a single row, I can use ->insertGetId() , however it has no support for multiple rows.对于单行,我可以使用->insertGetId() ,但是它不支持多行。 If I could at least retrieve the ID of the first row, as plain MySQL does, would be enough to figure out the other ones.如果我至少可以检索第一行的 ID,就像普通的 MySQL 那样,就足以找出其他的。

It's mysql behavior of last-insert-id这是last-insert-id的 mysql 行为

Important重要的
If you insert multiple rows using a single INSERT statement, LAST_INSERT_ID() returns the value generated for the first inserted row only.如果使用单个 INSERT 语句插入多行,则 LAST_INSERT_ID() 仅返回为第一个插入的行生成的值。 The reason for this is to make it possible to reproduce easily the same INSERT statement against some other server.这样做的原因是可以轻松地针对其他服务器重现相同的 INSERT 语句。

u can try use many insert and take it ids or after save, try use $data->id should be the last id inserted.您可以尝试使用多个插入并获取 ID,或者在保存后,尝试使用 $data->id 应该是最后插入的 ID。

As user Xrymz suggested, DB::raw('LAST_INSERT_ID();') returns the first.正如用户 Xrymz 所建议的, DB::raw('LAST_INSERT_ID();')返回第一个。

According to Schema api insertGetId() accepts array根据Schema api insertGetId()接受数组

public int insertGetId(array $values, string $sequence = null)

So you have to be able to do所以你必须能够做到

DB::table('table')->insertGetId($arrayValues);

Thats speaking, if using MySQL, you could retrive the first id by this and calculate the rest.也就是说,如果使用 MySQL,您可以通过此检索第一个 id 并计算其余部分。 There is also a DB::getPdo()->lastInsertId();还有一个DB::getPdo()->lastInsertId(); function, that could help.功能,这可能会有所帮助。

Or if it returened the last id with some of this methods, you can calculate it back to the first inserted too.或者,如果它使用某些方法返回最后一个 id,您也可以将其计算回第一个插入的 ID。

EDIT编辑

According to comments, my suggestions may be wrong.根据评论,我的建议可能是错误的。

Regarding the question of 'what if row is inserted by another user inbetween', it depends on the store engine.关于“如果行被另一个用户插入中间会怎样”的问题,这取决于存储引擎。 If engine with table level locking ( MyISAM , MEMORY , and MERGE ) is used, then the question is irrevelant, since thete cannot be two simultaneous writes to the table.如果使用具有表级锁定( MyISAMMEMORYMERGE )的引擎,则问题无关紧要,因为不能同时向表中写入两次。

If row-level locking engine is used ( InnoDB ), then, another possibility might be to just insert the data, and then retrieve all the rows by some known field with whereIn() method, or figure out the table level locking .如果使用行级锁定引擎( InnoDB ),那么另一种可能性可能是只插入数据,然后使用whereIn()方法通过某个已知字段检索所有行,或者找出表级锁定

If you are using INNODB, which supports transaction, then you can easily solve this problem.如果您使用的是支持事务的INNODB,那么您可以轻松解决这个问题。 There are multiple ways that you can solve this problem.有多种方法可以解决此问题。

Let's say that there's a table called Users which have 2 columns id, name and table references to User model.假设有一个名为Users的表,它有 2 列id, name和对User模型的表引用。

Solution 1解决方案1

Your data looks like你的数据看起来像

$data = [['name' => 'John'], ['name' => 'Sam'], ['name' => 'Robert']]; // this will insert 3 rows

Let's say that the last id on the table was 600 .假设表上的最后一个 id 是600 You can insert multiple rows into the table like this您可以像这样在表中插入多行

DB::begintransaction();
User::insert($data); // remember: $data is array of associative array. Not just a single assoc array.
$startID = DB::select('select last_insert_id() as id'); // returns an array that has only one item in it
$startID = $startID[0]->id; // This will return 601
$lastID = $startID + count($data) - 1; // this will return 603
DB::commit();

Now, you know the rows are between the range of 601 and 603 Make sure to import the DB facade at the top using this现在,您知道行在601603之间的范围确保使用此导入顶部的DB外观

use Illuminate\Support\Facades\DB;

Solution 2解决方案2
This solution requires that you've a varchar or some sort of text field此解决方案要求您具有 varchar 或某种文本字段

$randomstring = Str::random(8);
$data = [['name' => "John$randomstring"], ['name' => "Sam$randomstring"]];

You get the idea here.你明白了。 You add that random string to a varchar or text field.您将该随机字符串添加到varchartext字段。

Now insert the rows like this现在插入这样的行

DB::beginTransaction();
User::insert($data);
// this will return the last inserted ids
$lastInsertedIds = User::where('name', 'like', '%' . $randomstring)
                         ->select('id')
                         ->get()
                         ->pluck('id')
                         ->toArray();
// now you can update that row to the original value that you actually wanted
User::whereIn('id', $lastInsertedIds)
      ->update(['name' => DB::raw("replace(name, '$randomstring', '')")]);
DB::commit();

Now you know what are the rows that were inserted.现在您知道插入的行是什么。

        $result = Invoice::create($data);
    if ($result) {
        $id = $result->id;

it worked for me它对我有用

Note: Laravel version 9注:Laravel 版本 9

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM