CREATE OR REPLACE FUNCTION()
RETURND VOID AS
BEGIN
FOR I IN 1..5
LOOP
LOCK TABLE tbl_Employee1 IN EXCLUSIVE MODE;
INSERT INTO tbl_Employee1
VALUES
(i,'test');
END LOOP;
COMMIT;
END;
$$ LANGUAGE PLPGSQL
当我选择表格时,它将进入无限循环,这表示事务未完成。请帮帮我吗?
答案 0 :(得分:1)
您的代码已被精简,以至于不再有意义。
但是,您应该只锁定一次表,而不是在循环的每次迭代中。另外,您不能在Postgres的函数中使用commit
,因此也必须将其删除。不提供insert语句的列名也是不好的编码风格(在Postgres 和 Oracle中)。
立即解决方案:
CREATE OR REPLACE FUNCTION ...
RETURNS VOID AS
$$
BEGIN
LOCK TABLE Employee1 IN EXCLUSIVE MODE;
FOR I IN 1..5 LOOP
INSERT INTO Employee1 (id, name)
VALUES (i,'test');
END LOOP;
-- no commit here!
END;
$$ LANGUAGE PLPGSQL
以上内容在Postgres中不必要地复杂,可以更有效地实现很多,而无需循环:
CREATE OR REPLACE FUNCTION ....
RETURNS VOID AS
$$
BEGIN
LOCK TABLE Employee1 IN EXCLUSIVE MODE;
INSERT INTO Employee1 (id, name)
select i, test
from generate_series(1,5);
END;
$$ LANGUAGE PLPGSQL
首先以互斥模式锁定表似乎是个坏主意。在Oracle中也是如此,但在Postgres中可能有更多severe implications。如果要防止表中出现重复项,请创建唯一索引(或约束)并处理错误。或在Postgres中使用insert ... on conflict
。这将比锁定整个表更加有效(和可扩展)。
此外:LOCK TABLE IN EXCLUSIVE MODE;
在Oracle和Postgres中表现不同。尽管Oracle仍然允许对该表进行只读查询,但是您可以在Postgres中阻止对其的每次访问-包括 SELECT语句。