2

在 SQL Server 中,有没有办法检查架构中的更改是否会影响存储过程(和/或视图)?
例如更改一个表中的列名,可能会破坏一些存储过程;如何检查受影响的存储过程?

4

8 回答 8

3

尝试使用:

EXEC sp_depends 'YourTableName'

和/或

DECLARE @Search nvarchar(500)
SET @Search='YourTableName' --or anything else
SELECT DISTINCT
    LEFT(o.name, 100) AS Object_Name,o.type_desc
    FROM sys.sql_modules        m 
        INNER JOIN sys.objects  o ON m.object_id=o.object_id
    WHERE m.definition Like '%'+@Search+'%'
    ORDER BY 2,1
于 2010-03-26T19:43:40.330 回答
2

使用 Visual Studio Database Edition 进行 T-SQL 开发。它将在构建期间捕获此类问题,因为它会创建部署 .dbschema 文件。

于 2010-03-26T19:39:51.393 回答
1

我能想到的最好方法是使用视图从您的实际表中抽象出您的存储过程,并使用“WITH SCHEMABINDING”子句创建这些视图,该子句应防止会破坏您的视图的更改......

于 2010-03-26T19:33:59.333 回答
1

Red Gate 的 SQL Refactor等商业工具可以做到这一点。
我认为最近版本的Visual Studio也包含这种功能,但我没有尝试过。

据我所知,Microsoft SQL Server本身没有内置功能 可以做到这一点。更正:我刚刚在 KM 对这篇文章的回答中阅读了关于sp_depends的信息……请注意,不推荐使用 sp_depends;它被sys.dm_sql_referencing_entitiessys.dm_sql_referenced_entities取代

此外,如果底层存储过程使用动态 SQL,则检测依赖关系的任务变得更加困难并且容易出现“未命中”。

于 2010-03-26T19:40:02.773 回答
1

在 SSMS (SQL Server Management Studio) 中,右键单击要更改的对象,然后单击查看依赖项。我认为这不会从另一个数据库中找到参考。

如果未加密,您还可以在存储过程中查找引用。您必须在您怀疑可能引用您正在更改的对象的每个数据库中执行此操作。

select objects.name ,sql_modules.definition from sys.sql_modules sql_modules join sys.objects objects on sql_modules.object_id = objects.object_id where definition like '%some column name%';

我没有发现任何 100.0000% 准确率 100.000000% 的时间。

于 2010-03-26T19:43:03.437 回答
1

如果您想更改对象或列的名称,Red Gate Software 的SQL Prompt 5的智能重命名功能将生成一个脚本,该脚本既执行重命名,又更新对其他对象中旧名称的引用。

如果您只是对依赖于列名的内容感兴趣,那么 SQL Prompt 5 还有一个Column Dependencies函数,将鼠标悬停在脚本中的列名上会弹出一个窗口,其中包含引用该列的对象列表。

您可以免费下载 14 天试用版,看看这些功能是否适合您。

Paul Stephenson
SQL Prompt 项目经理
Red Gate Software

于 2010-12-17T15:59:46.603 回答
0

看看这些答案:

刷新用户函数 t-SQL 上的元数据

SQL Server 关系隐藏在存储过程而不是架构中

在 SQL Server 中,如何找到引用列的所有位置?

如何找到所有插入、更新或删除记录的存储过程?

除了动态 SQL 之外,在可能的情况下使用 SCHEMABINDING 并为其他所有内容使用 sp_refreshsqlmodule 和 sql_dependencies 是非常准确的。

于 2010-03-26T20:37:08.993 回答
0

如果您使用 SQL Server

您可以在更改后使用此查询并找到存储过程或视图或...

更改后可能会出错

USE <Your_DataBase_Name>;

SET NOCOUNT ON;

DECLARE @name NVARCHAR(MAX) 
DECLARE @sql NVARCHAR(MAX) 
DECLARE @type CHAR(2)
DECLARE @type_desc NVARCHAR(60)
DECLARE @params NVARCHAR(MAX)

DECLARE @tblInvalid TABLE
(
  [type_desc] NVARCHAR(60) ,
  [name] NVARCHAR(MAX) ,
  [error_number] INT ,
  [error_message] NVARCHAR(MAX) ,
  [type] CHAR(2)
);       

DECLARE testSPs CURSOR FAST_FORWARD
FOR
SELECT  [name] = OBJECT_NAME(SM.[object_id]) ,
        [type] = SO.[type] ,
        SO.[type_desc] ,
        [params] = ( SELECT (
                            SELECT  CONVERT(XML, ( SELECT STUFF(( SELECT
                                                          ', ' + [name]
                                                          + '=NULL' AS [text()]
                                                          FROM
                                                          sys.parameters
                                                          WHERE
                                                          [object_id] = SM.[object_id]
                                                          FOR
                                                          XML
                                                          PATH('')
                                                          ), 1, 1, '')
                                                 ))
                     FOR    XML RAW ,
                                TYPE
                 ).value('/row[1]', 'varchar(max)')
                   )
FROM    sys.sql_modules SM
        JOIN sys.objects SO ON SO.[object_id] = SM.[object_id]
WHERE   SO.[is_ms_shipped] = 0
        AND SO.[type] = 'P'


OPEN testSPs 
FETCH NEXT FROM testSPs INTO @name, @type, @type_desc, @params

WHILE ( @@FETCH_STATUS = 0 ) 
BEGIN
    BEGIN TRY
        SET @sql = 'SET FMTONLY ON; exec ' + @name + ' ' + @params
            + '; SET FMTONLY OFF;'
        --PRINT @sql;      
        EXEC (@sql);
    END TRY
    BEGIN CATCH
        PRINT @type_desc + ', ' + @name + ', Error: '
            + CAST(ERROR_NUMBER() AS VARCHAR) + ', ' + ERROR_MESSAGE();
        INSERT  INTO @tblInvalid
                SELECT  @type_desc ,
                        @name ,
                        ERROR_NUMBER() ,
                        ERROR_MESSAGE() ,
                        @type;
    END CATCH


    FETCH NEXT FROM testSPs INTO @name, @type, @type_desc, @params
END

CLOSE testSPs  
DEALLOCATE testSPs


SELECT  [type_desc] ,
    [name] ,
    [error_number] ,
    [error_message]
FROM    @tblInvalid
ORDER BY CHARINDEX([type], ' U V PK UQ F TR FN TF P SQ ') ,
    [name];
于 2013-09-25T09:02:21.567 回答