Postgresql 忽略 if 条件
Postgresql ignoring if condition
我正在尝试了解 plpgsql 中的事务,我想要一些解释。
我有这个代码:
CREATE OR REPLACE PROCEDURE MaJ(mode IN INT)
AS
$$
DECLARE
r RECORD;
DECLARE
r RECORD;
BEGIN
FOR r IN SELECT id, fname, lname, bday FROM usr
LOOP
IF r.ID % 2 = 0 THEN
UPDATE usr SET lname = 'KONAN';
RAISE NOTICE E'fname : %\n', r.lname;
END IF;
END LOOP;
IF mode = 0 THEN
COMMIT;
ELSE IF mode = 1 THEN
ROLLBACK;
END IF;
END;
- 首先,在获得并尝试所有可能的解决方案之后,根据过程参数实现 commit/rollback 的最佳方法是什么。
- 其次,除了 comit 回滚问题,postgres 完全忽略了 if
IF r.ID % 2 = 0 THEN
并更新了所有条目,感谢您的任何解释。
我正在使用 CALL MaJ(VAL);
从另一个过程调用此过程
更新:
也许这段代码更好地描述了问题:
这是我正在尝试做的事情:
CREATE OR REPLACE PROCEDURE CRDM(Crtrn INOUT INT)
AS
$CRDM$
DECLARE
R RECORD;
BEGIN
FOR R IN SELECT * FROM usr
LOOP
IF R.ID % 2 = 0 THEN
UPDATE USR SET lname = 'MAGNI' WHERE USR.ID = R.ID;
END IF;
END LOOP;
IF Crtrn = 0 THEN
COMMIT;
ELSE
ROLLBACK;
END IF;
END;
$CRDM$ LANGUAGE plpgsql;
CREATE OR REPLACE PROCEDURE AMI()
AS
$AMI$
DECLARE
rtrn INT:=0;
BEGIN
BEGIN
CALL CRDM(rtrn);
END;
END;
$AMI$ LANGUAGE plpgsql;
DO
$$
BEGIN
CALL AMI();
END;
$$ LANGUAGE plpgsql;
欢迎就我遗漏的内容以及如何更好地思考交易提供任何帮助。
您的“提交;”和“回滚;”读完这篇文章后我觉得逻辑没问题:https://www.postgresql.org/docs/current/plpgsql-transactions.html
您可能需要“开始;”在您“调用”您的程序之前的交易:我不确定。
您的第二个问题很简单:您的 UPDATE 语句没有 WHERE 子句。确保通过匹配 ID 值仅更新当前循环记录。
只有在新版本中才能使用 ROLLBACK
或 COMMIT
。如果支持这些命令,请检查您使用的版本。
很长一段时间 Postgres 存储过程没有这些命令也没有问题。在 PL/pgSQL 中使用 COMMIT
、ROLLBACK
并不太原生——主要是为了更容易从 Oracle 迁移而实现的,但是因为 Oracle 和 Postgres 的事务模型非常不同,所以有很多限制。
Oracle 在登录后启动隐式事务并等待显式 commit
或 rollback
。在这些命令之后,Oracle 立即开始新事务。
在 Postgres 中,每条语句都像在 Oracle 中一样在事务下执行。但如果交易是由用户发起的,则用户负责 commit
或 rollback
。如果用户没有启动事务,则 Postgres 启动事务,并且 Postgres 在操作引发异常时隐式运行 rollback
,否则运行 commit
。异常后只允许rollback
。
通常在 Postgres 中没有必要使用 commit
或 rollback
。只需引发异常,上层就会完成所有必要的工作。
你的代码不好,请尝试阅读文档和一些关于编程风格的注释。不要使用 Camel 表示法 - 不区分大小写的语言。
CREATE TABLE foo_tab(id int);
CREATE TABLE boo_tab(id int, b text);
INSERT INTO foo_tab VALUES(1);
INSERT INTO foo_tab VALUES(2);
CREATE OR REPLACE PROCEDURE foo(a bool, b text)
AS $$
DECLARE r record;
BEGIN
FOR r IN SELECT * FROM foo_tab
LOOP
INSERT INTO boo_tab VALUES(r.id, b);
END LOOP;
IF a THEN
COMMIT;
ELSE
ROLLBACK;
END IF;
END
$$ LANGUAGE plpgsql;
CREATE OR REPLACE PROCEDURE foo2(a bool, b text)
AS $$
BEGIN
CALL foo(a, b);
END;
$$ LANGUAGE plpgsql;
DO $$
BEGIN
CALL foo2(true, 'Ahoj');
CALL foo2(false, 'Nazdar');
END;
$$; -- LANGUAGE plpgsql is implicit here
postgres=# SELECT * FROM boo_tab;
┌────┬──────┐
│ id │ b │
╞════╪══════╡
│ 1 │ Ahoj │
│ 2 │ Ahoj │
└────┴──────┘
(2 rows)
在 Postgres 13 上测试
我正在尝试了解 plpgsql 中的事务,我想要一些解释。
我有这个代码:
CREATE OR REPLACE PROCEDURE MaJ(mode IN INT)
AS
$$
DECLARE
r RECORD;
DECLARE
r RECORD;
BEGIN
FOR r IN SELECT id, fname, lname, bday FROM usr
LOOP
IF r.ID % 2 = 0 THEN
UPDATE usr SET lname = 'KONAN';
RAISE NOTICE E'fname : %\n', r.lname;
END IF;
END LOOP;
IF mode = 0 THEN
COMMIT;
ELSE IF mode = 1 THEN
ROLLBACK;
END IF;
END;
- 首先,在获得并尝试所有可能的解决方案之后,根据过程参数实现 commit/rollback 的最佳方法是什么。
- 其次,除了 comit 回滚问题,postgres 完全忽略了 if
IF r.ID % 2 = 0 THEN
并更新了所有条目,感谢您的任何解释。
我正在使用 CALL MaJ(VAL);
更新: 也许这段代码更好地描述了问题: 这是我正在尝试做的事情:
CREATE OR REPLACE PROCEDURE CRDM(Crtrn INOUT INT)
AS
$CRDM$
DECLARE
R RECORD;
BEGIN
FOR R IN SELECT * FROM usr
LOOP
IF R.ID % 2 = 0 THEN
UPDATE USR SET lname = 'MAGNI' WHERE USR.ID = R.ID;
END IF;
END LOOP;
IF Crtrn = 0 THEN
COMMIT;
ELSE
ROLLBACK;
END IF;
END;
$CRDM$ LANGUAGE plpgsql;
CREATE OR REPLACE PROCEDURE AMI()
AS
$AMI$
DECLARE
rtrn INT:=0;
BEGIN
BEGIN
CALL CRDM(rtrn);
END;
END;
$AMI$ LANGUAGE plpgsql;
DO
$$
BEGIN
CALL AMI();
END;
$$ LANGUAGE plpgsql;
欢迎就我遗漏的内容以及如何更好地思考交易提供任何帮助。
您的“提交;”和“回滚;”读完这篇文章后我觉得逻辑没问题:https://www.postgresql.org/docs/current/plpgsql-transactions.html
您可能需要“开始;”在您“调用”您的程序之前的交易:我不确定。
您的第二个问题很简单:您的 UPDATE 语句没有 WHERE 子句。确保通过匹配 ID 值仅更新当前循环记录。
只有在新版本中才能使用 ROLLBACK
或 COMMIT
。如果支持这些命令,请检查您使用的版本。
很长一段时间 Postgres 存储过程没有这些命令也没有问题。在 PL/pgSQL 中使用 COMMIT
、ROLLBACK
并不太原生——主要是为了更容易从 Oracle 迁移而实现的,但是因为 Oracle 和 Postgres 的事务模型非常不同,所以有很多限制。
Oracle 在登录后启动隐式事务并等待显式 commit
或 rollback
。在这些命令之后,Oracle 立即开始新事务。
在 Postgres 中,每条语句都像在 Oracle 中一样在事务下执行。但如果交易是由用户发起的,则用户负责 commit
或 rollback
。如果用户没有启动事务,则 Postgres 启动事务,并且 Postgres 在操作引发异常时隐式运行 rollback
,否则运行 commit
。异常后只允许rollback
。
通常在 Postgres 中没有必要使用 commit
或 rollback
。只需引发异常,上层就会完成所有必要的工作。
你的代码不好,请尝试阅读文档和一些关于编程风格的注释。不要使用 Camel 表示法 - 不区分大小写的语言。
CREATE TABLE foo_tab(id int);
CREATE TABLE boo_tab(id int, b text);
INSERT INTO foo_tab VALUES(1);
INSERT INTO foo_tab VALUES(2);
CREATE OR REPLACE PROCEDURE foo(a bool, b text)
AS $$
DECLARE r record;
BEGIN
FOR r IN SELECT * FROM foo_tab
LOOP
INSERT INTO boo_tab VALUES(r.id, b);
END LOOP;
IF a THEN
COMMIT;
ELSE
ROLLBACK;
END IF;
END
$$ LANGUAGE plpgsql;
CREATE OR REPLACE PROCEDURE foo2(a bool, b text)
AS $$
BEGIN
CALL foo(a, b);
END;
$$ LANGUAGE plpgsql;
DO $$
BEGIN
CALL foo2(true, 'Ahoj');
CALL foo2(false, 'Nazdar');
END;
$$; -- LANGUAGE plpgsql is implicit here
postgres=# SELECT * FROM boo_tab;
┌────┬──────┐
│ id │ b │
╞════╪══════╡
│ 1 │ Ahoj │
│ 2 │ Ahoj │
└────┴──────┘
(2 rows)
在 Postgres 13 上测试