Transactions 与「;“尝试/抓住”;使用IBM Informix数据库中的回滚

Transactions 与「;“尝试/抓住”;使用IBM Informix数据库中的回滚,transactions,informix,Transactions,Informix,我正在处理数据库。我希望在事务内部执行一些查询,如果出现错误,我希望回滚所有编辑,因此在SQL Server中与此相当的内容: BEGIN TRY BEGIN TRAN -- insert, update, delete statements etc. COMMIT TRAN END TRY BEGIN CATCH IF(@@TRANCOUNT > 0) ROLLBACK TRAN; END CATCH 以下是: 当我搜索“info

我正在处理数据库。我希望在事务内部执行一些查询,如果出现错误,我希望回滚所有编辑,因此在SQL Server中与此相当的内容:

BEGIN TRY
    BEGIN TRAN
        -- insert, update, delete statements etc.
    COMMIT TRAN
END TRY
BEGIN CATCH
    IF(@@TRANCOUNT > 0)
        ROLLBACK TRAN;
END CATCH
以下是:

当我搜索“informix try catch”时,我得到的第一个链接是关于,但是,没有一个页面显示了关于如何捕获异常和回滚的完整语法示例,我在internet上的任何地方都找不到这样的示例。我尝试执行以下查询:

begin work;
    create table test_abc
    (
        test_value int
    );
    on exception
        rollback work;
    end exception
commit work;

我的期望是,第一次这个查询可以工作,但第二次它会失败,因为表已经存在。然而,在我第一次遇到这个错误时:

begin work;
        create table test_abc
        (
                test_value int
        );
        on exception
#^
#  201: A syntax error has occurred.
#
                rollback work;
        end exception
commit work;

所以这个语法是无效的

正确的语法是什么


编辑:关于我正在做什么的更多信息。我有一个新任务,我需要添加一些新表,并在其中的一些表中放入几行。即使可以在所有环境(test、prod等)上一次(或一个接一个)执行所有语句,我还是希望可以将所有语句打包到一个事务中,以避免在出现问题时需要清理。Jonathan Leffler建议创建存储过程,并使用异常上的
处理异常捕获,但我只需要使用一次事务,这并不保证创建存储过程。从技术上讲,我可以使用事务创建存储过程,运行它并删除它,但如果有一种方法可以避免创建存储过程,那么最好知道如何使用SPL(存储过程语言)处理异常。

既然有可能,我假设您正在存储过程中工作

您的示例是正确的,但是错误地放置了异常处理代码:

——问题中的错误代码
开始工作;
创建表test_abc
(
测试值int
);
例外
回滚工作;
结束例外
投入工作;
您需要在可能生成异常的代码之前指定异常处理。更接近正确的代码片段是:

CREATE PROCEDURE make_test_abc()
    BEGIN WORK;
    BEGIN
    ON EXCEPTION
        ROLLBACK WORK;
    END EXCEPTION;
    CREATE TABLE test_abc
    (   
        test_value INT 
    );  
    COMMIT WORK;
    END;
END PROCEDURE;

EXECUTE PROCEDURE make_test_abc();
上述注释适用于工程;多个类似的版本不起作用。SPL有时会变得非常棘手

我的库中还有一个“事务状态”函数,它在异常时使用:

CREATE PROCEDURE tx_state() RETURNING VARCHAR(14);
    DEFINE errcode INTEGER;
    ON EXCEPTION IN (-256, -535) SET errcode
        IF errcode = -256 THEN
            RETURN "TX-Unavailable";
        ELIF errcode = -535 THEN
            RETURN "In-TX";
        END IF;
    END EXCEPTION
    BEGIN WORK;
    ROLLBACK WORK;
    RETURN "No-TX";
END PROCEDURE
现在,创建表练习还有其他机制:

DROP TABLE IF EXISTS test_abc;
CREATE TABLE IF NOT EXISTS test_abc(test_value INT);
创建和删除过程也有类似的选项:

DROP PROCEDURE IF EXISTS make_test_abc;
CREATE PROCEDURE IF NOT EXISTS make_test_abc()
…
END PROCEDURE;
CREATE OR REPLACE PROCEDURE make_test_abc()
…
END PROCEDURE;
这两个variant
CREATE PROCEDURE
语句与Informix以外的不同DBMS兼容。“或替换”选项需要14.10版本(以及最新版本之一;我认为14.10.FC1中没有提供)。EXISTS选项在12.10中也可用(但同样,不一定在旧的12.10版本中)

当然,即使使用IF[NOT]EXISTS子句(或or REPLACE子句),如果您没有相关权限,操作也可能失败

但是,我假设这个问题比如何创建一个没有例外的表更一般。这应该会给你行动的指引。ON EXCEPTION子句在SPL(存储过程语言)中不可用,这意味着它只能在CREATE procedure(或CREATE FUNCTION)语句中使用


执行语句,失败时不提交 如果使用DB Access执行一系列命令,则可以使用以下大纲创建脚本(称为
script.sql
):

BEGIN WORK;

CREATE …
DROP …
CREATE …
GRANT …
…

COMMIT WORK;
然后,您可以在批处理模式下运行它,并在环境中设置环境变量
DBACCNOIGN
(DB Access“no ignore errors”)

$DBACCNOIGN=1 dbaccess yourdb脚本
…可讨论的输出-一些到标准输出,一些到标准错误…
$
语句成功时将有输出,但如果其中一个语句失败,脚本将停止并回滚事务。如果所有语句都成功,将执行提交工作并提交事务

还考虑检查SqLCMD(从中可用),我写的是在shell访问上下文中始终保持一致的行为,其中DB访问没有。它可以追溯到1986年(在出现

dbaccess
之前;在那些日子里,您使用的是
isql
,而-DB访问是在一个晚上从
isql
中分割出来的)。它与微软的johnny come Latesty程序没有任何关系,只是名称不同,并且具有相同的通用性(操作SQL数据库)。与DB Access不同,SQLCMD在出现错误时不会继续,除非您告诉它这样做(
-c
命令行选项,或脚本文件中的
继续;

$sqlcmd-d yourdb-f script.sql
$

与DB Access不同,SQLCMD不会有任何输出,除非您遇到错误,或选择某个内容,或使用
-x
(跟踪)选项或
-v
(详细)选项请求输出,或使用
-B
请求基准测试(计时),或以其他方式请求输出。

谢谢您的回答。你举的例子很有帮助。然而,我并不真正“需要”交易。我编辑了这个问题,并提供了更多细节。我只需要为所有环境中的新任务添加一些数据。它并不保证必须为此创建sp,但如果没有其他方法,它肯定是一个选项。“因为有可能出现异常,我假设您正在存储过程中工作。”。不,本来我不打算使用存储过程(但是在这个答案之后,我会考虑它,谢谢)。只是除了“on exception”语句之外,我找不到其他任何东西。当我搜索“informix try-catch”时,DDG和Google中的第一个链接是“on exception”,并且没有实际try/catch的迹象。我希望找到关于try/catch的文档(就像在SQLServer中一样),但没有找到。据我所知,现在尝试/捕获语法d
BEGIN WORK;

CREATE …
DROP …
CREATE …
GRANT …
…

COMMIT WORK;