这个创建视图代码是如何工作的?

How does this create view code work?

提问人:NulisDefo 提问时间:8/9/2017 最后编辑:NulisDefo 更新时间:8/9/2017 访问量:92

问:

好的,这里是视图的示例代码。第二部分对我来说似乎很清楚。这是运行查询以使用视图时将显示的部分。不过,第一部分尚不清楚。select RT.RoleID[...]

据我所知,前两行是标准的,然后是整个部分。有人可以向我解释一下吗?从未见过的配方withwith "something" as (select)

    CREATE VIEW [dbo].[sviw_System_MyPermissions_CurrentDomain]
AS  

WITH MyDomainRoles AS (
  SELECT RM.Domain, RM.RoleID
    FROM stbl_System_RolesMembersDomains AS RM WITH (NOLOCK)
    WHERE RM.Domain = (SELECT CurrentDomain FROM stbl_System_Users WITH (NOLOCK) WHERE Login = SUSER_SNAME())
      AND RM.Login = SUSER_SNAME()
)

SELECT RT.RoleID, RT.TableName, DR.Domain, RT.GrantUpdate, RT.GrantInsert, RT.GrantDelete
  FROM stbl_System_RolesTables AS RT WITH (NOLOCK) 
    JOIN MyDomainRoles AS DR ON RT.RoleID = DR.RoleID

GO
sql 服务器 t-sql 公用表表达式

评论

2赞 Shannon Severance 8/9/2017
首次编辑后,问题文本不再与示例代码匹配。
0赞 xQbert 8/9/2017
不要重新发明轮子:stackoverflow.com/questions/4740748/...。WITH(公共表表达式 (CTE))块类似于内联视图/子查询,它已被重构为它自己的选择。如果必须多次执行选择以节省性能和维护时间,则通常会执行此操作。
0赞 shiwanginio 9/21/2019
-- SQL Server 和 Azure SQL 数据库的语法 CREATE [ OR ALTER ] VIEW [ schema_name . ] view_name [ (列 [ ,...n ] ) ] [ WITH <view_attribute> [ ,...n ] ] AS select_statement [ with check option ] [ ; ] <view_attribute> ::= { [ 加密 ] [ 架构绑定 ] [ VIEW_METADATA ] }

答:

2赞 Lukasz Szozda 8/9/2017 #1

它被称为公共表表达,基本上您的视图与以下内容相同:

CREATE VIEW vSalesStaffQuickStats
AS
 SELECT E.EmployeeID, 
         EmployeeOrders = OS.NumberOfOrders, 
         EmployeeLastOrderDate = OS.MostRecentOrderDate, 
         E.ManagerID, 
         ManagerOrders = OM.NumberOfOrders, 
         ManagerLastOrderDate = OM.MostRecentOrderDate 
  FROM   HumanResources.Employee AS E 
       INNER JOIN    (
            SELECT SalesPersonID, COUNT(*) NumberOfOrders
                  , MAX(OrderDate) MostRecentOrderDate
            FROM Sales.SalesOrderHeader
            GROUP BY SalesPersonID
      ) AS OS 
         ON E.EmployeeID = OS.SalesPersonID 
       LEFT OUTER JOIN    (
            SELECT SalesPersonID, COUNT(*) NumberOfOrders
                 , MAX(OrderDate) MostRecentOrderDate
            FROM Sales.SalesOrderHeader
            GROUP BY SalesPersonID
      ) AS OM 
         ON E.ManagerID = OM.SalesPersonID 

如您所见,您可以轻松地将其与子查询交换。但就您而言,您需要做两次(使用 CTE,您只做一次)。

编辑:

更新后使用新查询:

CREATE VIEW [dbo].[sviw_System_MyPermissions_CurrentDomain]
AS  
SELECT RT.RoleID, RT.TableName, DR.Domain, RT.GrantUpdate, RT.GrantInsert, RT.GrantDelete
FROM stbl_System_RolesTables AS RT WITH (NOLOCK) 
JOIN (
    SELECT RM.Domain, RM.RoleID
    FROM stbl_System_RolesMembersDomains AS RM WITH (NOLOCK)
    WHERE RM.Domain = (SELECT CurrentDomain FROM stbl_System_Users WITH (NOLOCK) WHERE Login = SUSER_SNAME())
      AND RM.Login = SUSER_SNAME()
) AS DR ON RT.RoleID = DR.RoleID

评论

0赞 NulisDefo 8/9/2017
我看到我犯了一个错误,从互联网上随机举例。您可以使用稍后放入的查询来编辑答案吗?
0赞 NulisDefo 8/9/2017
所以它就像其他语言(php、c++)中的一个函数,我在其中进行查询,以后可以通过插入函数名称来重用它
1赞 Lukasz Szozda 8/9/2017
有点,但基本上是同一个想法。
0赞 pmbAustin 8/9/2017
它只是嵌入式子选择的语法糖。性能(几乎)总是一样的。它只是使代码更具可读性。它并不像一个“函数”,因为 CTE 的范围只是下一个命令 (SELECT/UPDATE/DELETE)......例如,您不能将其重用于多个 SELECT。这就像创建一个动态虚拟表供 SELECT 操作一样。
0赞 Milan 8/9/2017 #2

WITH关键字仅指公共表表达式(在此处阅读更多内容:https://learn.microsoft.com/en-us/sql/t-sql/queries/with-common-table-expression-transact-sql)基本上,WITH语句中的所有内容都可以被视为外部化的子查询,然后在主查询中使用结果集。

即:

WITH MyDomainRoles AS (

  --- sub-query Start
  SELECT RM.Domain, RM.RoleID
    FROM stbl_System_RolesMembersDomains AS RM WITH (NOLOCK)
    WHERE RM.Domain = (SELECT CurrentDomain FROM stbl_System_Users WITH (NOLOCK) WHERE Login = SUSER_SNAME())
      AND RM.Login = SUSER_SNAME()
  --- sub-query End

)

...上述子查询的结果集保存在名为 MyDomainRoles 的 CTE 中。然后,可以将 MyDomainRoles 引用为表。使阅读更简单,书写更清晰。

由于这个 CTE 非常简单,您可以轻松地将其重写如下,但它看起来并不那么整洁:

WITH MyDomainRoles AS (

)

SELECT RT.RoleID, RT.TableName, DR.Domain, RT.GrantUpdate, RT.GrantInsert, RT.GrantDelete
  FROM stbl_System_RolesTables AS RT WITH (NOLOCK) 
    JOIN (

SELECT RM.Domain, RM.RoleID
    FROM stbl_System_RolesMembersDomains AS RM WITH (NOLOCK)
    WHERE RM.Domain = (SELECT CurrentDomain FROM stbl_System_Users WITH (NOLOCK) WHERE Login = SUSER_SNAME())
      AND RM.Login = SUSER_SNAME()

) AS DR ON RT.RoleID = DR.RoleID