将 query/table 返回到变量中

Returning query/table into a variable

按照 here 的说明,我正在尝试 return 将查询结果转换为变量

DROP DATABASE IF EXISTS test;
CREATE DATABASE test;

\c test

CREATE TABLE staff(
    id BIGSERIAL PRIMARY KEY,
    first_name   VARCHAR(50),
    last_name    VARCHAR(50),
    age          SMALLINT
);

CREATE FUNCTION get_contacts(
    p_id_min  BIGINT,
    p_id_max  BIGINT,
    p_age_min BIGINT,
    p_age_max BIGINT
)
    RETURNS @contacts TABLE (
        first_name VARCHAR(50),
        last_name  VARCHAR(50)
    )
AS
BEGIN
    INSERT INTO @contacts
    SELECT 
        first_name, 
        last_name
    FROM
        staff
    WHERE
        id >= p_id_min
    AND
        id <= p_id_max;

    INSERT INTO @contacts
    SELECT 
        first_name, 
        last_name
    FROM
        staff
    WHERE
        age >= p_age_min
    AND
        age <= p_age_max;

    RETURN;
END;

但我收到以下错误

DROP DATABASE
CREATE DATABASE
You are now connected to database "test" as user "postgres".
CREATE TABLE
psql:test.sql:31: ERROR:  syntax error at or near "@"
LINE 5:     RETURNS @contacts TABLE (
                    ^
psql:test.sql:33: ERROR:  syntax error at or near "RETURN"
LINE 1: RETURN;
        ^
psql:test.sql:34: WARNING:  there is no transaction in progress
COMMIT

我有两个问题:

  1. 为什么我会收到 syntax error at or near "@" 以及如何解决问题?
  2. 变量名开头的@有什么意义?

事实证明,在 Postgres 中,RETURN 命令可以多次使用,所以我只做了以下操作

CREATE FUNCTION get_contacts(
    p_id_min  BIGINT,
    p_id_max  BIGINT,
    p_age_min BIGINT,
    p_age_max BIGINT
)
RETURNS TABLE(
    id          BIGINT,
    first_name  VARCHAR(50),
    last_name   VARCHAR(50),
    age         SMALLINT
)
AS $$
BEGIN
    --RETURN FIRST QUERY
    RETURN QUERY
        SELECT * FROM staff
        WHERE id >=p_id_min AND id<=p_id_max;

    --DO OTHER WORK
    ...

    --RETURN SECOND QUERY
    RETURN QUERY
        SELECT * FROM staff
        WHERE age >=p_age_min AND age<=p_age_max;
END $$ LAnguage 'plpgsql';

作者最初使用@作为参数。对于代码,你也可以试试这个

CREATE FUNCTION get_contacts(
p_id_min  BIGINT,
p_id_max  BIGINT,
p_age_min BIGINT,
p_age_max BIGINT
)
RETURNS TABLE (
    first_name VARCHAR(50),
    last_name  VARCHAR(50)
)
AS $$
BEGIN
INSERT INTO @contacts
SELECT 
    first_name, 
    last_name
FROM
    staff
WHERE
    id >= p_id_min
AND
    id <= p_id_max;

INSERT INTO @contacts
SELECT 
    first_name, 
    last_name
FROM
    staff
WHERE
    age >= p_age_min
AND
    age <= p_age_max;

RETURN;
END;