如何将select结果分配给variables?

如何将选定的字段值存储到查询中的variables中并在更新语句中使用它?

这是我的程序:

我正在编写一个SQL Server 2005 T-SQL存储过程,它执行以下操作:

  1. 从发票表中获取发票编号列表并存储到光标
  2. 从光标 – > tmp_keyvariables中获取发票ID
  3. foreach tmp_key从客户表中查找发票客户主要联系人标识
  4. 用主要联系人ID更新客户端联系人密钥
  5. closures游标

这是我的代码:

DECLARE @tmp_key int DECLARE @get_invckey cursor set @get_invckey = CURSOR FOR select invckey from tarinvoice where confirmtocntctkey is null and tranno like '%115876' OPEN @get_invckey FETCH NEXT FROM @get_invckey into @tmp_key WHILE (@@FETCH_STATUS = 0) BEGIN SELECT c.PrimaryCntctKey as PrimaryContactKey from tarcustomer c, tarinvoice i where i.custkey = c.custkey and i.invckey = @tmp_key UPDATE tarinvoice set confirmtocntctkey = PrimaryContactKey where invckey = @tmp_key FETCH NEXT FROM @get_invckey INTO @tmp_key END CLOSE @get_invckey DEALLOCATE @get_invckey 

如何存储PrimaryContactKey并在以下更新语句的set子句中再次使用它? 我是否创build一个游标variables或只是一个inttypes的另一个局部variables?

 DECLARE @tmp_key int DECLARE @get_invckey cursor SET @get_invckey = CURSOR FOR SELECT invckey FROM tarinvoice WHERE confirmtocntctkey IS NULL AND tranno LIKE '%115876' OPEN @get_invckey FETCH NEXT FROM @get_invckey INTO @tmp_key DECLARE @PrimaryContactKey int --or whatever datatype it is WHILE (@@FETCH_STATUS = 0) BEGIN SELECT @PrimaryContactKey=c.PrimaryCntctKey FROM tarcustomer c, tarinvoice i WHERE i.custkey = c.custkey AND i.invckey = @tmp_key UPDATE tarinvoice SET confirmtocntctkey = @PrimaryContactKey WHERE invckey = @tmp_key FETCH NEXT FROM @get_invckey INTO @tmp_key END CLOSE @get_invckey DEALLOCATE @get_invckey 

编辑:
这个问题比我预料的要多得多。 请注意,我不是主张在我的答案中使用游标,而是显示如何根据问题分配值。

我只是有同样的问题,…

 declare @userId uniqueidentifier set @userId = (select top 1 UserId from aspnet_Users) 

甚至更短:

 declare @userId uniqueidentifier SELECT TOP 1 @userId = UserId FROM aspnet_Users 

尝试这个

 SELECT @PrimaryContactKey = c.PrimaryCntctKey FROM tarcustomer c, tarinvoice i WHERE i.custkey = c.custkey AND i.invckey = @tmp_key UPDATE tarinvoice SET confirmtocntctkey = @PrimaryContactKey WHERE invckey = @tmp_key FETCH NEXT FROM @get_invckey INTO @tmp_key 

你可以在你的循环之外声明这个variables只是一个标准的TSQLvariables。

我也应该注意到,这是你如何做的任何types的select到一个variables,而不只是当处理游标。

为什么你需要一个游标呢? 您的整个代码段可以被replace,这将在大量的行上运行得更快。

 UPDATE tarinvoice set confirmtocntctkey = PrimaryCntctKey FROM tarinvoice INNER JOIN tarcustomer ON tarinvoice.custkey = tarcustomer.custkey WHERE confirmtocntctkey is null and tranno like '%115876' 

为了安全地分配一个variables,你必须使用SET-SELECT语句:

 SET @PrimaryContactKey = (SELECT c.PrimaryCntctKey FROM tarcustomer c, tarinvoice i WHERE i.custkey = c.custkey AND i.invckey = @tmp_key) 

确保你有一个开始和结束括号!

SET-SELECT版本是设置variables最安全的方法的原因是双重的。

1. SELECT返回几个post

如果以下select结果在几个职位会发生什么?

 SELECT @PrimaryContactKey = c.PrimaryCntctKey FROM tarcustomer c, tarinvoice i WHERE i.custkey = c.custkey AND i.invckey = @tmp_key 

@PrimaryContactKey将被分配结果中最后一个post的值。

实际上, @PrimaryContactKey将在结果中为每个post分配一个值,因此它将包含SELECT命令正在处理的最后一个post的值。

哪个post是“最后”由任何聚簇索引确定,或者如果没有使用聚簇索引或者主键被聚簇,则“最后”post将是最近添加的post。 在最坏的情况下,这种行为可能会在每次索引表被改变时被改变。

用SET-SELECT语句你的variables将被设置为null

2. SELECT不返回任何post

当使用第二个版本的代码时,如果你的select没有返回结果,会发生什么?

与你可能认为的相反,variables的值不会为空 – 它将保留它以前的值!

这是因为,如上所述,SQL将为每个post分配一个值给variables – 这意味着如果结果不包含任何post,它将不会对variables做任何事情。 所以,variables在运行语句之前仍然具有它的价值。

使用SET-SELECT语句,该值将为null

另请参见: 分配variables时SET与SELECT?