【问题标题】:Convert a query of views into a single query with derived tables将视图查询转换为具有派生表的单个查询
【发布时间】:2015-03-15 08:35:37
【问题描述】:

是否可以将由视图中的许多视图组成的查询(如以文本形式获取查询)转换为仅基于原始表的查询?

很明显是遍历所有视图,然后手动执行,但想知道是否有更快的方法?

【问题讨论】:

  • 能否请您指定您使用的是哪个 RDBMS? (MySQL、SQL Server、Oracle 等)
  • 如果你问的是这个问题,我不认为有一个通用的解决方案,至少不是一个实用的解决方案。
  • 好吧,我很害怕,在任何地方都找不到答案(正面或负面)的问题,想确定一下。
  • 不确定我是否按照您的要求进行操作,您是否要查询一些视图定义并创建多个视图定义的连接?

标签: sql sql-server sql-server-2012 sql-view


【解决方案1】:

它不漂亮,就像@David Faber 评论的那样,不确定这会有多实用,但是这里......

一个人必须做出很多假设才能让它发挥作用,比如

  • 所有视图都以 SELECT 开头。 (无 CTE)
  • 在另一个视图中引用时,该视图未包含在 [ ] 中
  • 视图名称中没有空格
  • 此版本仅深度 1 级,但应该可以以类似方式解析您在输出中找到的任何其他视图。
  • 可能还有一些我没想到的

我使用的是 sys 表,而不是较新的架构信息对象,只是因为我更了解 sys 表结构。

假设如下视图

CREATE VIEW VW_DUMMY
AS
SELECT c.Name as Company, g.Name as [Group], gu.UserId
FROM VW_Company c
    JOIN VW_Group g ON c.Id = g.CompanyId
    JOIN VW_GroupUser gu ON g.Id = gu.GroupId AND gu.CompanyId = c.Id

这就是我所做的。

1) 从 syscmets 获取 VW_DUMMY 的视图定义。

2) 去掉 CREATE VIEW 部分

2) 从 sysdepends 中获取 VW_DUMMY 依赖的对象列表

3) 从 syscmets 中获取所有依赖对象的视图定义。

4) 去掉 CREATE VIEW 部分

5) 将原始视图中“depends”对象的名称替换为 定义...

1)

DECLARE @SQL    VARCHAR(MAX);
SET @SQL = REPLACE((
    SELECT c.text AS [text()]
    FROM syscomments c 
    WHERE c.id = OBJECT_ID('VW_DUMMY')
    FOR XML PATH('')), '
', '');

2)

SET @SQL = SUBSTRING(@SQL, PATINDEX('%SELECT%', @SQL), LEN(@SQL))

3)、4) 和 5)

SELECT @SQL = REPLACE(@SQL, ' ' + name + ' ', '(' + SUBSTRING(text, PATINDEX('%SELECT%', text), LEN(text)) + ') ')
FROM (
    SELECT DISTINCT OBJECT_NAME(depid) as name,
    REPLACE((
        SELECT c.text AS [text()]
        FROM syscomments c 
        WHERE c.id = d.depid
        FOR XML PATH('')), '
', '') as text
    FROM sysdepends d
WHERE d.id = OBJECT_ID('VW_DUMMY')
AND exists(select 1 from sysobjects c where c.id = d.depid and c.type='V')) data

SELECT @SQL

我在我的数据库中尝试了 VW_DUMMY,输出是一些您可能见过的格式最差的代码,但结果与视图相同。

这里是输出(错误的格式是故意的)

SELECT c.Name as Company, g.Name as [Group], gu.UserId
FROM(SELECT *
FROM Company


) c
    JOIN(SELECT *
FROM [Group]



) g ON c.Id = g.CompanyId
    JOIN(SELECT *
FROM [GroupUser]



) gu ON g.Id = gu.GroupId AND gu.CompanyId = c.Id

这有帮助吗?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-23
    • 2020-12-10
    • 1970-01-01
    • 1970-01-01
    • 2021-11-02
    相关资源
    最近更新 更多