`
suiliangxiang
  • 浏览: 69139 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

SQL赋值SET和SELECT有什么区别?

阅读更多

事实上SQL Server数据库的开发者在SQL Server 7.0(1999)版本之前都是用SELECT赋值的,
但在SQL Server 7.0 之后,推出了SET方法赋值,而且Microsoft在其联机帮助文档中明确提出
推荐使用SET方法赋值。
 这让开发者很迷惑,Microsoft也没有明确说明为什么SET方法是被推荐的。
本文会讲明SET和SELECT的区别,而且让你明白什么时候用SET,什么时候用SELECT。

以下代码为使用SET和SELECT赋值。

 DECLARE @Variable1 AS int, @Variable2 AS int

/* 使用 SELECT */
SELECT @Variable1 = 1

/* 使用 SET */
SET @Variable2 = 2

下面就可以说说区别了:
1.假如你是标准SQL的开发者,那么请使用SET吧,因为SET是ANSI标准的SQL语句,SELECT不是。
2.你可以使用SELECT一次给两个以前变量赋值,但是SET不能。

DECLARE @Variable1 AS int, @Variable2 AS int

/* 一次赋两个变量 */
SELECT @Variable1 = 1, @Variable2 = 2

/* 一次一个变量 */
SET @Variable1 = 1
SET @Variable2 = 2

到目前来说,这没有问题,但是如果你曾经写过处理错误的T-SQL语句。你可能会意识到系统变量
@@ERROR and @@ROWCOUNT必须要在一句SQL语句中捕获。并且是在DML语句(INSERT, UPDATE, DELETE等)
之后立即捕获。如果不是这样,这样系统变量会马上重新设置为0。如果这时你还是使用校准SET来赋值,
那你就麻烦了。
如下例子说明这个问题:

DECLARE @Error int, @RowCount int
SELECT price/0 FROM dbo.titles
SET @RowCount = @@ROWCOUNT
SET @Error = @@ERROR
SELECT @Error AS Error
GO

以上代码如果在pubs数据库中运行,@@ERROR值会显示为0,但实际是显示 division by zero,错误号为8134.
在这样的情况下,我们可以忘掉SET语句,使用SELECT吧。

DECLARE @Error int, @RowCount int
SELECT price/0 FROM dbo.titles
SELECT @RowCount = @@ROWCOUNT, @Error = @@ERROR
SELECT @Error AS Error

但是如果你坚持使用标准ANSI SQL赋值方法,也是有办法的,但是可读性不好,不推荐这样。

DECLARE @ErrorAndRowcount AS varchar(25), @Error int, @RowCount int
SELECT price/0 FROM dbo.titles

/* Capturing @@ERROR and @@ROWCOUNT into a dot separated string */
SET @ErrorAndRowcount = CAST(@@ERROR AS varchar(12)) + '.' + CAST(@@ROWCOUNT AS varchar(12))

/* One way to separate the string into error and rowcount variables */
SET @Error = CAST(PARSENAME(@ErrorAndRowcount, 2) AS int)
SET @RowCount = CAST(PARSENAME(@ErrorAndRowcount, 1) AS int)
SELECT @Error AS Error, @RowCount AS Row_Count

/* Another way of splitting the string into error and rowcount variables */
SET @Error = CAST(LEFT(@ErrorAndRowcount, CHARINDEX('.', @ErrorAndRowcount)-1) AS int)
SET @RowCount = CAST(RIGHT(@ErrorAndRowcount, CHARINDEX('.', REVERSE(@ErrorAndRowcount))-1) AS int)
SELECT @Error AS Error, @RowCount AS Row_Count
GO

3.SET和SELECT还有一个区别是,当使用查询出来的值赋值给变量时,SET和SELECT都可以实现,但当查询出的值为多
个是,SET会提示错误,但SELECT不会,只会接受最后一个值。这点很重要,也是很多程序Bug容易被忽略的地方。
如下是例子:

/* 创建两条记录的测试表 */
SET NOCOUNT ON
CREATE TABLE #Test (i int, j varchar(10))
INSERT INTO #Test (i, j) VALUES (1, 'First Row')
INSERT INTO #Test (i, j) VALUES (1, 'Second Row')
GO

/* 以下查询出来两条记录,不会报错。
假如你不知道 WHERE i = 1 有两条记录,这样很容易出错*/
DECLARE @j varchar(10)
SELECT @j = j FROM #Test WHERE i = 1
SELECT @j
GO

但你用SET重写上面的SQL语句。

DECLARE @j varchar(10)
SET @j = (SELECT j FROM #Test WHERE i = 1)
SELECT @j
将会报错:
Server: Msg 512, Level 16, State 1, Line -1074284106
Subquery returned more than 1 value. This is not permitted when the subquery
 follows =, !=, <, <= , >, >= or when the subquery is used as an expression.

所以我们在查询赋值时推荐使用SET,如果你还想用SELECT,那么请这样使用:
DECLARE @j varchar(10)
SELECT @j = (SELECT j FROM #Test WHERE i = 1)
SELECT @j

但是如果查询不返回任何记录时,请小心。
/* 以下记录返回NULL */
DECLARE @Title varchar(80)
SET @Title = 'Not Found'

SET @Title =
(
SELECT title
FROM dbo.titles
WHERE title_id = 'InvalitTitleID'
)

SELECT @Title
GO

/* 返回'Not Found' */
DECLARE @Title varchar(80)
SET @Title = 'Not Found'

SELECT @Title = title
FROM dbo.titles
WHERE title_id = 'InvalitTitleID'

SELECT @Title
GO

最后一点,SET和SELECT在性能上有没有区别呢,这也是很多开发者不太清楚的地方。
经过测试我们发现,SET和SELECT在赋值方面,性能没有很大的区别。
但是SELECT语句可以实现一句给多个变量赋值,所以性能略高于SET。
以下为测试代码:

 DECLARE @Test1 int,  @Test2 int, @Test3 int, @TestVar1 int, @TestVar2 int
DECLARE @Loop int, @Start datetime, @CTR int, @TimesToLoop1 int, @TimesToLoop2 int

SET @Test1 = 0
SET @Test2 = 0
SET @Test3 = 0
SET @Loop = 0
SET @TestVar2 = 0
SET @TimesToLoop1 = 10
SET @TimesToLoop2 = 50000
WHILE @Loop < @TimesToLoop1
BEGIN
 SET @Start = CURRENT_TIMESTAMP
 SET @CTR = 0

 /* 测试SET */
 WHILE @CTR < @TimesToLoop2
 BEGIN
  SET @TestVar1 = 1
  SET @TestVar2 = @TestVar2 - @TestVar1
  SET @CTR = @CTR + 1
 END

 SET @Loop = @Loop + 1
 SET @Test1 = @Test1 + DATEDIFF(ms, @Start, CURRENT_TIMESTAMP)
END

SET @Loop = 0
SET @TestVar2 = 0
WHILE @Loop < @TimesToLoop1
BEGIN
 SELECT @Start = CURRENT_TIMESTAMP
 SELECT @CTR = 0

 /* 测试SELECT */
 WHILE @CTR < @TimesToLoop2
 BEGIN
  SELECT @TestVar1 = 1
  SELECT @TestVar2 = @TestVar2 - @TestVar1
  SELECT @CTR = @CTR + 1
 END

 SELECT @Loop = @Loop + 1
 SELECT @Test2 = @Test2 + DATEDIFF(ms, @Start, CURRENT_TIMESTAMP)
END

SET @Loop = 0
SET @TestVar2 = 0
WHILE @Loop < @TimesToLoop1
BEGIN
 SELECT @Start = CURRENT_TIMESTAMP, @CTR = 0

 /* 测试SELECT给多个变量赋值 */
 WHILE @CTR < @TimesToLoop2
 BEGIN
  SELECT @TestVar1 = 1, @TestVar2 = @TestVar2 - @TestVar1, @CTR = @CTR + 1
 END

 SELECT @Loop = @Loop + 1, @Test3 = @Test3 + DATEDIFF(ms, @Start, CURRENT_TIMESTAMP)
END

SELECT  (@Test1/CAST(@TimesToLoop1 AS decimal(7,2)))/1000.00 AS [SET],
 (@Test2/CAST(@TimesToLoop1 AS decimal(7,2)))/1000.00 AS [SELECT],
 (@Test3/CAST(@TimesToLoop1 AS decimal(7,2)))/1000.00 AS [SELECT with Multiple Assignments]

 

sql十万个为什么 http://www.sqlwhy.com

分享到:
评论

相关推荐

    SQL中SET和SELECT赋值的区别

    SQL 中 SET 和 SELECT 赋值的区别 SQL 中的赋值操作是数据库编程中非常重要的一部分,SET 和 SELECT 是两种常用的赋值方式,但是它们之间存在着一些关键的区别。本文将详细介绍 SET 和 SELECT 赋值的区别,并讨论...

    基于SQL中SET与SELECT赋值的区别详解

    最近的项目写的SQL比较多,经常会用到对变量赋值,而我使用SET和SELECT都会达到效果。那就有些迷惑,这两者有什么区别呢?什么时候哪该哪个呢?经过网上的查询,及个人练习,总结两者有以下几点主要区别:假定有设定...

    sqlserver存储过程中SELECT 与 SET 对变量赋值的区别

    总结来说,`SET`和`SELECT`在赋值上有以下几点不同: 1. `SET`一次只能赋值一个变量,且更严格,不允许返回多个值的表达式。 2. `SELECT`可以同时赋值多个变量,且在表达式返回多个值时取最后一个,无值时设为`NULL`...

    SQL变量声明和赋值知识归纳

    本文将深入探讨SQL中的变量声明和赋值方法,旨在为初学者提供一个全面的理解框架,同时为有经验的开发者提供一个快速回顾的平台。 ### SQL变量声明 在SQL中,变量用于存储数据,它们可以是在查询过程中动态生成或...

    SQL Server 之 SET IDENTITY_INSERT

    在SQL Server中,`SET IDENTITY_INSERT`是一个重要的命令,它主要用于处理标识列(即自动编号列,通常由`IDENTITY`关键字定义)的显式赋值问题。默认情况下,当向一个包含`IDENTITY`属性的表中插入数据时,标识列的...

    SQL SERVER中SELECT和SET赋值相同点与不同点(推荐)

    综上所述,了解`SELECT`和`SET`的区别有助于在编写SQL Server脚本时做出合适的选择。在实际应用中,应根据具体情况、性能需求和标准规范来决定使用哪种赋值方式。记得在开发过程中,始终确保代码的可读性和维护性,...

    动态SQL 并且把返回的值赋给变量

    SET @sqls = N'SELECT COUNT(*) FROM tableName'; EXEC sp_executesql @sqls, N'@a INT OUTPUT', @num OUTPUT; SELECT @num; ``` 在这个示例中,我们首先声明了一个整型变量`@num`,然后定义了一个SQL语句`@sqls`...

    sybase与microsoft—sql的语法区别

    - Sybase中,为变量赋值可以使用`select @variable`,而Microsoft SQL Server则更倾向于使用`set @variable`或`select @variable = expression`。 2. **动态SQL执行**: - 在执行动态SQL时,Sybase使用`execute ...

    mysql存储过程之创建(CREATE PROCEDURE)和调用(CALL)及变量创建(DECLARE)和赋值(SET)操作方法

    在过程中,可以使用`DECLARE`声明变量,并通过`SET`或`SELECT INTO`进行赋值。这些功能增强了数据库的灵活性和可维护性,使得复杂的数据处理任务变得更加简洁和易管理。在实际开发中,熟练掌握这些操作能显著提高...

    oracle与SQL server的语法差异总结

    - SQL Server中,变量声明需要 `DECLARE @code VARCHAR(5)`,赋值使用 `SET @result = 'abcd'` 或 `SELECT @code = code, @name = name FROM sysc01 WHERE id = 1000`。 6. **语句结束符**: Oracle的SQL语句以...

    Set IDENTITY _INSERTY用法

    在数据库管理与开发过程中,`SET IDENTITY_INSERT` 是一个非常实用的功能,主要用于允许或禁止手动插入带有 `IDENTITY` 属性的字段值。这一特性对于需要进行数据迁移或者特殊场景下的数据操作非常重要。 #### 1. ...

    sql语句的基本介绍和用法

    在SQL中,有一些最常用的操作语句,如`SELECT`、`INSERT`、`UPDATE`、`DELETE`等。这些语句是学习SQL的基础。 #### 三、`SELECT`语句详解 `SELECT`语句是最常用的SQL语句之一,用于从数据库中检索数据。 ##### 1. ...

    sqlserver 学习资料

    使用SET命令或SELECT命令可以赋值变量。使用SELECT命令可以显示变量数据。 五、批处理的例子 DECLARE @Test INT, @TestTwo NVARCHAR(25) SELECT @Test, @TestTwo SET @Test = 1 SET @TestTwo = 'a value' SELECT @...

    sql语法的各种妙用

    这里使用了`DECLARE`声明变量`@sql`,并使用`SET`为其赋值。最后通过`EXEC`命令来执行存储在`@sql`中的SQL语句。 **注意点:** - 使用动态SQL时,需要确保SQL字符串正确无误。 - 动态SQL可能存在安全风险,比如SQL...

    sql2000与oracle的语法区别

    - SQL Server 2000 中,可以使用 `SET @var_name=value` 或 `SELECT @var_name=value` 进行赋值。 - Oracle 使用 `var_name := value` 进行赋值。 4. 游标处理: - 游标的声明、打开、关闭以及取值,两者有明显...

    SQL Server存储过程基本语法

    在 SQL Server 中,我们可以使用 `DECLARE` 语句来定义变量,并通过 `SET` 或 `SELECT` 来给变量赋值。 ##### 1. 简单赋值 ```sql DECLARE @a int; SET @a = 5; PRINT @a; -- 使用 SET 语句进行赋值 ``` 这里声明了...

Global site tag (gtag.js) - Google Analytics