juu*_*uur 275 sql t-sql sql-server sql-server-2005 sql-server-2008
在T-SQL中分配变量时,SET
和SELECT
语句之间有什么区别?
OMG*_*ies 401
- SET是变量赋值的ANSI标准,SELECT不是.
- SET一次只能分配一个变量,SELECT可以一次分配多个赋值.
- 如果从查询中分配,SET只能分配标量值.如果查询返回多个值/行,则SET将引发错误.SELECT会将其中一个值分配给变量,并隐藏返回多个值的事实(因此您可能永远不会知道其他地方出现问题的原因 - 请对其进行故障排除)
- 从查询中分配时,如果没有返回值,则SET将分配NULL,其中SELECT将根本不进行赋值(因此变量不会从其先前的值更改)
- 就速度差异而言 - SET和SELECT之间没有直接的区别.然而,SELECT能够在一次拍摄中进行多次分配确实比SET具有轻微的速度优势.
Joe*_*lli 150
我相信SET
是ANSI标准,而SELECT
不是.另请注意,未找到值时,以下示例中的SET
vs的行为不同SELECT
.
declare @var varchar(20)
set @var = 'Joe'
set @var = (select name from master.sys.tables where name = 'qwerty')
select @var /* @var is now NULL */
set @var = 'Joe'
select @var = name from master.sys.tables where name = 'qwerty'
select @var /* @var is still equal to 'Joe' */
Run Code Online (Sandbox Code Playgroud)
Gor*_*ulu 24
在编写查询时,应记住这种差异:
DECLARE @A INT = 2
SELECT @A = TBL.A
FROM ( SELECT 1 A ) TBL
WHERE 1 = 2
SELECT @A
/* @A is 2*/
---------------------------------------------------------------
DECLARE @A INT = 2
SET @A = (
SELECT TBL.A
FROM ( SELECT 1 A) TBL
WHERE 1 = 2
)
SELECT @A
/* @A is null*/
Run Code Online (Sandbox Code Playgroud)
除了ANSI和速度等之外,还有一个非常重要的差异对我始终很重要;超过ANSI和速度。由于这一重要的疏忽,我修复的错误数量很多。我一直在代码审查期间寻找这个。
-- Arrange
create table Employee (EmployeeId int);
insert into dbo.Employee values (1);
insert into dbo.Employee values (2);
insert into dbo.Employee values (3);
-- Act
declare @employeeId int;
select @employeeId = e.EmployeeId from dbo.Employee e;
-- Assert
-- This will print 3, the last EmployeeId from the query (an arbitrary value)
-- Almost always, this is not what the developer was intending.
print @employeeId;
Run Code Online (Sandbox Code Playgroud)
几乎总是,这不是开发人员想要的。在上面的查询中,查询很简单,但是我看到的查询非常复杂,弄清楚它是否将返回单个值并非易事。查询通常比这更复杂,并且偶然地它一直在返回单个值。在开发人员测试期间,一切都很好。但这就像一枚滴答作响的炸弹,当查询返回多个结果时将引起问题。为什么?因为它将仅将最后一个值分配给变量。
现在让我们尝试使用SET
:
-- Act
set @employeeId = (select e.EmployeeId from dbo.Employee e);
Run Code Online (Sandbox Code Playgroud)
您将收到一个错误:
子查询返回的值超过1。当子查询遵循=,!=,<,<=,>,> =或将子查询用作表达式时,不允许这样做。
这是非常令人惊奇且非常重要的,因为您为什么要为分配一些琐碎的“结果中的最后一项” @employeeId
。有了它,select
您将永远不会收到任何错误,并且将花费数分钟,数小时进行调试。
也许,您正在寻找一个ID,这SET
将迫使您修复查询。因此,您可以执行以下操作:
-- Act
-- Notice the where clause
set @employeeId = (select e.EmployeeId from dbo.Employee e where e.EmployeeId = 1);
print @employeeId;
Run Code Online (Sandbox Code Playgroud)
清理
drop table Employee;
Run Code Online (Sandbox Code Playgroud)
最后,使用:
SET
:当您要为变量分配单个值并且您的变量用于单个值时。SELECT
:要为变量分配多个值时。该变量可以是表,临时表或表变量等。