diff --git a/content/en/docs/Developerguide/stored-procedure.md b/content/en/docs/Developerguide/stored-procedure.md index 68a1e7931f93df400c0e08819c5387d8bacc9913..9fe7014013ce6fbf1ba76c6a5ce8378a1cf7d234 100644 --- a/content/en/docs/Developerguide/stored-procedure.md +++ b/content/en/docs/Developerguide/stored-procedure.md @@ -16,6 +16,8 @@ - **[Control Statements](control-statements.md)** +- **[Transaction Management](Transaction Management.md)** + - **[Other Statements](other-statements.md)** - **[Cursors](cursors.md)** @@ -24,4 +26,3 @@ - **[Debugging](debugging.md)** - diff --git a/content/en/docs/Developerguide/transaction management.md b/content/en/docs/Developerguide/transaction management.md new file mode 100644 index 0000000000000000000000000000000000000000..90550f22ec5de21dc54a71f99de340c6d6b56ffa --- /dev/null +++ b/content/en/docs/Developerguide/transaction management.md @@ -0,0 +1,71 @@ +# Transaction Management + +In procedures as well as in anonymous code blocks, it is possible to end transactions using the commands COMMIT and ROLLBACK. A new transaction is started automatically after a transaction is ended using these commands, so there is no separated START TRANACTION command(Note that BEGIN and END have different meanings in PL/SQL). What’s more, we don’t support COMMIT and ROLLBACK command within procedures or anonymous code blocks in an transaction block through an START TRANACTION or BEGIN command. + +Here is a simple example: + +```sql +CREATE TABLE test1 (a int); +CREATE PROCEDURE transaction_test1() +AS +BEGIN + FOR i IN 0..9 LOOP + INSERT INTO test1 (a) VALUES (i); + IF i % 2 = 0 THEN + COMMIT; + ELSE + ROLLBACK; + END IF; + END LOOP; +END; +/ + +CALL transaction_test1(); +``` + +A new transaction starts out with default transaction characteristics such as isolation level. + +Within function, it’s not support transaction control. If you do it, the function will return an error immediately. Also, if the call stack is proc1()->proc2()->proc3(), then the last procedure cannot do transaction control, because of the function in between. + +Special considerations apply to cursor loops. Consider this example: + +```sql +CREATE PROCEDURE transaction_test2() +AS +DECLARE + r RECORD; +BEGIN + FOR r IN SELECT * FROM test2 ORDER BY x LOOP + INSERT INTO test1 (a) VALUES (r.x); + COMMIT; + END LOOP; +END; +/ + +CALL transaction_test2(); +``` + +Normally, cursors are automatically closed at transaction commit. However, a cursor created as part of a loop like this is automatically converted to a holdable cursor by the first COMMIT or ROLLBACK. That means that the cursor is fully evaluated at the first COMMIT or ROLLBACK rather than row by row. The cursor is still removed automatically after the loop, so this is mostly invisible to the user. + +Transaction commands are not allowed in cursor loops driven by commands that are not read-only(for example UPDATE … RETURNING). + +A transaction also can be ended inside a block with exception handlers. For example, + +```sql +CREATE PROCEDURE transaction_test3() +AS +BEGIN + INSERT INTO test1 (a) VALUES (1); + COMMIT; + INSERT INTO test1 (a) VALUES (1/0); + COMMIT; +EXCEPTION + WHEN division_by_zero THEN + RAISE NOTICE 'caught division_by_zero'; +END; +/ + +CALL transaction_test3(); +``` + +After executing the transaction procedure, we will get the exception, but the first insert SQL in the procedure will execute successfully. \ No newline at end of file diff --git "a/content/zh/docs/Developerguide/\344\272\213\345\212\241\347\256\241\347\220\206.md" "b/content/zh/docs/Developerguide/\344\272\213\345\212\241\347\256\241\347\220\206.md" new file mode 100644 index 0000000000000000000000000000000000000000..ce70b1942ed12a61cc8da2f0013eb84fec4455d3 --- /dev/null +++ "b/content/zh/docs/Developerguide/\344\272\213\345\212\241\347\256\241\347\220\206.md" @@ -0,0 +1,71 @@ +# 事务管理 + +在调用存储过程以及匿名块中,支持用命令COMMIT和ROLLBACK结束事务。在一个事务中使用这些命令后,一个新的事务会被自动开启,不需要单独使用START TRANSACTION命令(注意BEGIN和END在PL/SQL中有不同的含义),同时不支持在用户显示开启的事务块中调用带有事务命令的存储过程或者匿名块。 + +下面是一个简单的例子: + +```sql +CREATE TABLE test1 (a int); +CREATE PROCEDURE transaction_test1() +AS +BEGIN + FOR i IN 0..9 LOOP + INSERT INTO test1 (a) VALUES (i); + IF i % 2 = 0 THEN + COMMIT; + ELSE + ROLLBACK; + END IF; + END LOOP; +END; +/ + +CALL transaction_test1(); +``` + +新事务开始时具有默认事务特征,如事务隔离级别。 + +函数调用中不支持对事务的控制,如果在函数中试图使用事务控制,将直接报错。同时对于proc1()->func2()->proc3()这类嵌套使用,最后一个存储过程不能做事务控制,因为中间有函数的调用。 + +对于游标循环有特殊的考虑。如下面例子 + +```sql +CREATE PROCEDURE transaction_test2() +AS +DECLARE + r RECORD; +BEGIN + FOR r IN SELECT * FROM test2 ORDER BY x LOOP + INSERT INTO test1 (a) VALUES (r.x); + COMMIT; + END LOOP; +END; +/ + +CALL transaction_test2(); +``` + +通常,游标会在事务提交时被自动关闭。但是,一个作为循环的组成部分创建的游标会自动被第一个COMMIT或ROLLBACK成一个可保持游标。这意味着该游标在第一个COMMIT或ROLLBACK处会被完全计算出来,而不是逐行被计算。该游标在循环后仍会被自动删除,因此这通常对用户是不可见的。 + +有非只读命令(UPDATE … RETURNING)驱动的游标循环中不允许有事务命令。 + +在一个具有异常处理部分的块中同样支持事务的操作,如下面的例子 + +```sql +CREATE PROCEDURE transaction_test3() +AS +BEGIN + INSERT INTO test1 (a) VALUES (1); + COMMIT; + INSERT INTO test1 (a) VALUES (1/0); + COMMIT; +EXCEPTION + WHEN division_by_zero THEN + RAISE NOTICE 'caught division_by_zero'; +END; +/ + +CALL transaction_test3(); +``` + +上面存储过程执行后将捕获异常,但是第一条插入操作将正常完成。 \ No newline at end of file diff --git "a/content/zh/docs/Developerguide/\345\255\230\345\202\250\350\277\207\347\250\213.md" "b/content/zh/docs/Developerguide/\345\255\230\345\202\250\350\277\207\347\250\213.md" index 68ddcca27ee7cdfe0c3e4f53ddd5f62b94c34666..ef786b46789205b32ce4fa95b2582a071db2e708 100644 --- "a/content/zh/docs/Developerguide/\345\255\230\345\202\250\350\277\207\347\250\213.md" +++ "b/content/zh/docs/Developerguide/\345\255\230\345\202\250\350\277\207\347\250\213.md" @@ -16,11 +16,13 @@ - **[控制语句](控制语句.md)** +- **[事务管理](事务管理.md)** + - **[其他语句](其他语句.md)** - **[游标](游标.md)** -- **[Retry管理](Retry管理.md)** +- **[Retry管理](Retry管理.md)** - **[调试](调试-22.md)**