2011-05-24 32 views
43

是否可以在View中声明一个变量?例如:SQL视图 - 没有变量?

Declare @SomeVar varchar(8) = 'something' 

给我的语法错误:

Incorrect syntax near the keyword 'Declare'.

回答

43

你是对的。 VIEW中不允许局部变量。

可以设置在一个表值函数的局部变量,它返回一个结果集(像的图一样。)

http://msdn.microsoft.com/en-us/library/ms191165.aspx

例如

CREATE FUNCTION dbo.udf_foo() 
RETURNS @ret TABLE (col INT) 
AS 
BEGIN 
    DECLARE @myvar INT; 
    SELECT @myvar = 1; 
    INSERT INTO @ret SELECT @myvar; 
    RETURN; 
END; 
GO 
SELECT * FROM dbo.udf_foo(); 
GO 
+4

他们怎么能使这件事变得可怕?有时候我认为他们只雇用微软认证专家。 – 2015-08-26 12:48:40

+1

我想有一个课程可以跳出用户的概念,并用一袋钱的概念代替它,这个袋子可以帮助您获得认证 – user1566694 2016-02-08 18:48:05

3

是的,这是正确的,你不能有意见 变量(还有其他的限制也是如此)。

视图可以用于可以用select语句替换结果的情况。

+0

表函数可以在SELECT语句来代替,它有局部变量。 – JeffO 2017-03-29 12:28:45

+0

@JeffO - 不知道你指的是什么。 – Hogan 2017-03-29 15:52:45

+0

你是说因为select语句不能有局部变量,视图也不能? – JeffO 2017-03-29 22:50:11

13

编辑:我试图用我以前的答案,是不正确的热膨胀系数,由@bummi指出。这个选项,而不是工作:

下面是一个使用CROSS APPLY一个选项,以一种工作解决此问题:

SELECT st.Value, Constants.CONSTANT_ONE, Constants.CONSTANT_TWO 
FROM SomeTable st 
CROSS APPLY (
    SELECT 'Value1' AS CONSTANT_ONE, 
      'Value2' AS CONSTANT_TWO 
) Constants 
+0

感谢您的更正 - 更新为使用CROSS APPLY代替。 – 2014-11-19 19:57:06

+0

这是有效的,但不要交叉应用的列重新初始化为每一行?特别是对于计算值来说,这意味着很大的性能损失。局部变量和CTE在视图中不可用,这真让人伤心,任何人都知道为什么? – 2015-11-30 15:05:36

1

我要做的就是创建一个执行同样的选择作为表变量和视图将该视图链接到第二个视图。所以一个视图可以从另一个视图中选择。这实现了相同的结果

+1

Ben,除非你正在处理非常小的表格,否则这可能会导致性能问题。 – logixologist 2016-07-11 20:42:36

0

使用函数作为spencer7593提到的动态数据是一种正确的方法。对于静态数据,与SQL数据设计(与sprocs中写入大量过程代码的反模式)相一致的更高性能的方法是使用静态值创建单独的表并加入到它中。从性能角度来看,这是非常有益的,因为SQL引擎可以围绕JOIN构建有效的执行计划,并且如果需要,您还可以添加索引。

使用函数(或任何内嵌计算值)的缺点是每隔潜在的行发生标注,这是昂贵的。为什么?由于SQL必须首先使用计算值创建完整数据集,然后将WHERE子句应用于该数据集。

九次你不应该需要在你的查询动态计算的单元格值。它更好地弄清楚你需要什么,然后设计一个支持它的数据模型,并用半动态数据(例如通过批处理作业)填充该数据模型,并使用SQL引擎来完成繁重的工作标准SQL。

15

您可以使用WITH来定义您的表达式。然后做一个简单的Sub-SELECT来访问这些定义。

CREATE VIEW MyView 
AS 
    WITH MyVars (SomeVar, Var2) 
    AS (
    SELECT 
     'something' AS 'SomeVar', 
     123 AS 'Var2' 
) 

    SELECT * 
    FROM MyTable 
    WHERE x = (SELECT SomeVar FROM MyVars) 
0

@datenstation有正确的概念。下面是一个使用CTE缓存变量名的工作例如:

CREATE VIEW vwImportant_Users AS 
WITH params AS (
    SELECT 
    varType='%Admin%', 
    varMinStatus=1) 
SELECT status, name 
    FROM sys.sysusers, params 
    WHERE status > varMinStatus OR name LIKE varType 

SELECT * FROM vwImportant_Users 

还通过JOIN

WITH params AS (SELECT varType='%Admin%', varMinStatus=1) 
SELECT status, name 
    FROM sys.sysusers INNER JOIN params ON 1=1 
    WHERE status > varMinStatus OR name LIKE varType 

还通过CROSS APPLY

WITH params AS (SELECT varType='%Admin%', varMinStatus=1) 
SELECT status, name 
    FROM sys.sysusers CROSS APPLY params 
    WHERE status > varMinStatus OR name LIKE varType