在SQL Server中,是否可以在事务内运行多个DDL语句?

31

我想知道是否可以在一个事务内运行多个DDL语句。我对SQL Server特别感兴趣,尽管其他数据库(至少包括Oracle、PostgreSQL)的答案也可能很有意思。

我一直在执行一些“CREATE TABLE”和“CREATE VIEW”,用于创建表格,并且发现了一些不一致之处,我想知道DDL是否应该在事务内完成...

我可能可以将DDL移出事务,但我想找一些参考资料。我到目前为止找到的东西有:

针对Oracle:

如果有所作为,我是通过JTDS JDBC驱动程序使用Java进行操作的。

敬礼,Touko

4个回答

17

我知道大多数数据库都有限制,但Postgres没有。您可以在事务中运行任何数量的表创建、列更改和索引更改,并且在 COMMIT 成功之前对其他用户不可见。这就是数据库应该的样子!:-)

至于SQL Server,您可以在事务中运行DDL,但SQL Server 不会版本控制元数据,因此在事务提交之前,更改将对其他人可见。但是某些 DDL 语句可以回滚如果您在事务中, 但哪些语句起作用,哪些不起作用,您需要进行一些测试。


2
只是回复一下我自己,跟进了两年后...尽管 SQL Server 不提供针对 DDL 的隔离事务,但它可以回滚成为一个事务的多个 DDL 语句。我的同事刚测试了 SQL Server 2008 R2: "我试着创建一个表,在其上添加一个主键列,在另一张表中插入数据,在另一张表中添加一个列,再在其中插入数据,然后通过一些无效的 SQL 强制出错,所有操作都正确地回滚了!" 只需确保每个 DDL 语句都在自己的批处理中(使用 GO 分隔符)。 - David Roussel
1
应该得出的结论是,“在数据库正在使用时不要在SQL Server中运行DDL”?也就是说,通常情况下可以使用事务来处理DDL,只要没有其他内容正在读取表格(这意味着您的网站在更新数据库时应该关闭,反正它可能本来就应该关闭)。 - jpmc26
我可以确认Ingres允许(至少)在更广泛的CRUD事务中更改列。这可能并不令人惊讶,考虑到Postgres / Ingres之间的关系。 - Sepster
1
根据我的经验,似乎在 SQL Server 事务中应用任何 DDL 都会在表上保持锁定,直到事务被提交或回滚。虽然我没有看到明确指定这种行为的文档。 - jocull

4
如果您正在动态创建表格、视图等(除了表变量或临时表),您可能真的需要重新考虑您的设计。这些不是通常从用户界面发生的事情。即使您必须允许一些自定义,DDL语句也不应该与运行事务插入/更新/删除同时发生。将这些功能分开执行会更好。
这也是需要大量考虑和测试的事情,因为当两个用户尝试同时更改同一张表的结构并运行事务来插入数据时,会发生一些非常可怕的事情。当您允许用户调整数据库结构时,请注意出现的问题。
此外,有些DDL语句必须始终是批处理的第一条语句。在运行它们时也要注意这一点。

你说得很对,但不幸的是,在这个项目中我被迫使用这个遗留的数据库设计...这些批处理似乎是一组SQL Server语句.. 可能我正在使用JDBC在单独的批处理中运行所有语句,除非我明确地想要它.. 至少我是这么认为的.. - Touko
20
我认为DDL事务在另一种情况下非常有用——不是实时更新,而是确保生产数据库的模式更新永远不会处于不一致状态。 - Nathan
7
当数据库完全由应用程序管理,用户从早期版本的应用程序升级到较新版本时,可以使用迁移方案来迁移模式。这些迁移应该永远不会失败,但如果确实发生失败,最好让数据库保持在迁移前的状态。 - Roman Starkov
4
没回答问题,-1。 - Camron B
1
@CamronBute,它确实回答了问题,我说他提出的解决方案很糟糕,他应该重新考虑。鼓励人们采用不良解决方案是不负责任的,因为那不是他们想要的。 - HLGEM

1

在MS SQL中,当运行DDL和DML语句时,是否会触发隐式事务。如果您将其切换关闭,是否有所帮助,使用SET IMPLICIT_TRANSACTIONS

编辑:另一种可能性-您无法将CREATE VIEW与同一批处理中的其他语句组合使用。 CREATE TABLE可以。您可以使用GO分隔批次。

编辑2:只要使用GO分隔不同批次,就可以在事务中使用多个DDL。


我正在使用JDBC Connection#setAutoCommit(false),但DML语句没有隐式事务。结果似乎更像是创建视图的表并不总是存在或者其他原因。 - Touko
对于编辑(EDIT):这可能是正确的,但我想要一些关于SQL Server文档或其他相关内容的引用,无论它是否允许。 - Touko
我用过这本书,看看能否在网上找到? Microsoft® SQL Server® 2008 T-SQL基础 印刷版ISBN-10:0-7356-2601-4 印刷版ISBN-13:978-0-7356-2601-0 - Stuart
好的,谢谢。现在对我来说仍然存在一个问题,这与JDBC有何关联(我可以将此GO写为字符串,但由于我的软件应该在不同的DBMS上运行,那不是第一选择)这个GO仍然不同于事务和BEGIN/COMMIT等 - 与“批处理”或其他什么有关吗? - Touko

1

就一般情况和我所知,假设DDL语句是事务性的并不安全。

也就是说,在事务中如何交互模式变化有很大的灵活性(如果它确实存在)。这可能是由供应商甚至特定的安装(即,取决于dba)决定的。因此,至少不要使用一个DBMS来假设其他人会处理DDL语句。

编辑:MySql是一个不支持DDL事务的DBMS示例。此外,如果您有数据库复制/镜像,您必须非常小心,以确保复制服务(Sybase的复制是标准,信不信由你)实际上会复制DDL语句。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接