子查询作为mysql中生成的列?

use*_*162 8 mysql calculated-columns dynamically-generated generated

我可以在表A中创建一个生成的列,它将表B中的列与表A中的行的tableA_id相加?

假设我有一张家庭表和一张儿童表.我想要每个家庭孩子的年龄总和.

ALTER TABLE people.families 
ADD COLUMN sumofages DECIMAL(10,2) GENERATED ALWAYS AS 
(SELECT SUM(age) FROM people.children WHERE family_id = people.families.id) STORED;

ERROR 3102: Expression of generated column 'sumofages' contains a disallowed function.
Run Code Online (Sandbox Code Playgroud)

我无法将其保存为VIRTUAL类型.我在这做错了什么?

ALTER TABLE people.families 
ADD COLUMN sumofages DECIMAL(10,2) GENERATED ALWAYS AS 
(SELECT SUM(age) FROM people.children WHERE family_id = people.families.id) VIRTUAL;

ERROR 3102: Expression of generated column 'sumofages' contains a disallowed function.
Run Code Online (Sandbox Code Playgroud)

我不知道哪个功能不被禁止.SUM似乎不是它.也许SELECT?

Bil*_*win 11

https://dev.mysql.com/doc/refman/5.7/en/create-table-generated-columns.html

生成的列表达式必须遵守以下规则.如果表达式包含不允许的构造,则会发生错误.

  • 不允许使用子查询,参数,变量,存储函数和用户定义的函数.

这是合理的,对于生成列表达式可以引用在同一行内的列.生成的列不能使用子查询,也不能引用其他表或具有非确定性输出的函数.

假设生成的列确实支持跨表引用.特别考虑STORED生成列的情况.

如果更新表,MySQL还必须更新数据库中其他位置的生成列中的任何引用(如果它们引用您更新的行).MySQL追踪所有这些引用将是复杂而昂贵的.

然后考虑通过存储函数添加间接引用.

然后考虑您的更新是针对事务中的InnoDB表,但生成的列可能位于非事务(MyISAM,MEMORY,ARCHIVE等)表中.您的更新是否应该在生成的列中反映出来?如果你回滚怎么办?您的更新是否应在您提交时反映出来?那么MySQL如何"排队"更改以应用于这些表?如果多个事务提交影响生成的列引用的更新,该怎么办?应该赢得哪一个,最后应用更改的那个还是最后提交的那个?

由于这些原因,允许生成的列引用同一表中同一行的列以外的任何内容是不实际或有效的.


Tho*_*ner 8

计算列的想法是从记录中的其他列中导出数据,例如,将国家代码与邮政编码结合起来,这样您就可以存储 DE 和 12345,然后您将获得 DE-12345,您可以在地址。

然而,你正在尝试做的是完全不同的事情。您正在访问另一个表中的数据。但是该表的数据可能会发生变化,因此在访问同一条记录时,您可能会突然得到完全不同的结果。计算列应包含确定性值,因此只要您的记录数据不更改,它们就不会更改。在这方面我不了解 MySQL,但它可能禁止非确定性数据,例如您的子查询。

你真正要找的是一个视图。视图可以组合来自不同表的选择,就像您希望的那样。所以用

create view familydata as
(
  select f.*, sum(c.age) as sumofages
  from families f
  join children c on c.family_id = f.id
  group by f.id
);
Run Code Online (Sandbox Code Playgroud)

或者

create view familydata as
(
  select f.*,
  (
    select sum(age)
    from children c
    where c.family_id = f.id
  ) as sumofages
  from families f
);
Run Code Online (Sandbox Code Playgroud)

我希望我的语法正确。