从另一列计算的列?

时间:2011-03-07 16:17:33

标签: mysql sql

鉴于下表:

id | value
--------------
1     6
2     70

有没有办法添加一个根据同一个表中的另一列自动计算的列?像VIEW,但同一个表的一部分。例如,calculated将是value的一半。 Calculated更改后value会自动更新,就像VIEW一样。

结果将是:

id | value | calculated
-----------------------
1     6       3
2     70      35

7 个答案:

答案 0 :(得分:47)

Generated Column是MySql版本的一个很好的方法,它是5.7.6及更高版本。

有两种生成列:

  • 虚拟(默认) - 当a时,将立即计算列 从表中读取记录
  • 存储 - 列将在a时计算 新记录在表格中写入/更新

两种类型都可以具有NOT NULL限制,但只有存储的生成列才能成为索引的一部分。

对于当前情况,我们将使用存储生成的列。为了实现我已经考虑过计算所需的两个值都存在于表

CREATE TABLE order_details (price DOUBLE, quantity INT, amount DOUBLE AS (price * quantity));

INSERT INTO order_details (price, quantity) VALUES(100,1),(300,4),(60,8);

金额将自动弹出表格,您可以直接访问,也请注意,每当您更新任何列时,金额也会更新。

答案 1 :(得分:31)

如果是选择,您可以这样做:

SELECT id, value, (value/2) AS calculated FROM mytable

否则,您还可以先更改表以添加缺少的列,然后执行UPDATE查询以计算新列的值:

UPDATE mytable SET calculated = value/2;

如果必须是自动的,并且您的MySQL版本允许,您可以尝试使用triggers

答案 2 :(得分:24)

MySQL 5.7支持计算列。他们称之为“Generated Columns”,语法有点奇怪,但它支持我在其他数据库中看到的相同选项。

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

答案 3 :(得分:21)

@ krtek的回答是正确的,但有几个问题。

坏消息是在同一个表的触发器中使用UPDATE将不起作用。好消息是没有必要;在触摸桌子之前,您可以操作一个新对象。

触发器变为:

CREATE TRIGGER halfcolumn_update BEFORE UPDATE ON my_table
  FOR EACH ROW BEGIN
    SET NEW.calculated = NEW.value/2;
  END;

另请注意BEGIN ... END;语法必须使用不同的分隔符进行解析。整个shebang变成了:

DELIMITER |

CREATE TRIGGER halfcolumn_insert BEFORE INSERT ON my_table
  FOR EACH ROW BEGIN
    SET NEW.calculated = NEW.value/2;
  END;
|

CREATE TRIGGER halfcolumn_update BEFORE UPDATE ON my_table
  FOR EACH ROW BEGIN
    SET NEW.calculated = NEW.value/2;
  END;
|

DELIMITER ;

答案 4 :(得分:4)

如果要向表中添加一个自动更新为其他列的一半的列,则可以使用触发器执行此操作。

但我认为已经提出的答案是更好的方法。

干编码触发器:

CREATE TRIGGER halfcolumn_insert AFTER INSERT ON table
  FOR EACH ROW BEGIN
    UPDATE table SET calculated = value / 2 WHERE id = NEW.id;
  END;
CREATE TRIGGER halfcolumn_update AFTER UPDATE ON table
  FOR EACH ROW BEGIN
    UPDATE table SET calculated = value / 2 WHERE id = NEW.id;
  END;

我不认为你只能做一次触发,因为我们必须回应的事件是不同的。

答案 5 :(得分:3)

我希望这仍然有助于某些人可能会接触到这篇文章。如果您需要计算列,为什么不在视图中公开您想要的列?不要只使用触发器保存数据或使性能过载......只需在视图中公开您已经格式化/计算过的数据。

希望这会有所帮助......

答案 6 :(得分:1)

您可以使用MYSQL 5.7中生成的列。

示例用法:

ALTER TABLE tbl_test
ADD COLUMN calc_val INT 
GENERATED ALWAYS AS (((`column1` - 1) * 16) + `column2`) STORED;

虚拟 / 存储

  • 虚拟的:从表中读取记录时动态计算(默认)
  • 已存储:在插入或更新新记录时计算 桌子