【问题标题】:How do I "Declare the scalar variable" in a VIEW in Sql Server (2005)如何在 Sql Server (2005) 的 VIEW 中“声明标量变量”
【发布时间】:2017-12-13 04:53:10
【问题描述】:

我正在尝试在 SQL Server 2005 中创建 VIEW

SQL 代码是这样工作的(我在 VS2008 中使用它),但在 SQL Server 中我无法保存它,因为错误消息“声明标量变量 @StartDate”和“声明标量变量 @结束日期”弹出。

代码如下:

WITH Calendar AS (SELECT     CAST(@StartDate AS datetime) AS Date
     UNION ALL
     SELECT     DATEADD(d, 1, Date) AS Expr1
     FROM         Calendar AS Calendar_1
     WHERE     (DATEADD(d, 1, Date) < @EndDate))
    SELECT     C.Date, C2.Country, COALESCE (SUM(R.[Amount of people per day needed]), 0) AS [Allocated testers]
     FROM         Calendar AS C CROSS JOIN
                            dbo.Country AS C2 LEFT OUTER JOIN
                            dbo.Requests AS R ON C.Date BETWEEN R.[Start date] AND R.[End date] AND R.CountryID = C2.CountryID
     GROUP BY C.Date, C2.Country

我的问题当然是 - 我应该如何声明它们?

我尝试将以下内容放在代码中:

DECLARE @StartDate smalldatetime
DECLARE @EndDate smalldatetime

但这并没有奏效,正如我所料 - 它只给了我另一个弹出消息:

“不支持 Declare cursor SQL 构造或语句。”

【问题讨论】:

    标签: sql sql-server-2005


    【解决方案1】:

    正如 Alex K 所提到的,您应该将其编写为内联表值函数。这是描述它的article

    简而言之,语法类似于

    CREATE FUNCTION dbo.GetForPeriod
        ( @StartDate datetime, @EndDate datetime) 
    RETURNS TABLE 
    RETURN 
       SELECT  [[ your column list ]]
       FROM    [[ table list]
       WHERE   [[some column] BETWEEN @StartDate AND @EndDate
    

    您可以有一个选择查询(无论多么复杂,都可以使用 CTE)。然后你会用它作为

    SELECT * FROM dbo.GetForPeriod('1-Jan-2010', '31-Jan-2010')
    

    【讨论】:

    • 很好,要测试一下 - 我认为这是一个可以接受的答案:-)
    • 函数的缺点是,如果你想加入或过滤它,它们的性能很差。
    • @IanBoyd,您所说的对于多语句 TVF 和标量函数通常是正确的。但是,这里的解决方案使用内联表值函数。 AFAIK,SQL Server 将在查询中扩展 UDF(就像在视图中所做的那样)。因此,与您所说的相反,它们在连接/过滤中会更好地工作(假设参与表具有适当的索引),或者至少,使用内联 TVF 不应该涉及任何惩罚(除了额外的解析)。见blogs.msdn.com/b/psssql/archive/2010/10/28/…
    • 添加 WITH SCHEMABINDING 会带来更多好处吗?
    • @Mark, WITH SCHEMABINDING 由于相关的依赖性检查(即避免由于架构更改而破坏 UDF)而总是有益的。但是,如果您从性能角度询问,则没有任何好处 - 适用于标量函数(请参阅blogs.msdn.com/b/sqlprogrammability/archive/2006/05/12/…
    【解决方案2】:

    如果 VIEW 是指 SQL Server 原生视图 (CREATE VIEW ...),则根本不能使用局部变量(您可以使用表值 udf)。

    如果你的意思是别的,那么添加 DECLARE @StartDate DATETIME, @EndDate DATETIME 会使该语句解析得很好,它是整个 SQL 吗?

    【讨论】:

    • 我的意思是我在 SQL Server Management Studio 中右键单击“视图”文件夹并选择“新视图...” - 我以这种方式创建了其他视图,然后我使用它们例如,在 Visual Studio 2008 (C#) 中创建“TableAdapters”时使用它们。那么,什么是表值 udf?我在哪里以及如何创建它,你知道吗?
    【解决方案3】:

    这是一个使用 CTE 很好地模拟内部变量构造的示例查询。您可以在您的 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
    

    【讨论】:

      【解决方案4】:

      尝试用 A.X 和 A.Y 替换所有 @X、@Y,添加到您的代码中: FROM (SELECT X = 'literalX', Y = 'literalY') A 那么您将所有文字放在一个位置,并且只有一个副本。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-03-13
        • 1970-01-01
        相关资源
        最近更新 更多