I clearly misunderstand the difference between a batch and a session. I believe three things that cannot all be true at the same time:
GO
marks the end of a batch.@t
should be out of scopedeclare @t table (id int)
insert into @t values (1)
select * from @t
GO
select * from @t
Clearly I am mistaken about something, but what?
GO
is a batch separator known to SSMS. If you try the first script block from your fiddle in SSMS, it will fail - as expected.
This seems to be a symptom of db<>fiddle ignoring go
in some cases. Actually, in this specific case, it seems to be ignoring the carriage return before go
and applying it as an alias to @t
in the preceding line, as Martin suggested, like this:
declare @t table (id int);
insert into @t values (1);
select go.* from @t as go;
select * from @t;
This is simply because db<>fiddle uses separate input areas, not GO
, to separate batches. In fact your script fails by adding a single character (properly terminating the insert):
declare @t table (id int)
insert into @t values (1)
select * from @t;
----------------^
go
select * from @t
There are other examples where go
will definitely cause errors. For example:
create table #t(id int);
go
select * from #t;
There are a lot of limitations and behavior differences between the database engine, the supported tools that ship for SQL Server, and online tools like db<>fiddle. If you're trying to confirm what the documentation says, please use the supported tooling against supported versions of SQL Server, and always terminate statements with statement terminators to minimize surprises. Online emulators are useful for demonstrating syntax but not for validating documented behavior.