【问题标题】:Automatic rollback of implicit transaction(s) for multiple statements?自动回滚多个语句的隐式事务?
【发布时间】:2019-04-17 08:22:32
【问题描述】:

当多个语句一起提交时 -- 用分号分隔 (;) 但在同一个字符串中 -- 并且未包装在显式事务中,仅创建一个隐式事务或为每个语句创建一个隐式事务单独声明?此外,如果后面的语句之一失败并执行自动回滚,是否所有语句都回滚?

另一个answer 几乎满足了我的问题,但官方文档中的措辞让我感到困惑。事实上,这可能看起来像重复,但我特别想知道多个语句的 隐式 事务。另一个答案没有明确解决这种特殊情况。

作为示例(借用另一个问题),以下内容作为单个字符串提交:

INSERT INTO a (x, y) VALUES (0, 0);
INSERT INTO b (x, y) VALUES (1, 2); -- line 3 error here, b doesn't have column x

documentation

最后查询完成时提交自动启动的事务。 (强调)

last 活动语句完成时,会自动提交隐式事务(自动启动的事务,而不是由 BEGIN 启动的事务)。一个语句在其准备好的语句被重置或最终确定时结束。 (强调)

关键字last对我来说暗示了多个陈述的可能性。当然,如果为每个单独的语句启动一个隐式事务,那么每个语句将是要执行的“最后一个”语句,但在单个语句的上下文中,它应该只是说 the 语句强调上下文是一个单一的语句。

或者说准备好的语句和未准备好的 SQL 字符串有区别吗? (但据我了解,即使调用应用程序没有保留准备好的语句以供重用,所有语句都已准备好,所以我不确定这是否重要。)

在所有语句都成功的情况下,单次commit或者多次commit的结果本质上是一样的,但是文档中只提到了单次失败的语句会自动回滚,而没有提到其他一起提交的语句.

【问题讨论】:

    标签: sqlite


    【解决方案1】:

    sqlite3_prepare 接口编译查询字符串中的first SQL 语句。这些函数的pzTail 参数返回一个指向查询字符串未使用部分开头的指针。

    例如,如果您在示例中使用多语句 SQL 字符串调用 sqlite3_prepare,则第一条语句是唯一对生成的准备语句有效的语句。 pzTail 指针(如果提供)指向第二条语句的开头。在您使用pzTail 指针再次调用sqlite3_prepare 之前,第二个语句不会被编译为准备好的语句。

    所以,不,多个语句不会回滚。 SQLite 引擎创建的每个隐式事务都包含一个预准备语句。

    【讨论】:

    • 谢谢。我没有直接使用 sqlite C/C++ API 进行编码,而是使用 .Net 绑定和其他工具。我现在意识到这些工具不是作为批处理执行多个语句,而是处理单个语句处理。它具有欺骗性,好像 sqlite 会自动处理多个语句。当各种接口和工具都以不同的方式处理事情时,试图正确解释文档是一项挑战。
    • 作为参考,这里有一个link to sqlite_prepare 文档也描述了这种行为。
    • 是的,sqlite3 标记应该用于 C 库,但它通常用于使用该库的包装器的问题。有时如果没有额外的编程语言标签就很难分辨。
    • 虽然我个人的上下文是使用其他工具,但我要求得到与您在底层 API 上下文中发布的完全相同的答案。我之前看过sqlite3_prepare 函数,但是错过了关于它只处理一个语句的关键部分,我认为也许我忽略了多个语句的事务处理的一些细节。所以在这种情况下,我认为它被适当地标记了,但如果我将来对其他包装器/绑定有疑问,我肯定会使用特定的标签。
    • 嗯,那很好。通常可以从问题的上下文中判断它是关于包装器还是实际的 C 库,所以我不会太担心它太多。是的,我同意这个问题被适当地标记了,因为它似乎读得很清楚是关于 C API 本身的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-07-22
    • 1970-01-01
    • 2013-05-13
    • 2016-03-05
    • 1970-01-01
    • 1970-01-01
    • 2016-06-23
    相关资源
    最近更新 更多