首页 > 解决方案 > Postgresql在for循环中获取单列

问题描述

这可能真的很容易,但它让我发疯。

我有以下功能:

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;

id我明白了,这意味着我不能只group说,但 我group.id真的要疯了
for 循环中的一行?

标签: postgresqlplpgsql

解决方案


你把事情复杂化了。您的要求可以通过单个 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 子句没有返回匹配项,max(id)则将产生null并将其coalesce()变为 0(尽管我认为 anull会更有意义)。

如果 WHERE 子句匹配一行,则查询将返回最高 ID。由于您只期望查询中有一行,因此聚合函数不会改变这一点。


如果你真的希望它是一个 PL/pgSQL 函数,你可以使用手册中显示FOUND的状态:

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;

推荐阅读