我可以使用 postgreSQL 根据名字和姓氏的输入为用户创建电子邮件吗?

Can I create an email for the user based on input for the first and last name using postgreSQL?

我是 Postgres 的新手,我正在制作一个模拟数据库来管理一所大学的学生,这样我就可以更好地了解 Postgres 的工作原理。

我正在创建一个学生 table,其中包含学生 ID、入学日期、毕业年份、first/last 姓名和大学电子邮件地址等列。目前我只是将电子邮件列设置为 NOT NULL,用户必须输入他们自己的电子邮件地址,但显然这不是大学电子邮件地址的工作方式。

我想知道是否有办法根据用户输入的名字和姓氏动态创建电子邮件。例如,如果我要 运行 以下查询:

INSERT INTO students (first_name, last_name) VALUES ('bob', 'smith');

将以 'bobsmith@university.com' 格式为 bob smith 即时创建电子邮件地址,因此我的 table 将如下所示:

 student_id | enrollment_date | grad_year |             email              | student_first | student_last 
------------+-----------------+-----------+--------------------------------+---------------+--------------
          2 | 2020-12-28      |    2024   |     bobsmith@university.com    |      bob      | smith

有没有一种方法可以创建一个函数,从 student_first 和 student_last 列中获取值并根据它们创建电子邮件?

任何指向可读文档的链接都会有用。

An email address would be created on the fly for bob smith in the format 'bobsmith@university.com'

您可以使用 generated column:

create table students (
    student_id serial primary key,
    first_name text not null,
    last_name text not null,
    ...
    email text 
        generated always as (first_name || '.' || last_name || '@university.com') 
        stored
);

Demo on DB Fiddle:

INSERT INTO students (first_name, last_name) VALUES ('bob', 'smith');
-- 1 rows affected

SELECT * FROM students;

student_id | first_name | last_name | email                   
---------: | :--------- | :-------- | :-----------------------
         1 | bob        | smith     | bob.smith@university.com

有几种方法可以完成您想要的事情:function/procedure 或(我不想说)Trugger。但是,生成的列在这种情况下不起作用:第二个学生“Bob Smith”注册时会发生什么。您可以使用一个函数来生成电子邮件地址 - 如果需要,可以使用一个数字来使其唯一。

create or replace 
function generate_email_address(first_name_in text
                               ,last_name_in  text
                               )
  returns text 
  language sql 
as $$
   with email(num) as 
        ( select count(*) 
            from students 
           where lower(first_name) = lower(first_name_in) 
             and lower(last_name)  = lower(last_name_in) 
        ) 
   select lower(first_name_in) ||
          lower(last_name_in)  || 
          case when num = 0 then '' else to_char(num+1,'FM99') end ||
          '@university.com'
     from email; 
$$; 

example: