我试图找到一次更新多条记录,就像我们insert
一次创建多条记录一样。
假设我有一个关联的数组,其中包含要在表员工的每一行中更新的数据:
$data = [
['id'=>1,'name'=>'xxx'],
['id'=>2,'name'=>'xxx'],
['id'=>3,'name'=>'xxx'],
['id'=>4,'name'=>'xxx']
];
更新所有这些记录的一种方法是:
foreach($data as $d){
Employee::where('id'=>$d['id'])->update(['name'=>$d['name']]);
}
其中Employee是员工表的模型。
我想知道我是否可以通过一行声明更新所有记录?
例如,如果我从$ data创建了新记录,我会使用:
Employee::insert($data);
而不是循环遍历$ data并为每条记录使用create()。
还有类似的更新吗?
答案 0 :(得分:0)
不,这是不可能的,你应该迭代数组并分别更新每一行。
答案 1 :(得分:0)
你试过Employee::update($data);
吗?当然数据应该是数组
喜欢:
$data = (['name'=>'test'],['surname'=>'test2']));
- 它将更新表中的所有行 - 但您可以添加where条件。
答案 2 :(得分:0)
Doctrine允许您进行批量插入/更新。您可以在此处找到它:http://www.laraveldoctrine.org/
答案 3 :(得分:0)
使用集合做这样的事情呢。
$data = [
['id'=>3,'name'=>'xxx'],
['id'=>4,'name'=>'xxx'],
['id'=>5,'name'=>'xxx']
];
Employee::find(collect($data)->pluck('id')->toArray())->map(function($item, $key) use ($data){
$item['name'] = $data[$key]['name'];
return $item->save();
});
答案 4 :(得分:0)
这是不可能的,因为批量更新只能通过union
来实现,/// <summary>
/// A stackpanel similar to the Wpf stackpanel.
/// </summary>
public class StackPanel: FlowLayoutPanel
{
public StackPanel(): base()
{
InitializeComponent();
this.ForceAutoresizeOfControls = true;
}
private void InitializeComponent()
{
this.SuspendLayout();
//
// StackPanel
//
this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
this.WrapContents = false;
this.ResumeLayout(false);
}
/// <summary>
/// Override it just in order to hide it in design mode.
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public new bool WrapContents
{
get { return base.WrapContents; }
set { base.WrapContents = value; }
}
/// <summary>
/// Override it just in order to set its default value.
/// </summary>
[DefaultValue(typeof(AutoSizeMode), "GrowAndShrink")]
public override AutoSizeMode AutoSizeMode
{
get { return base.AutoSizeMode; }
set { base.AutoSizeMode = value; }
}
/// <summary>
/// Get or set a value that when is true forces the resizing of each control.
/// If this value is false then only control that have AutoSize == true will be resized to
/// fit the client size of this container.
/// </summary>
[DefaultValue(true)]
public bool ForceAutoresizeOfControls { get; set; }
protected override void OnSizeChanged(EventArgs e)
{
base.OnSizeChanged(e);
this.SuspendLayout();
switch (FlowDirection)
{
case FlowDirection.BottomUp:
case FlowDirection.TopDown:
foreach (Control control in this.Controls)
if (ForceAutoresizeOfControls || control.AutoSize)
control.Width = this.ClientSize.Width - control.Margin.Left - control.Margin.Right;
break;
case FlowDirection.LeftToRight:
case FlowDirection.RightToLeft:
foreach (Control control in this.Controls)
if (ForceAutoresizeOfControls || control.AutoSize)
control.Height = this.ClientSize.Height - control.Margin.Top - control.Margin.Bottom;
break;
default:
break;
}
this.ResumeLayout();
}
protected override void OnLayout(LayoutEventArgs levent)
{
base.OnLayout(levent);
if (levent != null && levent.AffectedControl != null)
{
Control control = levent.AffectedControl;
if (ForceAutoresizeOfControls || control.AutoSize)
{
switch (FlowDirection)
{
case FlowDirection.BottomUp:
case FlowDirection.TopDown:
control.Width = this.ClientSize.Width - control.Margin.Left - control.Margin.Right;
break;
case FlowDirection.LeftToRight:
case FlowDirection.RightToLeft:
control.Height = this.ClientSize.Height - control.Margin.Top - control.Margin.Bottom;
break;
default:
break;
}
}
}
}
}
是你可以在sql中使用的最慢的运算符。
否则,即使在原始sql中也无法使用不同行中的不同值批量更新,因此也无法在laravel中进行更新。
答案 5 :(得分:0)
我写了一个批处理更新函数,用于我的Laravel项目。对于想要在laravel中使用批量更新查询的任何人来说,这可能很有用。它的第一个参数 是表名字符串,第二个是要更新一行或多行的键名称字符串,大部分是&#39; id&#39;,第三个参数是数据数组,格式如下: / p>
array(
array(
'id' => 1,
'col_1_name' => 'col_1_value',
'col_2_name' => 'col_2_value',
//....
),
array(
'id' => 2,
'col_1_name' => 'col_1_value',
'col_2_name' => 'col_2_value',
//....
),
//....
);
功能定义:
private function custom_batch_update(string $table_name = '', string $key = '', Array $update_arr = array()) {
if(!$table_name || !$key || !$update_arr){
return false;
}
$update_keys = array_keys($update_arr[0]);
$update_keys_count = count($update_keys);
for ($i = 0; $i < $update_keys_count; $i++) {
$key_name = $update_keys[$i];
if($key === $key_name){
continue;
}
$when_{$key_name} = $key_name . ' = CASE';
}
$length = count($update_arr);
$index = 0;
$query_str = 'UPDATE ' . $table_name . ' SET ';
$when_str = '';
$where_str = ' WHERE ' . $key . ' IN(';
while ($index < $length) {
$when_str = " WHEN $key = '{$update_arr[$index][$key]}' THEN";
$where_str .= "'{$update_arr[$index][$key]}',";
for ($i = 0; $i < $update_keys_count; $i++) {
$key_name = $update_keys[$i];
if($key === $key_name){
continue;
}
$when_{$key_name} .= $when_str . " '{$update_arr[$index][$key_name]}'";
}
$index++;
}
for ($i = 0; $i < $update_keys_count; $i++) {
$key_name = $update_keys[$i];
if($key === $key_name){
continue;
}
$when_{$key_name} .= ' ELSE ' . $key_name . ' END, ';
$query_str .= $when_{$key_name};
}
$query_str = rtrim($query_str, ', ');
$where_str = rtrim($where_str, ',') . ')';
$query_str .= $where_str;
$affected = DB::update($query_str);
return $affected;
}
它将生成并执行如下的查询字符串:
UPDATE table_name SET col_1_name = CASE
WHEN id = '1' THEN 'col_1_value'
WHEN id = '2' THEN 'col_1_value'
ELSE col_1_name END,
col_2_name = CASE
WHEN id = '1' THEN 'col_2_value'
WHEN id = '2' THEN 'col_2_value'
ELSE col_2_name END
WHERE id IN('1','2')
答案 6 :(得分:0)
它将在laravel中更新现有或新插入到表中。
$data=array(
array('id'=>1,'name'=>'kaleemullah@example.com'),
array('id'=>2,'name'=>'kaleemullah@example.com2'),
array('id'=>4,'name'=>'kaleemullah@example.com4')
);
$imported = implode(', ', array_map(function ($string) {
return "(".$string['id'].','."'".$string['name']."'"."),";
}, $data));
$OneStepAway = str_replace(',,', ',', $imported);
$kale = rtrim($OneStepAway,',');
$s = DB::statement("INSERT INTO tests (id,name) VALUES $kale
ON DUPLICATE KEY UPDATE name=VALUES(name)") ;
echo "Successfully Updated and Insert New records into the database ";
答案 7 :(得分:0)
对于一小部分数据,循环会很好。
但是,如果您有大量数据-绝对不要循环,因为“数据库事务”是一项昂贵的操作,并且带有for循环,您将结束每次迭代都要进行交易。
在这里,您可以了解如何在不使用for循环的情况下进行更新:
$data = [
['id'=>1,'name'=>'xxx'],
['id'=>2,'name'=>'xxx'],
['id'=>3,'name'=>'xxx'],
['id'=>4,'name'=>'xxx']
];
$cases = [];
$ids = [];
$params = [];
foreach ($data as $datum) {
$id = $datum['id'];
$cases[] = "WHEN {$id} then ?";
$params[] = $datum['name'];
$ids[] = $id;
}
$ids = implode(',', $ids);
$cases = implode(' ', $cases);
if (!empty($ids)) {
\DB::update("UPDATE employees SET `name` = CASE `id` {$cases} END WHERE `id` in ({$ids})", $params);
}
如果您想阅读有关内容,请选中https://medium.com/@sentiasa/bulk-update-multiple-records-with-separate-data-laravel-3da9131c279a
答案 8 :(得分:0)
public function transaction($callback) {
DB::connection(**<TABLE_NAME>**)->transaction($callback);
}
public function updateBatch($batchData)
{
$count = 0;
try {
$batchData = array_values($batchData);
$total = count($batchData);
$j = 0;
$i = 0;
do {
$j = min($total -1, $j + self::$configBatch);
DB::connection(**<TABLE_NAME>**)->transaction(function() use ($batchData, &$count, $total, $j, &$i) {
for (; $i <= $j; $i++) {
$batchData[$i]->save();
$count++;
}
});
} while ($i < $total);
} catch (\Exception $exception) {
print_r($exception->getMessage());
$count = 0;
}
return $count;
}
希望能为您提供帮助