SQL视图中的动态架构名称

时间:2019-06-05 14:05:01

标签: sql sql-server tsql dynamic table-valued-parameters

我有两个数据集:

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

匹配键会定期更新,我想创建一个Dog数据集的视图(或具有相同目的的东西),该数据集始终连接到最新匹配键上。此外,它可以像表一样被内联引用

查找表中的匹配更新由它们的架构名称区分,因此要获取最新的名称,我只需要标识最新的架构名称并将其交换出查询即可。

鉴于视图和表值函数均禁止动态SQL,并且不能像表一样引用存储过程,这是怎么能仅用SQL来实现的呢?

1 个答案:

答案 0 :(得分:2)

  

查找表中的匹配更新因其架构名称而有所不同,因此,要获取最新的名称,我只需标识最新的架构名称并将其交换出查询即可。

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

我假设每当创建一个新的架构时,也会在该架构中创建一个新表,但是表名和它的列名总是相同的。请注意,此假设对我将要提出的解决方案至关重要-该解决方案是使用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 '+ @NewSchemaName +'.'+ @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

You can see a live demo on Rextester.