【问题标题】:How do I get SQL SELECT @variable = expression assignments to work like a spreadsheet?如何让 SQL SELECT @variable = 表达式分配像电子表格一样工作?
【发布时间】:2010-10-24 21:35:24
【问题描述】:

免责声明:这是根据常见问题解答声明发布的“问答式问题”,即“完全可以提出和回答您自己的编程问题”。其目的是鼓励 SQL Anywhere 编程社区的成员通过在“sqlanywhere”标签中植入一些真实内容来使用 StackOverflow。欢迎编辑和其他答案,并且它已被标记为“社区 wiki”以促进这一点,并避免声称与声誉系统博弈。

我正在为 SQL Anywhere 9.0.2 编写一个存储过程,下面是一些代码:

...
declare
@v_d datetime, @v_d1 datetime, @v_d2 datetime
....
select @v_d1 = @v_d, @v_d2 = dateadd(dd, 1, @v_d1)
...

事实证明@v_d2 不会按预期设置。 如果我将其修改为:

...
declare
@v_d datetime, @v_d1 datetime, @v_d2 datetime
....
select @v_d1 = @v_d
select @v_d2 = dateadd(dd, 1, @v_d1)
...

什么都没有发生,都一样。 最后,我把它改成了:

...
declare
@v_d datetime, @v_d1 datetime, @v_d2 datetime
....
begin
   select @v_d1 = @v_d
end
begin
   select @v_d2 = dateadd(dd, 1, @v_d1)
end
...

现在它工作正常,但看起来有点愚蠢。 我的问题是:这是一个已知问题吗?或者也许我可以做得更整洁?任何 cmets 将不胜感激。 谢谢!

【问题讨论】:

  • +1 以激怒那些不阅读常见问题解答并否决这些问题的人。

标签: sql stored-procedures variables variable-assignment sqlanywhere


【解决方案1】:

您正在为 Transact-SQL SELECT 列表中的主变量分配寻找电子表格样式的自动重新计算。我很好奇是 Microsoft SQL Server 还是 Sybase ASE 做的,但这是 SQL Anywhere...

从原始代码的行为来看,对主机变量的引用(对 dateadd 的调用中对 @v_d1 的引用)总是引用语句开始时存在的值(null),而不是重新计算的值( @v_d 的值):

CREATE PROCEDURE p AS
declare
@v_d datetime, @v_d1 datetime, @v_d2 datetime
SELECT @v_d = CURRENT TIMESTAMP
select @v_d1 = @v_d, @v_d2 = dateadd(day, 1, @v_d1)
SELECT @v_d, @v_d1, @v_d2
GO

SELECT * FROM p();

@v_d,@v_d1,@v_d2
'2009-05-08 15:13:43.964','2009-05-08 15:13:43.964',(NULL)

您报告您的第二个版本(单独的 SELECT 语句)不起作用,但以下对我有用:

DROP PROCEDURE p;

CREATE PROCEDURE p AS
declare
@v_d datetime, @v_d1 datetime, @v_d2 datetime
SELECT @v_d = CURRENT TIMESTAMP
select @v_d1 = @v_d
select @v_d2 = dateadd(dd, 1, @v_d1)
SELECT @v_d, @v_d1, @v_d2
GO

SELECT * FROM p();

@v_d,@v_d1,@v_d2
'2009-05-08 15:12:54.339','2009-05-08 15:12:54.339','2009-05-09 15:12:54.339'

您正在寻找的电子表格样式的重新计算确实适用于选择编码为“表达式 AS 标识符”的列表项(但这并不是您想要的)...

DROP PROCEDURE p;

CREATE PROCEDURE p AS
declare @v_d datetime
SELECT CURRENT TIMESTAMP INTO @v_d
select @v_d AS v_d, dateadd(day, 1, v_d) AS v_d1, dateadd(day, 1, v_d1) AS v_d2
GO

SELECT * FROM p();

v_d,v_d1,v_d2
'2009-05-08 15:14:27.292','2009-05-09 15:14:27.292','2009-05-10 15:14:27.292'

如果您想要电子表格样式的重新计算并且您想要主机变量分配,我建议您切换到 Watcom-SQL 方言,以便您可以使用 INTO 列表:

DROP PROCEDURE p;

CREATE PROCEDURE p() BEGIN
   DECLARE @v_d  datetime;
   DECLARE @v_d1 datetime;
   DECLARE @v_d2 datetime;
SET @v_d = CURRENT TIMESTAMP;
SELECT @v_d AS v_d, 
       dateadd(day, 1, v_d) AS v_d1, 
       dateadd(day, 1, v_d1) AS v_d2
  INTO @v_d,
       @v_d1,
       @v_d2;
SELECT @v_d,
       @v_d1,
       @v_d2;
END;

SELECT * FROM p();

@v_d,@v_d1,@v_d2
'2009-05-08 15:27:09.808','2009-05-09 15:27:09.808','2009-05-10 15:27:09.808'

SQL Anywhere 版本 9.0.2 和 11.0.1 中的行为相同。

布雷克

【讨论】:

  • WTF?你问了这个问题,然后立即发布了答案?在尝试与系统博弈以获得徽章时,请尽量不那么透明。
  • 如果不是名誉嫖娼,你在做什么?如果您想要一个一般性的 SQL Anywhere 问题,它应该是社区 wiki,而不是非常具体的代码示例。如果您想要答案,为什么在询问后立即发布?您似乎已经有了问题的答案,并发布它以获得一些声誉。
  • 这种做法不仅是允许的,@welblog 和 @Pesto,而且是鼓励的。
  • @Gortok:当问题、答案和样本足够笼统,几乎可以适用于任何情况时,当然可以。我完全同意。这种具体情况远非鼓励的做法。即使是 CW,我仍然觉得它很可疑。
  • FAQ 的第一页说“问和回答你自己的编程问题也很好” 在 Google Techtalk youtube.com/watch?v=NWHfY_lvKIQ Joel Spolsky 说 StackOverflow 的主要目的是成为一个存储库关于编程的规范问题和答案。我这样做的主要原因是通过增加“sqlanywhere”标记的计数来鼓励其他 SQL Anywhere 用户带着他们的问题来到 StackOverflow。徽章无所谓。声誉点是达到目的的一种手段(发布 cmets 的能力等)。
猜你喜欢
  • 2013-04-05
  • 1970-01-01
  • 2018-06-28
  • 1970-01-01
  • 2016-01-14
  • 1970-01-01
  • 2010-10-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多