为什么此代码使用NULL
值而不是错误消息Must declare the scalar variable "@i".
给出一行。为什么微软在T-SQL中使用了此行为?
if 1 = 0
begin
declare @i int = 1;
end;
select @i;
来自msdn:
变量的范围是Transact-SQL语句的范围 可以引用变量。变量的范围从 指点它被声明为直到批处理结束或存储过程 它被声明。
因此,在您的示例中,@i
变量的范围是批处理或过程定义了它们。
所以下一个查询: -
if 1 = 0
begin
declare @i int = 1
end
else
begin
declare @i int = 3
end
select @i
正在检索下一个错误: -
已声明了变量名称'@i'。可变名称必须 在查询批次或存储过程中保持独特。
但是您的查询没有。
update
Microsoft表示他们不会解决此问题: -
使声明仅在块中可见的变量。
DECLARE
s范围是当前批处理,而不是代码块。因此,编译器可以看到您的变量。
问题是 - 如果可见,为什么不分配。作业与常规评估相同,只是在可变声明中以在线书面。分配是受代码流影响的命令。这是您的代码的实际执行计划:
<Batch>
<Statements>
<StmtCond StatementCompId="1" StatementId="1" StatementText="
if 1 = 0
" StatementType="COND" RetrievedFromCache="false">
<Condition />
<Then>
<Statements>
<StmtSimple StatementCompId="2" StatementId="2" StatementText="
begin
 declare @i int = 1;
" StatementType="ASSIGN" RetrievedFromCache="false" />
</Statements>
</Then>
</StmtCond>
</Statements>
<Statements>
<StmtSimple StatementCompId="4" StatementId="3" StatementText="
end;

select @i;
" StatementType="SELECT WITHOUT QUERY" RetrievedFromCache="false" />
</Statements>
</Batch>
及以下是扩展声明和作业的计划:
declare @i int
if 1 = 0
begin
set @i = 1;
end;
select @i;
<Batch>
<Statements>
<StmtCond StatementCompId="1" StatementId="1" StatementText="declare @i int 

if 1 = 0
" StatementType="COND" RetrievedFromCache="false">
<Condition />
<Then>
<Statements>
<StmtSimple StatementCompId="2" StatementId="2" StatementText="
begin
 set @i = 1;
" StatementType="ASSIGN" RetrievedFromCache="false" />
</Statements>
</Then>
</StmtCond>
</Statements>
<Statements>
<StmtSimple StatementCompId="4" StatementId="3" StatementText="
end;

select @i;
" StatementType="SELECT WITHOUT QUERY" RetrievedFromCache="false" />
</Statements>
</Batch>