【问题标题】:Create View - Declare a variable创建视图 - 声明一个变量
【发布时间】:2017-04-10 02:34:50
【问题描述】:

我正在创建一个使用 STUFF 函数的视图。我想将STUFF 的结果放在一个变量中以供我查看。我遇到的问题是声明我的变量。它给了我消息 “'DECLARE' 附近的语法不正确。期待 '(' 或 SELECT。” 我已经有 '(' 在那里。我尝试在它前面放一个 BEGIN。我已尝试将其放在 SELECT 单词之后。但似乎没有任何效果,我在搜索中找不到解决方案。我使用的是 SQL Server 2012

CREATE VIEW [AQB_OB].[GISREQUESTEDBURNS] 
AS

(DECLARE @CONDITIONS AS varchar(20)
SET @CONDITIONS = (SELECT DISTINCT BD.[RequestedBurnsID]
,[ConditionsReasonsID] = STUFF((SELECT ', ' + CONVERT(VARCHAR (20),[ConditionsReasonsID]) FROM [AQB_OB].[BurnDecisions] WHERE [RequestedBurnsID]= BD.[RequestedBurnsID] ORDER BY [RequestedBurnsID] ASC
FOR XML PATH ('')) , 1 , 1, '') FROM
[AQB_OB].[BurnDecisions] BD)

SELECT RB.[RequestedBurnsID] AS REQUESTEDBURNID
  ,BUY.[BurnYear] AS BURNYEAR
  ,CY.[CurrentYear] AS CURRENTYEAR
  ,RB.[BurnSitesID] AS BURNSITESID
  ,[BurnerID] AS BURNERID
  ,[Contact] AS CONTACT
  ,[BurnDecision] AS BURNDECISION
  ,RB.[Comment] AS COMMENT
  ,@CONDITIONS AS CONDITIONS
FROM [AQB_MON].[AQB_OB].[RequestedBurns] RB
LEFT join AQB_MON.[AQB_OB].[PileDryness] PD on RB.[PileDrynessID] = PD.[PileDrynessID]
inner join AQB_MON.[AQB_OB].[BurnYear] BUY on BUY.BurnYearID = BP.BurnYearID
inner join AQB_MON.[AQB_OB].[CurrentYear] CY on CY.CurrentYearID = BUY.CurrentYearID

GO

【问题讨论】:

  • 您不能在视图中声明变量。用户存储过程或函数。
  • 这能回答你的问题吗? SQL Views - no variables?

标签: sql-server tsql sql-view declare


【解决方案1】:

您不能在视图中声明变量。你能把它做成一个函数或存储过程吗?

编辑 - 您也可以将某些内容放入 CTE (Common Table Expression) 并将其保留为视图。

例如

WITH conditions as 
(
 ... do the STUFF here
)
SELECT blah
FROM blah
INNER JOIN conditions
(or CROSS JOIN conditions if its just one row, I can't quite decipher what your data is like)

【讨论】:

  • 它让我执行with conditions as ( .. )left join 但是在我看来如何为conditions 创建一个列,因为它不喜欢conditions
  • "conditions" 将被视为一个表格,因此它将是 conditions.ConditionsReasonsID。
  • @Ahmed 的回答可能也不错 - 子查询而不是 cte
  • 我能够使用ConditionReasonID。感谢您与我合作。
  • 使用 CTE 的缺点是结果视图无法被索引
【解决方案2】:

这是一个示例查询,它使用 CTE (Common Table Expression) 来很好地模拟内部变量构造,正如 James Casey 所描述的那样。您可以在您的 SQL Server 版本中测试运行它。

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

产出输出:

status  name
12      dbo
0       db_accessadmin
0       db_securityadmin
0       db_ddladmin

也可以通过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

【讨论】:

    【解决方案3】:

    尝试将条件子查询直接放在视图选择语句中。您可以将 XML 转换为 VARCHAR(20)。

    CREATE VIEW [AQB_OB].[GISREQUESTEDBURNS] 
    AS    
    SELECT RB.[RequestedBurnsID] AS REQUESTEDBURNID
      ,BUY.[BurnYear] AS BURNYEAR
      ,CY.[CurrentYear] AS CURRENTYEAR
      ,RB.[BurnSitesID] AS BURNSITESID
      ,[BurnerID] AS BURNERID
      ,[Contact] AS CONTACT
      ,[BurnDecision] AS BURNDECISION
      ,RB.[Comment] AS COMMENT,
    
     (
         SELECT DISTINCT BD.[RequestedBurnsID],
                 [ConditionsReasonsID] = STUFF((SELECT ', ' + CONVERT(VARCHAR (20),     [ConditionsReasonsID]) FROM [AQB_OB].[BurnDecisions] 
         WHERE [RequestedBurnsID]= BD.[RequestedBurnsID] ORDER BY [RequestedBurnsID] ASC
        FOR XML PATH ('')) , 1 , 1, '') FROM
        [AQB_OB].[BurnDecisions] BD
     ) AS CONDITIONS
    
    FROM [AQB_MON].[AQB_OB].[RequestedBurns] RB
    LEFT join AQB_MON.[AQB_OB].[PileDryness] PD on RB.[PileDrynessID] = PD.[PileDrynessID]
    inner join AQB_MON.[AQB_OB].[BurnYear] BUY on BUY.BurnYearID = BP.BurnYearID
    inner join AQB_MON.[AQB_OB].[CurrentYear] CY on CY.CurrentYearID = BUY.CurrentYearID
    

    【讨论】:

    • 当我这样做时,我收到了错误Only one expression can be specified in the select list when the subquery is not introduced with EXISTS.。我认为这是由于STUFF 功能。
    【解决方案4】:

    或者使用 CTE(公用表表达式)作为子选择,例如:

    WITH CTE_Time(Clock)
    AS(
        SELECT 11 AS [Clock] -- set var
    )
    
    SELECT 
        DATEPART(HOUR, GETDATE()) AS 'actual hour',
        CASE
            WHEN DATEPART(HOUR, GETDATE()) >= (SELECT [Clock] FROM CTE_Time) THEN 'after'
            ELSE 'before'
        END AS [Data]
    

    【讨论】:

      猜你喜欢
      • 2012-10-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-01
      • 1970-01-01
      • 2014-04-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多