有没有办法使用 SQL Server 2012 查找视图中引用的所有无效列?

Posted

技术标签:

【中文标题】有没有办法使用 SQL Server 2012 查找视图中引用的所有无效列?【英文标题】:Is there a way to find all invalid columns that are referenced in a view using SQL Server 2012? 【发布时间】:2013-09-23 07:30:32 【问题描述】:

我继承了一个拥有数千个视图的大型数据库项目。

许多视图无效。它们引用不再存在的列。有些视图非常复杂,引用了很多列。

有没有一种简单的方法可以追踪所有不正确的列引用?

【问题讨论】:

您可以调整来自sp_refreshview 页面的示例B(通过删除连接)来创建一个尝试刷新数据库中每个视图的脚本。然后运行该脚本,它应该为每个不再工作的视图产生一个错误 【参考方案1】:

此答案通过查看 sys.viewssys.columnssys.depends 来查找最初在视图中定义的基础列(如果列已被​​别名,则获取基础列)。然后将其与INFORMATION_Schema.VIEW_COLUMN_USAGE 中保存的数据进行比较,该数据似乎具有当前列的使用情况。

SELECT  SCHEMA_NAME(v.schema_id) AS SchemaName, 
        OBJECT_NAME(v.object_id) AS ViewName, 
        COALESCE(alias.name, C.name) As MissingUnderlyingColumnName
FROM sys.views v
INNER JOIN sys.columns C
    ON C.object_id = v.object_id
LEFT JOIN sys.sql_dependencies d 
    ON d.object_id = v.object_id
LEFT JOIN sys.columns alias
    ON d.referenced_major_id = alias.object_id AND c.column_id= alias.column_id
WHERE NOT EXISTS
        (
            SELECT * FROM Information_Schema.VIEW_COLUMN_USAGE  VC
            WHERE VIEW_NAME = OBJECT_NAME(v.object_id) 
                AND VC.COLUMN_NAME = COALESCE(alias.name, C.name)
                AND VC.TABLE_SCHEMA = SCHEMA_NAME(v.schema_id)
        )

对于以下视图:

create table test
( column1 varchar(20), column2 varchar(30))


create view vwtest as select column1, column2 as column3 from test


alter table test drop column column1

查询返回:

SchemaName  ViewName    MissingUnderlyingColumnName
dbo         vwtest      column1

这是在Answer的帮助下开发的

【讨论】:

谢谢,这个答案更好。它运行得更快。 @Alex 这是不使用游标的好处之一!【参考方案2】:

已更新以检索错误详细信息

所以这个答案可以让你得到你想要的,但它不是最好的代码。

使用游标(是的,我知道 :))从 TRY 块中的每个视图执行 SELECT 以查找失败的视图。请注意,我用SELECT * INTO #temp FROM view X WHERE 1 = 0 包装每个语句,这是为了阻止EXEC 返回任何结果,而 1=0 是为了让 SQL Server 可以优化查询,使其实际上是一个 NO-OP。

然后我返回一个 sql 失败的视图列表。

我没有对此进行大量测试,但它似乎有效。我想摆脱 View 中每个 SELECT 的执行。

原来是这样:

DECLARE curView CURSOR FOR
    SELECT  v.name AS ViewName
    FROM sys.views v
    INNER JOIN sys.sql_modules m
        on v.object_id = m.object_id

OPEN curView
DECLARE @viewName SYSNAME

DECLARE @failedViews TABLE
(
    FailedViewName SYSNAME,
    ErrorMessage VARCHAR(MAX)
)

FETCH NEXT FROM curView 
    INTO @ViewName

WHILE @@FETCH_STATUS = 0
BEGIN
    BEGIN TRY
        exec ('SELECT * INTO #temp FROM ' + @viewName + ' WHERE 1=0' )
    END TRY
    BEGIN CATCH
        INSERT INTO @failedViews VALUES (@viewName, ERROR_MESSAGE())
    END CATCH
    FETCH NEXT FROM curView 
        INTO @ViewName
END
CLOSE curView
DEALLOCATE curView

SELECT *
FROM @failedViews

返回的错误示例如下:

FailedViewName  ErrorMessage
--------------- -------------
vwtest          Invalid column name 'column1'.

【讨论】:

这只显示视图名称?我想找到导致视图失败的列。有些表有很多列,所以手动操作很慢。 @Alex 我已更新答案以报告查看错误消息,该消息将提供列错误的详细信息 @Alex 查看我的新答案 @Alex 感谢您的接受,但我认为我的其他回答可能对您有更多帮助【参考方案3】:

您可以使用系统表获取信息。

SELECT v.VIEW_NAME,v.TABLE_CATALOG,v.TABLE_SCHEMA,v.TABLE_NAME,v.COLUMN_NAME
from INFORMATION_SCHEMA.VIEW_COLUMN_USAGE v
left outer join INFORMATION_SCHEMA.COLUMNS c
ON v.TABLE_CATALOG=c.TABLE_CATALOG AND v.TABLE_SCHEMA=c.TABLE_SCHEMA AND v.TABLE_NAME=c.TABLE_NAME AND v.COLUMN_NAME=c.COLUMN_NAME
WHERE c.TABLE_NAME IS NULL
ORDER BY v.VIEW_NAME

【讨论】:

这只会返回表中仍然存在的列,而不是视图中引用但表中不再存在的列。试试 CREATE TABLE test1 (ID INT,NAME VARCHAR(50), Additional VARCHAR(50)) GO CREATE VIEW vTest1 AS SELECT Id, Name, Additional FROM test1 GO ALTER table Test1 DROP COLUMN Additional GO SELECT * from INFORMATION_SCHEMA.VIEW_COLUMN_USAGE v WHERE VIEW_NAME = 'vtest1'

以上是关于有没有办法使用 SQL Server 2012 查找视图中引用的所有无效列?的主要内容,如果未能解决你的问题,请参考以下文章

在Windows2012下安装SQL Server 2005无法启动服务的解决办法

使用 JDBC 识别 SQL Server 版本

如何用sqlserver 2000事件查探器查询sql

如何让 SQL Server 2012 Management Studio 长时间连接到数据库?

关于sql server 2012日志变得超大的删除解决办法

windows server 2012 可以安装sql2008 吗