更新 MySQL 中的缓存计数

发布于 2024-09-06 01:54:03 字数 578 浏览 9 评论 0原文

为了修复错误,我必须迭代表中的所有行,将缓存的子项计数更新为其实际值。表中事物的结构形成一棵树。

在rails中,以下内容满足我的要求:

Thing.all.each do |th|
  Thing.connection.update(
    "
      UPDATE #{Thing.quoted_table_name} 
        SET children_count = #{th.children.count}
        WHERE id = #{th.id}
    "
  )
end

有没有办法在单个MySQL查询中执行此操作? 或者,有没有办法在多个查询中但在纯 MySQL 中执行此操作?

我想要类似的东西

UPDATE table_name
  SET children_count = (
    SELECT COUNT(*) 
      FROM table_name AS tbl 
      WHERE tbl.parent_id = table_name.id
  )

,但上面的方法不起作用(我明白为什么它不起作用)。

In order to fix a bug, I have to iterate over all the rows in a table, updating a cached count of children to what its real value should be. The structure of the things in the table form a tree.

In rails, the following does what I want:

Thing.all.each do |th|
  Thing.connection.update(
    "
      UPDATE #{Thing.quoted_table_name} 
        SET children_count = #{th.children.count}
        WHERE id = #{th.id}
    "
  )
end

Is there any way of doing this in a single MySQL query?
Alternatively, is there any way of doing this in multiple queries, but in pure MySQL?

I want something like

UPDATE table_name
  SET children_count = (
    SELECT COUNT(*) 
      FROM table_name AS tbl 
      WHERE tbl.parent_id = table_name.id
  )

except the above doesn't work (I understand why it doesn't).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

2024-09-13 01:54:03

您可能遇到此错误,对吗?

ERROR 1093 (HY000): You can't specify target table 'table_name' for update in FROM clause

解决此问题的最简单方法可能是将子计数选择到临时表中,然后加入该表以进行更新。

假设父/子关系的深度始终为 1,这应该可行。根据您的原始更新,这似乎是一个安全的假设。

我在表上添加了显式写锁,以确保创建临时表后不会修改任何行。仅当您有能力在此更新期间锁定它时才应执行此操作,这取决于数据量。

lock tables table_name write;

create temporary table temp_child_counts as
select parent_id, count(*) as child_count
from table_name 
group by parent_id;

alter table temp_child_counts add unique key (parent_id);

update table_name
inner join temp_child_counts on temp_child_counts.parent_id = table_name.id
set table_name.child_count = temp_child_counts.child_count;

unlock tables;

You probably got this error, right?

ERROR 1093 (HY000): You can't specify target table 'table_name' for update in FROM clause

The easiest way around this is probably to select the child counts into a temporary table, then join to that table for the updates.

This should work, assuming the depth of the parent/child relationship is always 1. Based on your original update this seems like a safe assumption.

I added an explicit write lock on the table to assure that no rows are modified after I create the temp table. You should only do this if you can afford to have it locked for the duration of this update, which will depend on the amount of data.

lock tables table_name write;

create temporary table temp_child_counts as
select parent_id, count(*) as child_count
from table_name 
group by parent_id;

alter table temp_child_counts add unique key (parent_id);

update table_name
inner join temp_child_counts on temp_child_counts.parent_id = table_name.id
set table_name.child_count = temp_child_counts.child_count;

unlock tables;
绝不服输 2024-09-13 01:54:03

您的子选择更新应该有效;让我们尝试稍微修改一下:

UPDATE table_name
  SET children_count = (
    SELECT COUNT(sub_table_name.id) 
      FROM sub_table_name 
      WHERE sub_table_name.parent_id = table_name.id
  )

或者如果子表是同一个表:

UPDATE table_name as top_table
  SET children_count = (
    SELECT COUNT(sub_table.id) 
      FROM (select * from table_name) as sub_table
      WHERE sub_table.parent_id = top_table.id
  )

但我猜这不是超级有效。

your subselect update should work; let's try touching it up a bit:

UPDATE table_name
  SET children_count = (
    SELECT COUNT(sub_table_name.id) 
      FROM sub_table_name 
      WHERE sub_table_name.parent_id = table_name.id
  )

Or if the sub-table is the same table:

UPDATE table_name as top_table
  SET children_count = (
    SELECT COUNT(sub_table.id) 
      FROM (select * from table_name) as sub_table
      WHERE sub_table.parent_id = top_table.id
  )

But that's not super efficient I'm guessing.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文