我可以在视图中查询数据库中的表(仅当它存在时)?

Posted

技术标签:

【中文标题】我可以在视图中查询数据库中的表(仅当它存在时)?【英文标题】:Can I query a table in a database, only if it exists, within a view? 【发布时间】:2019-08-28 10:15:28 【问题描述】:

我正在尝试标准化两个客户之间不同的视图。不同之处之一是对数据库中的表的左连接,该表仅针对其中一个客户存在,因为它仅与他们相关。我不想在其他客户服务器上创建数据库。我还想避免创建为另一个视图,因为附加了很多依赖项。

我已尝试添加 SYNONYM,但由于其他服务器上不存在数据库和表,这会导致错误。

我尝试将逻辑添加到视图中,但这里有点受限。

CREATE TABLE #Product
(
    ProductID INT IDENTITY(1,1) NOT NULL,
    Product_Name VARCHAR(100) NOT NULL
)

INSERT #Product
(
    Product_Name
)
SELECT 'Example Product 1' UNION
SELECT 'Example Product 2' 

CREATE TABLE #CustomerDB_Product -- This is a replica of the table which exists in the customer specific database
(
    CustomerDBProductID INT IDENTITY(1,1) NOT NULL,
    CustomerDBProduct_Name VARCHAR(100) NOT NULL
)

INSERT #CustomerDB_Product
(
    CustomerDBProduct_Name
)
SELECT 'Example Customer Product 1'

SELECT  P.ProductID,
        MAX(P.Product_Name) AS Product_Name,
        MAX(CASE WHEN CP.CustomerDBProductID IS NOT NULL THEN CP.CustomerDBProduct_Name ELSE P.Product_Name END) AS CustomerProduct_Format
FROM    #Product P
        LEFT JOIN #CustomerDB_Product CP ON CP.CustomerDBProductID = P.ProductID
GROUP BY
        P.ProductID

-- DROP TABLE #Product
-- DROP TABLE #CustomerDB_Product

存在客户特定数据库的地方我希望看到CustomerProduct_Format 列提取数据,而客户特定数据库不存在的地方我希望CustomerProduct_Format 列与Product_Name 完全匹配列。

建议的解决方案需要能够写成视图。

【问题讨论】:

VIEW 只是一个预编译的SELECT 语句,它不能有任何其他内部逻辑。如果 VIEW 引用的对象不存在,则会出错;你无法避免。如果该对象可能存在也可能不存在,这听起来像是您有设计问题,或者您不应该使用VIEW 感谢@Larnu 的确认!看起来我别无选择,只能将其拆分为另一个客户特定的视图,然后去修改所有依赖项。 @APC - 因为“CustomerDB_Product”存在于无法在其他客户服务器上创建的客户特定数据库中。它在运行查询的数据库中不存在。它在一个单独的数据库中的原因是因为它是一个完全独立的应用程序,我们正在为其存储数据。 好的,但你不能建立一个虚拟的吗?您只需要一列。 如果你可以只为一个特定的客户维护一个特殊的表,你不能也为那个客户维护一个特殊的视图吗?或者创建两个视图,然后为该客户维护一个不同的同义词 【参考方案1】:

我添加同义词的意思。对于客户 A,您有一个视图,其中包含仅为客户 A 存在的表或列。

CREATE VIEW dbo.ViewForCustomerA
AS
  SELECT ... FROM <tables that exist for everyone>
             JOIN <table that only exists for CustomerA>;
GO

对于其他所有人(甚至客户 A),您有一个不包含这些对象的不同视图:

CREATE VIEW dbo.ViewForEveryoneElse
AS
  SELECT ... FROM <tables that exist for everyone>;
GO

然后,仅在客户 A 的数据库中,创建一个指向其特殊观点的同义词:

CREATE SYNONYM dbo.ViewName FOR dbo.ViewForCustomerA;

对于其他所有人,您创建相同的同义词,但将其指向所有人的视图:

CREATE SYNONYM dbo.ViewName FOR dbo.ViewForEveryoneElse;

现在,您引用底层视图的所有其余代码都可以引用dbo.ViewName - 无论它是哪个客户,它都可以工作,省去了很多麻烦,使您的所有查询都是有条件的或保持混乱大量嵌套视图。

【讨论】:

以上是关于我可以在视图中查询数据库中的表(仅当它存在时)?的主要内容,如果未能解决你的问题,请参考以下文章

mysql--视图,触发器

仅当表存在时如何删除 Amazon Redshift 中的表

mysql数据库视图

仅当查询不为空时,才从查询写入 BigQuery 中的表

视图应用竟然还可以这么优化?不得不收藏

「mysql优化专题」视图应用竟然还可以这么优化?不得不收藏