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

时间:2016-07-19 02:21:47

标签: 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.

我也无法将其保存为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.

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

2 个答案:

答案 0 :(得分:10)

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

  

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

     
      
  • 子查询,参数,变量,存储函数和用户定义的   不允许使用这些功能。
  •   

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

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

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

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

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

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

答案 1 :(得分:3)

计算列的想法是从记录中的其他列派生数据,例如将国家/地区代码与邮政编码相结合,这样您就可以存储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
);

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

我希望我的语法正确。