如何插入选择查询的结果(如果不返回任何行则默认)作为 Postgres 函数的一部分?

Posted

技术标签:

【中文标题】如何插入选择查询的结果(如果不返回任何行则默认)作为 Postgres 函数的一部分?【英文标题】:How to insert result of select query (with default if return no rows) as part of Postgres Function? 【发布时间】:2022-01-04 05:18:26 【问题描述】:

对于我的 Nextjs 网站,我将后端配置为在向 auth.users 表中插入一行时自动将用户信息添加到 public.profiles 表中(通过 Supabase 的身份验证自动完成)。

我有一个 public.college_emails 表,其中包含 1700 多所大学的名称以及与它们关联的电子邮件标签。当用户使用他们的学校电子邮件创建帐户时,我希望它返回与他们的电子邮件标签关联的大学名称,并将其输入到他们的“学校”字段中。否则,如果他们使用不在我列表中的电子邮件,它将插入“其他”。

我能够让 Supbase 编译我的 SQL 而没有语法错误,但是在尝试添加新用户时,它失败并出现错误 Database error when creating user。 (我发现这是当与用户创建相关的触发器或函数出现问题时。当我删除执行前面提到的功能的代码时,它工作正常(但只是没有正确选择大学名称。

这是我的 PostgreSQL 代码,它不起作用。它没有报告语法错误,但在尝试插入用户时失败:

create table if not exists public.profiles (
id uuid not null primary key, -- UUID from auth.users
email text,
full_name text,
avatar_url text,
created_at timestamp with time zone
);
create or replace function public.handle_new_user() 
returns trigger as $$
begin
  insert into public.profiles (id, email, full_name, school, created_at)
  values (new.id, new.email, SPLIT_PART(new.email, '@', 1), 
  (SELECT coalesce(college, 'Other') FROM college_emails WHERE tag = SPLIT_PART(new.email, '@', 2)) // THIS LINE DOES NOT WORK
  ,current_timestamp);
  return new;
end;
$$ language plpgsql security definer;

create trigger on_new_user_created
  after insert on auth.users
  for each row execute procedure public.handle_new_user();

我的大学表格格式为:

email (text): 'example@mycollege.edu'; college (text): 'My College'; tag (text): 'mycollege.edu'

这就是我现在的功能(恢复为工作版本以继续测试)。这缺少添加正确大学名称的代码。表和触发器保持不变:

create or replace function public.handle_new_user() 
returns trigger as $$
begin
  insert into public.profiles (id, email, full_name, school, created_at)
  values (new.id, new.email, SPLIT_PART(new.email, '@', 1), SPLIT_PART(SPLIT_PART(new.email, '@', 2), '.', 1)
  ,current_timestamp);
  return new;
end;
$$ language plpgsql security definer;

我的预期结果:

使用电子邮件“myname@uci.edi”的用户注册并添加到 auth.users。 向 public.profiles 添加了一个新行,其中包含电子邮件:“myname@uci.edu”、用户名:“myname”和 school: "University of California Irvine"

【问题讨论】:

【参考方案1】:

像这样更新你的触发函数public.handle_new_user()

create or replace function public.handle_new_user() 
returns trigger as $$
declare
  coll text ;
begin
  SELECT college
    INTO coll
    FROM college_emails 
   WHERE tag = SPLIT_PART(new.email, '@', 2);

  IF NOT FOUND
  THEN coll = 'Other' ;
  END IF ;
  
  INSERT INTO public.profiles (id, email, full_name, school, created_at)
  SELECT  new.id, new.email, SPLIT_PART(new.email, '@', 1), coll, current_timestamp ;
  return new;
end;
$$ language plpgsql security definer;

【讨论】:

目前好像不行,我尝试用学校邮箱注册,还是收到Database error saving new user 当new.email对应表college_emails中的一个标签时,触发函数工作得很好,但是当它不对应时,查询中没有选择行,所以没有行插入到表public中。配置文件。我已经相应地更新了答案并对其进行了测试here。尝试直接从 sql 客户端进行测试。 虽然我仍然收到错误,但我能够将错误隔离到 supbase 的 组件;通过插入语句直接将用户添加到 auth.users (例如您的示例)正确地添加了找到的大学的新个人资料。我会接受您的回答并在单独的问题中提出新问题,谢谢!

以上是关于如何插入选择查询的结果(如果不返回任何行则默认)作为 Postgres 函数的一部分?的主要内容,如果未能解决你的问题,请参考以下文章

测试通过 Mule JDBC 传输到嵌入式 HSQLDB 的插入,后续查询不返回任何结果

批量插入不插入

pymongo 查询未在烧瓶中返回任何内容

如何在sql中插入记录时返回id(id为自动增长)

如何将查询结果转换为字符串并将其插入表行

MAGNOLIA CMS - cmsu:simpleSearch 在作者实例中工作,但在公共实例中不返回任何结果