SQL 视图中的动态架构名称

问题描述 投票:0回答:1

我有两个数据集:

  1. 一个是关于狗的数据[我的数据]
  2. 第二个是匹配键的查找表[我无法控制这些数据]

匹配的键会定期更新,我想创建 Dog 数据集的视图(或实现相同目的的东西),它总是连接到 最新的 匹配键。此外,我需要能够内联引用它 - 就好像它是一个表

查找表中的匹配更新通过其架构名称来区分,因此要获取最新的,我只需识别最新的架构名称并将其从查询中交换出来。

鉴于视图和表值函数都禁止动态 SQL,并且存储过程不能像表一样引用,我怎样才能仅用 SQL 来实现这一点?

sql sql-server t-sql dynamic table-valued-parameters
1个回答
3
投票

查找表中的匹配更新通过其架构名称来区分,因此要获取最新的,我只需识别最新的架构名称并将其从查询中交换出来。

您可以使用视图来解决这个问题,但是每当新数据输入数据库时,您需要某种方法来更改它。

我假设每当创建新模式时,也会在该模式中创建一个新表,但表名及其列名始终相同。请注意,这个假设对于我即将提出的解决方案至关重要 - 该解决方案是使用 DDL 触发器侦听数据库级别的

create_table
事件来更改您的视图,以便它将引用新的模式创建表。

我所做的另一个假设是您已经拥有初始视图,或者您正在使用 SQL Server 2016 或更高版本(允许创建或更改语法)。

首先,让我们创建初始视图:

CREATE VIEW dbo.TheView 
AS 
    SELECT NULL As Test 
GO

然后,我添加了 DML 触发器,它根据新创建表的架构创建并执行动态

alter view
语句:

CREATE TRIGGER AlterViewWhenSchemaChanges
    ON DATABASE
    FOR CREATE_TABLE
AS

    DECLARE @Sql nvarchar(max),
            @NewTableName sysname,
            @NewSchemaName sysname;
            
    SELECT  @NewSchemaName = EVENTDATA().value('(/EVENT_INSTANCE/SchemaName)[1]',  'NVARCHAR(255)'),
            @NewTableName = EVENTDATA().value('(/EVENT_INSTANCE/ObjectName)[1]',  'NVARCHAR(255)');

    -- We only want to alter the view when this specific table is created!
    IF @NewTableName = 'TableName' 
    BEGIN 

        SELECT @Sql = 
        'ALTER VIEW dbo.TheView
        AS
            SELECT Col as test
            FROM '+ QUOTENAME(@NewSchemaName) +'.'+ QUOTENAME(@NewTableName) +';'

        EXEC(@Sql)
    END
GO

这样,每当创建具有特定名称(在我的示例中为

TableName
)的新表时,视图都会更改为引用最后创建的
TableName
(显然是在最新模式中创建的)。

测试脚本:

SELECT * FROM dbo.TheView;
GO

结果:

Test
NULL

使用表创建新架构

TableName

CREATE SCHEMA SchemaName
CREATE TABLE SchemaName.TableName (Col int);

GO  

-- insert some data
INSERT INTO SchemaName.TableName(Col) VALUES (123);

-- get the data from the altered view
SELECT * FROM dbo.TheView

结果:

test
123

您可以在 Rextester 上观看现场演示。

© www.soinside.com 2019 - 2024. All rights reserved.