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
表。生成的列可能只引用当前行值,自动递增列除外。它不能引用其他行或其他表。您可以使用常规存储列和插入/更新触发器之前。感谢触发器示例和深入了解,我决定使用触发器路径。