【问题标题】:union all on views based on table联合所有基于表的视图
【发布时间】:2011-09-09 13:56:42
【问题描述】:

我有一个带有 sql 视图列表的数据库表

我想创建一个新视图或存储过程,基于该表中的哪些视图将返回那些合并的视图 像这样

SELECT     ALINE1, HOME, EMAIL, EXPIRE, EDATE7, type
    FROM         dbo.campaign_membership_30
    UNION ALL
    SELECT     ALINE1, HOME, EMAIL, EXPIRE, EDATE7, type
    FROM         dbo.campaign_membership_30n
    UNION ALL
    SELECT     ALINE1, HOME, EMAIL, EXPIRE, EDATE7, type
    FROM         dbo.campaign_membership_60n
    UNION ALL
    SELECT     ALINE1, HOME, EMAIL, EXPIRE, EDATE7, type
    FROM         dbo.campaign_membership_today
    UNION ALL
    SELECT     ALINE1, BOOKNO, EMAIL, DEPART, DEP7, type
    FROM         dbo.depart_151days
    UNION ALL
    SELECT     ALINE1, BOOKNO, EMAIL, DEPART, DEP7, type
    FROM         dbo.depart_90Days

【问题讨论】:

  • 是的,你可以这样做。我不确定你的问题是什么。
  • 是什么阻止了你这样做?什么是 RDBMS?到目前为止,您尝试过什么?
  • 我的问题是动态创建联合,所以假设我有一个网络应用程序,我在其中键入视图并单击添加
  • 我希望它动态添加 UNION ALL SELECT ALINE1, BOOKNO, EMAIL, DEPART, DEP7, type FROM addedview
  • 我明白了。又是什么 RDBMS?

标签: sql sql-server-2005 stored-procedures dynamic-sql


【解决方案1】:

这里有很多重要的警告。

首先,使用动态 SQL 通常很危险。它可以打开您的数据库以进行 SQL 注入攻击。如果你不明白这些是什么,那么在我建议你使用动态 SQL 之前,你需要对自己进行大量的教育。

其次,这种模式(将表和列存储在用于生成 SQL 的表中)是一种非常糟糕的模式。它有很多问题。在不了解您的应用程序/问题空间的情况下,我无法建议替代解决方案。

也就是说,以下是它在 SQL Server 2005 中如何工作的简化版本。这不包括错误处理等。

DECLARE @sql VARCHAR(MAX)  -- NVARCHAR if you use unicode characters in table names

SELECT
    @sql = dbo.Concatenated_Rows('SELECT col1, col2 FROM ' + MT.table_name + ' UNION ALL ')
FROM
    dbo.My_Table MT

-- Remove the extra UNION ALL
SELECT @sql = SUBSTRING(@sql, 1, LEN(@sql) - 11)

EXEC(@sql)

必须编写函数 Concatenated_Rows。您也可以使用游标或什至 FOR XML 来创建连接字符串。这是a link,它很好地解释了许多可能的方法,并且很好地比较了它们。

同样,可能有比走这条路更好的解决方案,尤其是如果这不仅仅是一次性的任务。

【讨论】:

  • 对不起,如果这是一个愚蠢的问题,但 dbo.Concatenated_Rows 或 mt.table_name 会是我所有视图的表的名称
  • 因为当我执行 SELECT @sql = dbo.Concatenated_Rows('SELECT email FROM ' + dbo.email_campaigns + ' UNION ALL ') FROM dbo.email_campaigns 时,我在 dbo.Concatenated_Rows 收到错误
  • Msg 4121,级别 16,状态 1,过程 testemailcampaign,第 21 行找不到列“dbo”或用户定义的函数或聚合“dbo.Concatenated_Rows”,或者名称不明确。
  • 包含所有视图的表将是 dbo.My_Table。正如我所说,必须编写函数 Concatenated_Rows。如果您点击我包含的链接,您可以看到它的示例。
【解决方案2】:

我认为您正在寻求一种方法来让表驱动哪些视图是查询的一部分。换句话说,如果您的表有以下行:

dbo.View1
dbo.View2
dbo.View3

您的查询将返回这三个视图的联合;对吗?

警告:我强烈质疑要求您这样做的底层关系结构。更好的数据模型可能会使这变得不必要。但我假设你没有能力改变模型,所以试试这个:

假设上面列出的三个视图位于名为“ViewsToReturn”的表中名为“ViewName”的字段中。构造一个查询,首先联合 所有 视图,然后根据 ViewsToReturn 中的视图名称对其进行过滤。像这样:

SELECT * FROM
    (SELECT Field1, Field2, 'dbo.View1' AS ViewName FROM dbo.View1
    UNION
    SELECT Field1, Field2, 'dbo.View2' AS ViewName FROM dbo.View2
    UNION
    SELECT Field1, Field2, 'dbo.View3' AS ViewName FROM dbo.View3
    UNION
    SELECT Field1, Field2, 'dbo.View4' AS ViewName FROM dbo.View4) AllRecords
WHERE AllRecords.TableName IN
    SELECT ViewName FROM ViewsToReturn

这个解决方案既不优雅也不高效,但如果我正确理解您的问题,应该可以解决问题。

祝你好运!

【讨论】:

  • hmmm 所以如果我将 dbo.view4 添加到顶部表中,我不需要更改底部的任何内容
  • 嗯,这不是我想要的方式,因为我不想继续更改 sql
  • 正确。但是,如果您添加了 dbo.view5,则必须在查询中添加另一行。正如我所说......不优雅!有人可能会提出一种在存储过程中使用动态查询的更可扩展的方法,但这不是我的专长。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-02-07
  • 2011-05-28
  • 1970-01-01
  • 2011-08-10
  • 1970-01-01
  • 2021-01-24
  • 2022-12-17
相关资源
最近更新 更多