Mysql 基于另一个表中的数据生成的列

Mysql 基于另一个表中的数据生成的列,mysql,Mysql,假设我有两个表,Faculty和FacultyEmail,它们具有1:1的关系,具有以下属性: +-------------+ +--------------+ | Faculty | | FacultyEmail | +-------------+ +--------------+ | FacultyID | | FacultyID | | FirstName | | Email | | LastName |

假设我有两个表,
Faculty
FacultyEmail
,它们具有1:1的关系,具有以下属性:

+-------------+     +--------------+
|   Faculty   |     | FacultyEmail |
+-------------+     +--------------+
|  FacultyID  |     |  FacultyID   |
|  FirstName  |     |  Email       |
|  LastName   |     +--------------+
+-------------+
我需要根据
Faculty
中的
FirstName
LastName
字段自动生成
Email
列,例如:
FirstName。lastname@gmail.com

我的问题是这是否可能?如果是这样的话,我将如何为这篇文章编写DDL

这是我到目前为止的DDL:

CREATE TABLE IF NOT EXISTS `Faculty`
(
    `FacultyID` INT NOT NULL,
    `FirstName` VARCHAR(45) NOT NULL,
    `LastName` VARCHAR(45) NOT NULL,
    PRIMARY KEY (`FacultyID`)
);

CREATE TABLE IF NOT EXISTS `FacultyEmail`
(
    `FacultyID` INT NOT NULL,
    `Email` VARCHAR(90) GENERATED ALWAYS AS (...), -- What goes here?
    PRIMARY KEY (`FacultyID`)
    FOREIGN KEY (`FacultyID`)
        REFERENCES `Faculty` (`FacultyID`)
        ON DELETE CASCADE
        ON UPDATE CASCADE
);
假设我有两个表,Faculty和FacultyMail,它们具有1:1的关系,具有以下属性:

+-------------+     +--------------+
|   Faculty   |     | FacultyEmail |
+-------------+     +--------------+
|  FacultyID  |     |  FacultyID   |
|  FirstName  |     |  Email       |
|  LastName   |     +--------------+
+-------------+
如果这真的是1:1的关系,那么第二张表是不必要的复杂化。对于单个表,可以使用生成的列

CREATE TABLE IF NOT EXISTS `Faculty`
(
    FacultyID int not null primary key auto_increment,
    FirstName varchar(255) not null,
    LastName varchar(255) not null,
    Email varchar(255) as
      (lower(concat(firstname,'.',lastname,'@wossamotta.edu'))) stored not null,
    unique(Email)
);
但是,无法更新生成的列。您的教员可能不喜欢无法选择他们的电子邮件地址。考虑使用<代码>默认< /代码>。< /P>
    Email varchar(255) not null  
      default(lower(concat(firstname,'.',lastname,'@wossamotta.edu'))),
不幸的是,因为这是一个数据规范,使教员有特定的电子邮件和表格

如果您必须有一个用于兼容性的电子邮件“表”,请考虑一个视图。

create view FacultyEmail
  as select FacultyID, Email from Faculty


如果确实需要两个表,可以在insert触发器之后编写一个

create trigger default_faculty_email
  after insert 
  on Faculty for each row
  insert into FacultyEmail (facultyid, email)
    values(
      NEW.facultyid,
      lower(CONCAT(NEW.firstname,'.',NEW.lastname,'@wossamotta.edu'))
    );
然而,在那之后,没有任何东西可以阻止一封教员邮件被删除,而使教员没有教员邮件。所以我们需要另一个触发器来防止这种情况

create trigger ProtectFacultyEmail
  before delete
  on FacultyEmail for each row
  signal sqlstate '45000'
    set message text = 'FacultyEmail cannot be directly deleted. Delete the Faculty row instead.';
这样可以防止直接从FacultyMail中删除,但允许在删除级联时执行

正如您所看到的,第二张表会带来很多复杂问题


笔记
  • 我不认为有必要对更新级联进行
    ,FacultyMail中没有任何内容需要更新。如果FacultyID可以更改,那么主键就不好。考虑与任何可变ID分开的独立ID列。
  • varchar(45)
    不节省任何空间,它只设置最大大小。最大大小是一个业务规则,不应硬编码到架构中

我不确定生成的列是否可以处理您想要的内容,因为它需要一个正式的查询来获取名字和姓氏。还有什么更好的选择@TimBiegeleisen?如果给定的教员只能有一个名字和姓氏,那么电子邮件数据可能属于
教员
表。也就是说,可以去掉
FacultyEmail
表。生成的列可能只引用当前行值,自动递增列除外。它不能引用其他行或其他表。您可以使用常规存储列和插入/更新触发器之前。感谢触发器示例和深入了解,我决定使用触发器路径。