Postgres:函数中的临时 table 是持久的。为什么?
Postgres: Temporary table in function is persistent. Why?
我的 postgresql 数据库中有以下函数:
CREATE OR REPLACE FUNCTION get_unused_part_ids()
RETURNS integer[] AS
$BODY$
DECLARE
part_ids integer ARRAY;
BEGIN
create temporary table tmp_parts
as
select vendor_id, part_number, max(price) as max_price
from refinery_akouo_parts
where retired = false
group by vendor_id, part_number
having min(price) < max(price);
-- do some work etc etc
-- simulate ids being returned
part_ids = '{1,2,3,4}';
return part_ids;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION get_unused_part_ids()
OWNER TO postgres;
这可以编译,但是当我 运行:
select get_unused_part_ids();
临时 table、tmp_parts
仍然存在。之后我可以在上面做一个 select。请原谅我,因为我已经习惯了 t-sql/MSSQL 的特定功能。 MSSQL 不会出现这种情况。我做错了什么?
之后
Temporary tables are automatically dropped at the end of a session, or optionally at the end of the current transaction (see ON COMMIT below)
断开连接后会话结束。不是在事务提交之后。所以默认行为是保留 temp table 直到你的连接仍然打开。您必须添加 ON COMMIT DROP;
才能实现您想要的行为:
create temporary table tmp_parts on commit drop
as
select vendor_id, part_number, max(price) as max_price
from refinery_akouo_parts
where retired = false
group by vendor_id, part_number
having min(price) < max(price)
on commit drop;
临时 table 在两个数据库中的处理方式不同。在 SQL 服务器中,它们将在创建它们的存储过程结束时自动删除。
在 Postgres 中,临时 table 被分配给会话(或事务),如 documentation:
中所述
If specified, the table is created as a temporary table. Temporary
tables are automatically dropped at the end of a session, or
optionally at the end of the current transaction (see ON COMMIT
below). Existing permanent tables with the same name are not visible
to the current session while the temporary table exists, unless they
are referenced with schema-qualified names. Any indexes created on a
temporary table are automatically temporary as well.
这个概念介于 SQL 服务器中的常规临时 table 和全局临时 table 之间(全局临时 table 以 ##
).
table只会在会话结束时删除。您需要指定 ON COMMIT 选项才能删除,它会在事务结束时删除 table。
create temporary table tmp_parts
on commit drop
as
select vendor_id, part_number, max(price) as max_price
from refinery_akouo_parts
where retired = false
group by vendor_id, part_number
having min(price) < max(price);
我的 postgresql 数据库中有以下函数:
CREATE OR REPLACE FUNCTION get_unused_part_ids()
RETURNS integer[] AS
$BODY$
DECLARE
part_ids integer ARRAY;
BEGIN
create temporary table tmp_parts
as
select vendor_id, part_number, max(price) as max_price
from refinery_akouo_parts
where retired = false
group by vendor_id, part_number
having min(price) < max(price);
-- do some work etc etc
-- simulate ids being returned
part_ids = '{1,2,3,4}';
return part_ids;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION get_unused_part_ids()
OWNER TO postgres;
这可以编译,但是当我 运行:
select get_unused_part_ids();
临时 table、tmp_parts
仍然存在。之后我可以在上面做一个 select。请原谅我,因为我已经习惯了 t-sql/MSSQL 的特定功能。 MSSQL 不会出现这种情况。我做错了什么?
Temporary tables are automatically dropped at the end of a session, or optionally at the end of the current transaction (see ON COMMIT below)
断开连接后会话结束。不是在事务提交之后。所以默认行为是保留 temp table 直到你的连接仍然打开。您必须添加 ON COMMIT DROP;
才能实现您想要的行为:
create temporary table tmp_parts on commit drop
as
select vendor_id, part_number, max(price) as max_price
from refinery_akouo_parts
where retired = false
group by vendor_id, part_number
having min(price) < max(price)
on commit drop;
临时 table 在两个数据库中的处理方式不同。在 SQL 服务器中,它们将在创建它们的存储过程结束时自动删除。
在 Postgres 中,临时 table 被分配给会话(或事务),如 documentation:
中所述If specified, the table is created as a temporary table. Temporary tables are automatically dropped at the end of a session, or optionally at the end of the current transaction (see ON COMMIT below). Existing permanent tables with the same name are not visible to the current session while the temporary table exists, unless they are referenced with schema-qualified names. Any indexes created on a temporary table are automatically temporary as well.
这个概念介于 SQL 服务器中的常规临时 table 和全局临时 table 之间(全局临时 table 以 ##
).
table只会在会话结束时删除。您需要指定 ON COMMIT 选项才能删除,它会在事务结束时删除 table。
create temporary table tmp_parts
on commit drop
as
select vendor_id, part_number, max(price) as max_price
from refinery_akouo_parts
where retired = false
group by vendor_id, part_number
having min(price) < max(price);