SQL Server带有READONLY子句的SELECT查询

5

我想以只读模式从表中读取一些数据。

之前我曾经使用过DB2,因此有些困惑并尝试在SELECT语句中使用FOR READONLY子句:P

经过尝试,我意识到以下语句可行:

SELECT * FROM dbo.Users READONLY
使用READONLY子句查询的时间不到不使用它的一半。 所以我决定搜索一些有关此事的文档,但是我找不到SELECT子句与READONLY同时使用的文档。 如果没有文档,我们的DBA要求我们不要使用READONLY子句,因为它可能在新版本中过时。 如果有人能指出一些有用的文档,并告诉我这是否可以安全地用于SQL Server存储过程,我将不胜感激。 我正在使用SQL Server版本11.0.3000.0。
5个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
14

虽然这是一个旧问题,但如果有人认为他们已经发现了一个魔法加速开关,那么它值得得到一个新答案。

这与 SELECT * FROM dbo.Users PLEASE_BUFF_MY_PYLONSSELECT * FROM Users AS U 具有相同的语义。它将别名 READONLY 分配给表 Users,并且对于执行计划或查询执行时间本身没有任何影响。任何声称否则的人最好有一些非常好的证据来支持它(例如,一个不显示READONLY 的执行计划只是一个别名)。READONLY 是一个 T-SQL 关键字,但仅在将表变量传递给存储过程的上下文中。在此查询的上下文中,它只是另一个标识符。

查询在某种情况下变慢,在其他情况下变快有很多原因(缓存的执行计划就是其中一个重要原因);将您的表别名为名称READONLY 不是其中之一。

虽然查询没有"只读"模式,但通过使用快照隔离可以从表中读取而不阻塞写入。这也不是一个魔法加速开关,但在许多 OLTP 工作负载中非常有用。


一个小补充:READONLY 不仅是 T-SQL 关键字,似乎在 ISO SQL:2016 中也出现了(至少)参见 https://github.com/ronsavage/SQL,文件“sql-2016.ebnf”。 - user7427029

4
这是一个示例脚本,用于突出显示您在上下文中使用的READONLY的含义:
DECLARE @t TABLE(id INT);
INSERT INTO @t(id)VALUES(1),(2),(3);

SELECT READONLY.id FROM @t READONLY;

导致:

id
1
2
3
换句话说,您将别名命名为READONLY并赋值给表dbo.users(在示例中是表变量@t)。 我建议不要使用此别名。这可能不会导致错误,但它可以在SQL Server的另一个上下文中使用(在存储过程中声明一个表值参数)。也许出于这个原因,READONLY应该成为保留关键字,因为在一种情况下将此单词用作关键字,而在另一种情况下将其用作表别名可能会令人困惑。

-1
通常情况下,在SELECT语句中不需要包含FOR READ ONLY子句。按照定义,SELECT操作是只读的,因此FOR READ ONLY子句通常是不必要的。然而,在某些情况下,您必须在SELECT语句中包含FOR READ ONLY关键字。 请参阅本文以获取更多信息。

谢谢。这是DB2文档。我特别寻找SQL Server文档。另外,如果没有太大的区别,为什么查询速度会明显更快呢? - Rashmi Pandit
SQL Server中没有记录READONLY表提示,所以我认为你的DBA明智地建议不要使用它。使用未记录的功能是冒险的,因为补丁、服务包或版本升级可能会破坏代码。我无法解释为什么你看到性能差异,因为我在查询计划或锁定方面没有发现任何差异(使用SQL跟踪)。 - Dan Guzman
您粘贴的链接似乎已经失效。以下链接是否可以作为失效链接的有效替代品?:https://www.ibm.com/support/knowledgecenter/zh/SSGU8G_11.50.0/com.ibm.sqls.doc/ids_sqs_1062.htm - Noel Widmer

-1

更新的链接:

bumbumpaw回复中的链接已不再有效。在IBM知识中心发现了关于在查询Informix数据库时使用“FOR READ ONLY”子句的内容。

https://www.ibm.com/support/knowledgecenter/en/SSGU8G_11.50.0/com.ibm.sqls.doc/ids_sqs_1062.htm

正如Jeroen Mostert所指出的那样,尽管“READONLY”是保留关键字,但Microsoft SQL Server并不包含它。 但是,它确实有一个选项可以将数据库级别设置为“READ_ONLY”,这超出了本问题的范围。

https://learn.microsoft.com/en-us/sql/t-sql/statements/alter-database-transact-sql-set-options?view=sql-server-2017


1
请不要仅仅为了更新链接或确认他人的陈述而发布新答案。您可以通过编辑帖子来更新损坏的链接,或者通过评论添加额外信息。 - Noel Widmer

-1

绝对不是。恰恰相反:NOLOCK 意味着不尊重任何锁定。它将返回甚至还没有提交的被锁定的行。 - Panagiotis Kanavos

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