如果表变量只有其批次的范围,那么为什么使用GO后我可以从其中选择一个呢?

J. *_*ini 3 t-sql sql-server table-variable

我显然误解了批处理和会话之间的区别。我相信三件事不能同时为真:

  1. 众所周知,表变量仅具有其批次的范围。
  2. 我相信文档报告是正确的,这GO 标志着一批的结束
  3. 以下脚本不会引发错误,即使@t应该超出范围
declare @t table (id int)
insert into @t values (1)
select * from @t
GO
select * from @t
Run Code Online (Sandbox Code Playgroud)

数据库小提琴链接

显然我弄错了一些事情,但是什么?

Aar*_*and 13

GO是 SSMS 已知的批次分隔符。如果您在 SSMS 中尝试使用小提琴中的第一个脚本块,它将失败 - 正如预期的那样

go 在某些情况下,这似乎是 db<>fiddle 忽略的症状。实际上,在这种特定情况下,它似乎忽略了之前的 回车并将其用作前go一行的别名,正如 Martin 建议的那样,如下所示@t

declare @t table (id int);
insert into @t values (1);
select go.* from @t as go;
select * from @t;
Run Code Online (Sandbox Code Playgroud)

这只是因为 db<>fiddle 使用单独的输入区域,而不是GO来分隔批次。事实上,您的脚本因添加单个字符而失败(正确终止插入)

declare @t table (id int)
insert into @t values (1)
select * from @t;
----------------^
go
select * from @t
Run Code Online (Sandbox Code Playgroud)

还有其他一些肯定go会导致错误的例子。例如

create table #t(id int);
go
select * from #t;
Run Code Online (Sandbox Code Playgroud)

数据库引擎、SQL Server 附带的受支持工具以及 db<>fiddle 等在线工具之间存在许多限制和行为差异。如果您尝试确认文档的内容,请针对受支持的 SQL Server 版本使用受支持的工具,并始终使用语句终止符来终止语句,以尽量减少意外情况。在线模拟器可用于演示语法,但不适用于验证记录的行为。

  • 我向开发人员多次宣扬语句终止。“但这没有必要……他们说”然后我就说“我告诉过你了……”但当它发生时我讨厌这种情况。 (2认同)