Postgresql在for循环中获取单列行

Postgresql get single column of row in for loop

这可能真的很简单,但它让我抓狂。

我有以下功能:

CREATE OR REPLACE FUNCTION get_group(serverid BIGINT, name VARCHAR(100)) RETURNS BIGINT
LANGUAGE plpgsql
AS $$
DECLARE
    group server_groups%ROWTYPE;
BEGIN
    FOR group IN SELECT * FROM server_groups WHERE server_id = serverid AND LOWER(group_name) = LOWER(name) LOOP
        RETURN group.id;
    END LOOP;
    RETURN 0;
END;
$$;

以及下表:

服务器

server_id |  server_name
----------+---------------
 3251623  |  ServerOfDoom
 5578921  |  BestServerEU

server_groups

id | server_id |  group_name
---+----------+---------------
 1 |  3251623  |  aNiceGroup
 2 |  5578921  |  Valorant
 3 |  5578921  |  Admins

但是在执行我的函数查询时出现以下错误:

ERROR:  syntax error at or near "."
LINE 8:         RETURN group.id;

我知道这意味着我不能通过说 group.id 只得到 group 行的 id,但我真的很疯狂地发现访问后如何100 个不同的网站(也许我只是一个糟糕的 Google 员工)
如何在 for 循环中获取一行的单个属性?

你把事情复杂化了。您的要求可以通过单个 SQL 查询(可以包装在 SQL 函数中)来实现:

CREATE OR REPLACE FUNCTION get_group(serverid BIGINT, name VARCHAR(100)) 
  RETURNS BIGINT
as
$$
  select coalesce(max(id), 0) as id
  from server_groups 
  where server_id = serverid 
    and lower(group_name) = lower(name);
$$
language sql
stable;

如果 WHERE 子句 return 不匹配,max(id) 将产生 nullcoalesce() 会将其变成 0(尽管我认为 null 会更有意义)。

如果WHERE子句匹配一行,查询将return最高ID。由于您只期望查询中的一行,聚合函数不会改变它。


如果您真的希望它成为一个 PL/pgSQL 函数,您可以使用 FOUND 状态 as shown in the manual:

CREATE OR REPLACE FUNCTION get_group(serverid BIGINT, name VARCHAR(100)) 
  RETURNS BIGINT
AS $$
declare
  group_id int;
BEGIN
  select id
    into group_id
  from server_groups 
  where server_id = serverid 
  and lower(group_name) = lower(name);
  
  if found then
    return group_id;
  else 
    return 0;
  end if;
END;
$$
LANGUAGE plpgsql;