plpgsql函数:执行查询,处理记录和return原始结果集为table
plpgsql function: execute query, process records and return original result set as table
我想要一个执行以下操作的函数:执行查询,然后处理结果集中的所有数据记录,然后 returns 原始结果集。
所以我有这个 table:
employee_state_id | employee_id | start_date | end_date | state | created | modified
-------------------+-------------+------------+------------+-------+----------------------------+----------------------------
29 | 1 | 2008-12-15 | 2008-12-31 | 1 | 2020-02-12 02:26:56.999502 | 2020-02-12 02:26:56.999502
31 | 1 | 2009-01-01 | 2010-05-04 | 2 | 2020-02-12 02:27:42.973775 | 2020-02-12 02:27:42.973775
(2 rows)
有开始和结束日期的记录。如果此持续时间低于作为参数给出的值并且存在具有相同 ID 的后续记录,则合并这两个记录。最后,return 合并前记录的值。
select combine ('1', '2', 30);
调用后,table中应该只有一个条目如下:
(这已经适用于该功能)
employee_state_id | employee_id | start_date | end_date | state | created | modified
-------------------+-------------+------------+------------+-------+----------------------------+----------------------------
32 | 1 | 2008-12-15 | 2010-05-04 | 2 | 2020-02-12 01:36:51.731834 | 2020-02-12 01:36:51.731834
但是 table 应该像这样把原始记录还给我:
employee_id | a_employee_state_id | a_start_date | a_end_date | a_state | a_created | a_modified | b_employee_state_id | b_start_date | b_end_date | b_state | b_created | b_modified
-------------+---------------------+---------------+--------------+---------+----------------------------+----------------------------+---------------------+---------------+-------------+---------+----------------------------+---------------------------
1 | 29 | 2008-12-15 | 2008-12-31 | 1 | 2020-02-12 02:26:56.999502 | 2020-02-12 02:26:56.999502 | 31 | 2009-01-01 | 2010-05-04 | 2 | 2020-02-12 02:27:42.973775 | 2020-02-12 02:27:42.973775
但这不起作用。我得到这样的东西:
postgres=# select combine('1', '2', 30);
combine
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
(1,29,2008-12-15,2008-12-31,1,"2020-02-12 02:26:56.999502","2020-02-12 02:26:56.999502",31,2009-01-01,2010-05-04,2,"2020-02-12 02:27:42.973775","2020-02-12 02:27:42.973775")
(1 row)
我尝试了以下功能,但它似乎不起作用。有谁知道如何(更优雅地)解决这个任务?
CREATE OR REPLACE FUNCTION combine(changeFrom text, changeTo text, afterDays int4)
RETURNS TABLE (
employee_id int4,
a_employee_state_id int4,
a_start_date date,
a_end_date date,
a_state text,
a_created timestamp,
a_modified timestamp,
b_employee_state_id int4,
b_start_date date,
b_end_date date,
b_state text,
b_created timestamp,
b_modified timestamp
)
AS $$
DECLARE
rec RECORD;
begin
FOR rec in
SELECT -- this query works
a1.employee_id,
a1.employee_state_id AS a_employee_state_id,
a1.start_date AS a_start_date,
a1.end_date AS a_end_date,
a1.state AS a_state,
a1.created AS a_created,
a1.modified AS a_modified,
a2.employee_state_id AS b_employee_state_id,
a2.start_date AS b_start_date,
a2.end_date AS b_end_date,
a2.state AS b_state,
a2.created AS b_created,
a2.modified AS b_modified
FROM
employee_state AS a1,
employee_state AS a2
WHERE
a1.employee_id = a2.employee_id
AND a1.state = changeFrom
AND a1.end_date - a1.start_date < afterDays
AND a2.state = changeTo
AND a1.end_date + 1 = a2.start_date
LOOP
employee_id := rec.employee_id;
a_employee_state_id := rec.a_employee_state_id;
a_start_date := rec.a_start_date;
a_end_date := rec.a_end_date;
a_state := rec.a_state;
a_created := rec.a_created;
a_modified := rec.a_modified;
b_employee_state_id := rec.b_employee_state_id;
b_start_date:= rec.b_start_date;
b_end_date := rec.b_end_date;
b_state := rec.b_state;
b_created := rec.b_created;
b_modified := rec.b_modified;
INSERT INTO
employee_state
(employee_id, start_date, end_date, state)
VALUES
(rec.employee_id, rec.a_start_date, rec.b_end_date, rec.b_state);
DELETE FROM employee_state AS b
WHERE b.employee_id = rec.employee_id
AND b.start_date= rec.b_start_date
AND b.end_date = rec.b_end_date
AND b.state = rec.b_state;
DELETE FROM employee_state AS b
WHERE b.employee_id = rec.employee_id
AND b.start_date= rec.a_start_date
AND b.end_date = rec.a_end_date
AND b.state = rec.a_state;
return next;
END LOOP;
END;
$$
LANGUAGE plpgsql;
我是 sql 菜鸟,所以请帮忙。谢谢。
--- 你可以用这个
创建table
CREATE TABLE employee_state (
employee_state_id serial UNIQUE NOT NULL,
employee_id int4 NOT NULL,
start_date date NULL,
end_date date NULL,
state text null,
created timestamp default now(),
modified timestamp default now()
);
insert into employee_state (employee_id, start_date, end_date, state) values (1, '2008-12-15', '2008-12-31', '1');
insert into employee_state (employee_id, start_date, end_date, state) values (1, '2009-01-01', '2010-05-04', '2');
您的功能运行良好。您只需要像调用 table:
一样调用该函数
postgres=# delete from employee_state ;
DELETE 2
postgres=# insert into employee_state (employee_id, start_date, end_date, state) values (1, '2008-12-15', '2008-12-31', '1');
INSERT 0 1
postgres=# insert into employee_state (employee_id, start_date, end_date, state) values (1, '2009-01-01', '2010-05-04', '2');
INSERT 0 1
postgres=# select * from employee_state;
employee_state_id | employee_id | start_date | end_date | state | created | modified
-------------------+-------------+------------+------------+-------+----------------------------+----------------------------
6 | 1 | 2008-12-15 | 2008-12-31 | 1 | 2020-02-13 06:31:56.942556 | 2020-02-13 06:31:56.942556
7 | 1 | 2009-01-01 | 2010-05-04 | 2 | 2020-02-13 06:31:57.024654 | 2020-02-13 06:31:57.024654
(2 rows)
postgres=# select combine('1', '2', 30);
combine
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
(1,6,2008-12-15,2008-12-31,1,"2020-02-13 06:31:56.942556","2020-02-13 06:31:56.942556",7,2009-01-01,2010-05-04,2,"2020-02-13 06:31:57.024654","2020-02-13 06:31:57.024654")
(1 row)
postgres=# delete from employee_state ;
DELETE 1
postgres=# insert into employee_state (employee_id, start_date, end_date, state) values (1, '2008-12-15', '2008-12-31', '1');
INSERT 0 1
postgres=# insert into employee_state (employee_id, start_date, end_date, state) values (1, '2009-01-01', '2010-05-04', '2');
INSERT 0 1
postgres=# select * from combine('1', '2', 30);
employee_id | a_employee_state_id | a_start_date | a_end_date | a_state | a_created | a_modified | b_employee_state_id | b_start_date | b_end_date | b_state | b
_created | b_modified
-------------+---------------------+--------------+------------+---------+----------------------------+----------------------------+---------------------+--------------+------------+---------+----------
------------------+----------------------------
1 | 9 | 2008-12-15 | 2008-12-31 | 1 | 2020-02-13 06:32:12.635742 | 2020-02-13 06:32:12.635742 | 10 | 2009-01-01 | 2010-05-04 | 2 | 2020-02-1
3 06:32:12.717752 | 2020-02-13 06:32:12.717752
(1 row)
披露:我为 EnterpriseDB (EDB)
工作
我想要一个执行以下操作的函数:执行查询,然后处理结果集中的所有数据记录,然后 returns 原始结果集。 所以我有这个 table:
employee_state_id | employee_id | start_date | end_date | state | created | modified
-------------------+-------------+------------+------------+-------+----------------------------+----------------------------
29 | 1 | 2008-12-15 | 2008-12-31 | 1 | 2020-02-12 02:26:56.999502 | 2020-02-12 02:26:56.999502
31 | 1 | 2009-01-01 | 2010-05-04 | 2 | 2020-02-12 02:27:42.973775 | 2020-02-12 02:27:42.973775
(2 rows)
有开始和结束日期的记录。如果此持续时间低于作为参数给出的值并且存在具有相同 ID 的后续记录,则合并这两个记录。最后,return 合并前记录的值。
select combine ('1', '2', 30);
调用后,table中应该只有一个条目如下:
(这已经适用于该功能)
employee_state_id | employee_id | start_date | end_date | state | created | modified
-------------------+-------------+------------+------------+-------+----------------------------+----------------------------
32 | 1 | 2008-12-15 | 2010-05-04 | 2 | 2020-02-12 01:36:51.731834 | 2020-02-12 01:36:51.731834
但是 table 应该像这样把原始记录还给我:
employee_id | a_employee_state_id | a_start_date | a_end_date | a_state | a_created | a_modified | b_employee_state_id | b_start_date | b_end_date | b_state | b_created | b_modified
-------------+---------------------+---------------+--------------+---------+----------------------------+----------------------------+---------------------+---------------+-------------+---------+----------------------------+---------------------------
1 | 29 | 2008-12-15 | 2008-12-31 | 1 | 2020-02-12 02:26:56.999502 | 2020-02-12 02:26:56.999502 | 31 | 2009-01-01 | 2010-05-04 | 2 | 2020-02-12 02:27:42.973775 | 2020-02-12 02:27:42.973775
但这不起作用。我得到这样的东西:
postgres=# select combine('1', '2', 30);
combine
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
(1,29,2008-12-15,2008-12-31,1,"2020-02-12 02:26:56.999502","2020-02-12 02:26:56.999502",31,2009-01-01,2010-05-04,2,"2020-02-12 02:27:42.973775","2020-02-12 02:27:42.973775")
(1 row)
我尝试了以下功能,但它似乎不起作用。有谁知道如何(更优雅地)解决这个任务?
CREATE OR REPLACE FUNCTION combine(changeFrom text, changeTo text, afterDays int4)
RETURNS TABLE (
employee_id int4,
a_employee_state_id int4,
a_start_date date,
a_end_date date,
a_state text,
a_created timestamp,
a_modified timestamp,
b_employee_state_id int4,
b_start_date date,
b_end_date date,
b_state text,
b_created timestamp,
b_modified timestamp
)
AS $$
DECLARE
rec RECORD;
begin
FOR rec in
SELECT -- this query works
a1.employee_id,
a1.employee_state_id AS a_employee_state_id,
a1.start_date AS a_start_date,
a1.end_date AS a_end_date,
a1.state AS a_state,
a1.created AS a_created,
a1.modified AS a_modified,
a2.employee_state_id AS b_employee_state_id,
a2.start_date AS b_start_date,
a2.end_date AS b_end_date,
a2.state AS b_state,
a2.created AS b_created,
a2.modified AS b_modified
FROM
employee_state AS a1,
employee_state AS a2
WHERE
a1.employee_id = a2.employee_id
AND a1.state = changeFrom
AND a1.end_date - a1.start_date < afterDays
AND a2.state = changeTo
AND a1.end_date + 1 = a2.start_date
LOOP
employee_id := rec.employee_id;
a_employee_state_id := rec.a_employee_state_id;
a_start_date := rec.a_start_date;
a_end_date := rec.a_end_date;
a_state := rec.a_state;
a_created := rec.a_created;
a_modified := rec.a_modified;
b_employee_state_id := rec.b_employee_state_id;
b_start_date:= rec.b_start_date;
b_end_date := rec.b_end_date;
b_state := rec.b_state;
b_created := rec.b_created;
b_modified := rec.b_modified;
INSERT INTO
employee_state
(employee_id, start_date, end_date, state)
VALUES
(rec.employee_id, rec.a_start_date, rec.b_end_date, rec.b_state);
DELETE FROM employee_state AS b
WHERE b.employee_id = rec.employee_id
AND b.start_date= rec.b_start_date
AND b.end_date = rec.b_end_date
AND b.state = rec.b_state;
DELETE FROM employee_state AS b
WHERE b.employee_id = rec.employee_id
AND b.start_date= rec.a_start_date
AND b.end_date = rec.a_end_date
AND b.state = rec.a_state;
return next;
END LOOP;
END;
$$
LANGUAGE plpgsql;
我是 sql 菜鸟,所以请帮忙。谢谢。
--- 你可以用这个
创建tableCREATE TABLE employee_state (
employee_state_id serial UNIQUE NOT NULL,
employee_id int4 NOT NULL,
start_date date NULL,
end_date date NULL,
state text null,
created timestamp default now(),
modified timestamp default now()
);
insert into employee_state (employee_id, start_date, end_date, state) values (1, '2008-12-15', '2008-12-31', '1');
insert into employee_state (employee_id, start_date, end_date, state) values (1, '2009-01-01', '2010-05-04', '2');
您的功能运行良好。您只需要像调用 table:
一样调用该函数postgres=# delete from employee_state ;
DELETE 2
postgres=# insert into employee_state (employee_id, start_date, end_date, state) values (1, '2008-12-15', '2008-12-31', '1');
INSERT 0 1
postgres=# insert into employee_state (employee_id, start_date, end_date, state) values (1, '2009-01-01', '2010-05-04', '2');
INSERT 0 1
postgres=# select * from employee_state;
employee_state_id | employee_id | start_date | end_date | state | created | modified
-------------------+-------------+------------+------------+-------+----------------------------+----------------------------
6 | 1 | 2008-12-15 | 2008-12-31 | 1 | 2020-02-13 06:31:56.942556 | 2020-02-13 06:31:56.942556
7 | 1 | 2009-01-01 | 2010-05-04 | 2 | 2020-02-13 06:31:57.024654 | 2020-02-13 06:31:57.024654
(2 rows)
postgres=# select combine('1', '2', 30);
combine
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
(1,6,2008-12-15,2008-12-31,1,"2020-02-13 06:31:56.942556","2020-02-13 06:31:56.942556",7,2009-01-01,2010-05-04,2,"2020-02-13 06:31:57.024654","2020-02-13 06:31:57.024654")
(1 row)
postgres=# delete from employee_state ;
DELETE 1
postgres=# insert into employee_state (employee_id, start_date, end_date, state) values (1, '2008-12-15', '2008-12-31', '1');
INSERT 0 1
postgres=# insert into employee_state (employee_id, start_date, end_date, state) values (1, '2009-01-01', '2010-05-04', '2');
INSERT 0 1
postgres=# select * from combine('1', '2', 30);
employee_id | a_employee_state_id | a_start_date | a_end_date | a_state | a_created | a_modified | b_employee_state_id | b_start_date | b_end_date | b_state | b
_created | b_modified
-------------+---------------------+--------------+------------+---------+----------------------------+----------------------------+---------------------+--------------+------------+---------+----------
------------------+----------------------------
1 | 9 | 2008-12-15 | 2008-12-31 | 1 | 2020-02-13 06:32:12.635742 | 2020-02-13 06:32:12.635742 | 10 | 2009-01-01 | 2010-05-04 | 2 | 2020-02-1
3 06:32:12.717752 | 2020-02-13 06:32:12.717752
(1 row)
披露:我为 EnterpriseDB (EDB)
工作