SQL - 触发器中的表模式更改然后更新依赖项(视图)

时间:2015-07-09 12:55:18

标签: sql-server triggers sql-view

这是场景(代码是C#):

我们允许在我们的应用程序中创建表格列。当一个记录被放入一个表(我们的元数据表,前进称为mdt)时,我们在一个表上创建一个列,该列对应于我们刚刚在mdt中创建的数据。我们在mdt上有一个触发器来创建这个列。在此触发器结束时,我们正在更新刚刚创建新列的表的所有依赖项。

在SSMS中我可以运行所有SQL并且它可以工作,但是在代码中,所有SQL运行,但依赖关系不会更新。代码在事务中运行所有SQL,但是我使用事务在SSMS中运行测试,但是SSMS中的SQL工作,而我们的应用程序中的代码却没有。通过不工作,我的意思是依赖关系不刷新。列创建工作,这意味着触发器在两种情况下都会触发,这意味着尝试重新生成视图依赖项的代码正在运行。

简而言之:

插入记录>火灾触发器>创建列>刷新视图依赖性

SSMS - 一切正常

从代码 - 一切正常,但视图依赖关系的刷新实际上并没有刷新视图

我的第一个想法是交易的方式(代码和SSMS之间)存在差异,但是我在运行脚本的应用程序中添加了代码以刷新事务结束之外的视图依赖关系创建新列仍然没有更新依赖项,但是如果我在SSMS中运行相同的SQL,依赖项会更新。

任何想法都会受到赞赏。

这是我们用来刷新视图的代码:

    IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[uspRefreshViewDependencies]') AND type in ('P'))
DROP Procedure [dbo].[uspRefreshViewDependencies]
GO

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE PROCEDURE [dbo].[uspRefreshViewDependencies](
    @nvcViewName nvarchar(776),
    @bitIncludeCustomerObjects bit = 1
)
AS

/*
This procedure will correct View and UDF dependencies after columns have changed.  Given the name of a View
for @nvcViewName, it will detect all of the Views and UDFs (both table-type and inline-table) that reference
them, and call sys.sp_refreshsqlmodule to update them.  It runs recursively (so it can correct dependencies
on dependencies on dependencies, and so on.)

if @bitIncludeCustomerObjects is false, the algorithm will skip custom database objects (anything in the dbo
schema that starts with the letter "c".)

This was created for managing Entity Views but it should also work for tables and UDFs.
*/

DECLARE c CURSOR FORWARD_ONLY STATIC FOR


WITH dependencies (referencing_id, referencing_object_name, type, level)
AS
(
    SELECT referencing_id, OBJECT_SCHEMA_NAME(referencing_id) + '.' + OBJECT_NAME(referencing_id), SO.type, 1 as level
    FROM sys.dm_sql_referencing_entities(OBJECT_SCHEMA_NAME(OBJECT_ID(@nvcViewName)) + '.' + OBJECT_NAME(OBJECT_ID(@nvcViewName)), 'OBJECT') sre
        INNER JOIN sys.objects SO ON sre.referencing_id = SO.object_id
    WHERE SO.type IN ('V', 'TF', 'IF', 'P')
        AND (
            @bitIncludeCustomerObjects = 1
            OR OBJECT_NAME(referencing_id) NOT LIKE 'c%')

    UNION ALL

    SELECT SED.referencing_id, OBJECT_SCHEMA_NAME(SED.referencing_id) + '.' + OBJECT_NAME(SED.referencing_id), SO.type, level + 1
    FROM dependencies D
        INNER JOIN sys.sql_expression_dependencies SED ON D.referencing_id = sed.referenced_id
        INNER JOIN sys.objects SO ON SED.referencing_id = SO.object_id
    WHERE SO.type IN ('V', 'TF', 'IF', 'P')
        AND (
            @bitIncludeCustomerObjects = 1
            OR OBJECT_NAME(SED.referencing_id) NOT LIKE 'c%')
)

SELECT referencing_object_name, type, Max(level) as level
FROM dependencies
Where (OBJECT_SCHEMA_NAME(referencing_id) <> 'Custom')
Group By referencing_object_name, type
ORDER BY level


DECLARE @nvcDependency nvarchar(776)
DECLARE @nvcType nvarchar(30)
DECLARE @intLevel Int

OPEN c
FETCH NEXT FROM c INTO @nvcDependency, @nvcType, @intLevel

WHILE @@FETCH_STATUS = 0
BEGIN
    PRINT 'Refreshing ' + @nvcDependency
    EXEC sys.sp_refreshsqlmodule @nvcDependency
    FETCH NEXT FROM c INTO @nvcDependency, @nvcType, @intLevel
END

CLOSE c
DEALLOCATE c
Go

我发现在SSMS中运行它时,一切都按预期运行,但是从C#运行时,CTE似乎没有返回任何结果,也从未进入游标。

0 个答案:

没有答案