如何在 JOIN 中使用 SELECT 中的 GENERATED?

sms*_*are 5 mysql mysql-5.7

数据库模式

这是我的数据库。FoodItems 只是普通表,但我想使用虚拟列来生成所有相关数据,例如 Servings.kcal 等于相关 (FieldItem.kcal*unit)/100(数据以每 100g/100ml 的千卡为单位指定):

CREATE TABLE IF NOT EXISTS `DietDB`.`Servings` (
      `id` INT UNSIGNED NOT NULL,
      `FoodItem_id` INT UNSIGNED NOT NULL,
      `name` VARCHAR(255) NOT NULL,
      `units` DOUBLE UNSIGNED NULL,
      `kcal` INT GENERATED ALWAYS AS (SELECT (FoodItems.kcal*units)/100 FROM Servings JOIN FoodItems ON Servings.FoodItem_id = FoodItems.id) VIRTUAL,
      `carbohydrate` DOUBLE UNSIGNED NULL,
      `carbohydrate_sugar` DOUBLE UNSIGNED NULL,
      `fat` DOUBLE UNSIGNED NULL,
      `fat_saturated` DOUBLE UNSIGNED NULL,
      `fat_trans` DOUBLE UNSIGNED NULL,
      `protein` DOUBLE UNSIGNED NULL,
      `fibre` DOUBLE UNSIGNED NULL,
      PRIMARY KEY (`id`, `FoodItem_id`),
      INDEX `fk_Servings_FoodItems1_idx` (`FoodItem_id` ASC),
      UNIQUE INDEX `name_UNIQUE` (`name` ASC),
      CONSTRAINT `fk_Servings_FoodItems1`
        FOREIGN KEY (`FoodItem_id`)
        REFERENCES `DietDB`.`FoodItems` (`id`)
        ON DELETE NO ACTION
        ON UPDATE NO ACTION)
    ENGINE = InnoDB
Run Code Online (Sandbox Code Playgroud)

这显然是错误的,因为查询返回整个表,而不是单个值,并且它会大喊错误......但它展示了我试图在那里实现的目标。怎么可能呢?

ype*_*eᵀᴹ 4

根据 MySQL 文档,GENERATED不能有子查询:

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

  • 允许使用文字、确定性内置函数和运算符。如果给定表中相同的数据,多次调用会产生相同的结果,而与连接的用户无关,则该函数是确定性的。不符合此定义的函数示例:CONNECTION_ID(), CURRENT_USER(), NOW()

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

  • ...


你可以做的是使用视图:

CREATE VIEW DietDB.Servings_All        -- pick an appropriate name
AS 
SELECT s.*,
       CAST((fi.kcal * s.units) / 100 AS UNSIGNED INT) AS kcal 
FROM DietDB.Servings AS s 
  LEFT JOIN DietDB.FoodItems AS fi 
    ON s.FoodItem_id = fi.id ; 
Run Code Online (Sandbox Code Playgroud)