Sql server 有没有办法让SQL server验证存储过程中的对象引用?
以下代码在SQL Server中执行良好Sql server 有没有办法让SQL server验证存储过程中的对象引用?,sql-server,stored-procedures,typechecking,Sql Server,Stored Procedures,Typechecking,以下代码在SQL Server中执行良好 create proc IamBrokenAndDontKnowIt as select * from tablewhichdoesnotexist 当然,如果我尝试运行它,它会失败 无效的对象名称“tablewhichdoesnotexist” 有没有办法编译或验证存储的进程是否有效?您可以运行sp\u dependens(请参阅),并使用该信息查询信息架构(),查看是否存在所有对象。根据我在这里读到的()内容,您只需要检查引用的表,这是可行的。您可
create proc IamBrokenAndDontKnowIt as
select * from tablewhichdoesnotexist
当然,如果我尝试运行它,它会失败
无效的对象名称“tablewhichdoesnotexist”
有没有办法编译或验证存储的进程是否有效?您可以运行
sp\u dependens
(请参阅),并使用该信息查询信息架构(),查看是否存在所有对象。根据我在这里读到的()内容,您只需要检查引用的表,这是可行的。您可以使用
SET FMTONLY ON
EXEC dbo.My_Proc
SET FMTONLY OFF
您将需要以某种方式捕获错误,但是不需要花费太多时间就可以构建一个快速实用程序应用程序,利用它查找无效的存储过程
我还没有广泛使用过它,所以我不知道是否有任何副作用需要注意。当您尝试创建这样的存储过程时,通常会收到一条警告消息。它会说: 无法向当前存储过程的sysdepends添加行,因为它依赖于缺少的对象“dbo.nonexistenttable”。存储过程仍将被创建 由于某些原因,我现在无法理解它,我不确定它是否已被更改,或者是否只有一些设置可以打开或关闭警告。不管怎样,这应该给你一个提示,这里发生了什么 SQL Server确实跟踪依赖项,但只跟踪实际存在的依赖项。不幸的是,像
sp_dependences
或sp_msdependences
这样的依赖技巧在这里都不起作用,因为您正在查找缺少的依赖项
即使我们可以假设找到一种方法来检查这些缺失的依赖项,但捏造一些东西来破坏检查仍然是微不足道的:
CREATE PROCEDURE usp_Broken
AS
DECLARE @sql nvarchar(4000)
SET @sql = N'SELECT * FROM NonExistentTable'
EXEC sp_executesql @sql
您也可以尝试解析“FROM xxx”之类的表达式,但也很容易克服这一点:
CREATE PROCEDURE usp_Broken2
AS
SELECT *
FROM
NonExistentTable
在不实际运行存储过程的情况下,确实没有任何可靠的方法来检查存储过程并检查缺少的依赖项
如Tom H所述,您可以使用SET FMTONLY ON
,但请注意,这会改变过程“运行”的方式。它抓不到一些东西。例如,没有什么可以阻止您编写这样的过程:
CREATE PROCEDURE usp_Broken3
AS
DECLARE @TableName sysname
SELECT @TableName = Name
FROM SomeTable
WHERE ID = 1
DECLARE @sql nvarchar(4000)
SET @sql = N'SELECT * FROM ' + @TableName
EXEC sp_executesql @sql
假设您有一个名为SomeTable
的实表和一个ID=1的实行,但其名称不引用任何表。如果将其包装在SET FMTONLY ON/OFF
块中,则不会产生任何错误
这可能是人为造成的问题,但是FMTONLY ON
会执行其他奇怪的操作,比如执行IF
/然后
/ELSE
块的每个分支,这可能会导致其他意外错误,因此您必须非常具体地处理错误
测试过程唯一真正可靠的方法是实际运行它,如下所示:
BEGIN TRAN
BEGIN TRY
EXEC usp_Broken
END TRY
BEGIN CATCH
PRINT 'Error'
END CATCH
ROLLBACK
此脚本将在事务中运行该过程,对错误(在捕获
中)采取一些操作,并立即回滚事务。当然,即使这样做也可能有一些副作用,例如,如果将标识种子插入到表中(成功),则会更改该种子。只是一些需要注意的事情
老实说,我不会用一根50英尺长的杆子碰这个问题。不会(但请继续阅读,请参阅最后一行)
它的设计是:
为设置严格的检查
连接请求有一个(不是我自己尝试的):
使用检查执行计划。唯一的
缺点是你可能需要
查看执行计划的权限
首先
您可以检查information_schema.tables以检查表是否存在,然后执行代码
这里是快速悬挂功能检查
create function fnTableExist(@TableName varchar(64)) returns int as
begin
return (select count(*) from information_schema.tables where table_name=@tableName and Table_type='Base_Table')
end
go
if dbo.fnTableExist('eObjects') = 0
print 'Table exist'
else
print 'no suchTable'
像wise一样,您可以在中检查存储的进程/函数是否存在
.INFORMATION\u SCHEMA.ROUTINES.Routine\u存储过程/函数的名称在SQL 2005或更高版本中,您可以使用事务和try/catch测试存储过程:
BEGIN TRANSACTION
BEGIN TRY
EXEC (@storedproc)
ROLLBACK TRANSACTION
END TRY
BEGIN CATCH
WHILE @@TRANCOUNT > 0
ROLLBACK
END CATCH
测试数据库中所有存储过程的算法要复杂一些,因为如果有许多SP返回许多结果集,则需要绕过SSMS限制。请参阅我的。我刚刚发现带有数据库项目的VS2010将执行语法和名称引用检查。似乎是最好的选择。我认为sp_depend只适用于实际存在的对象。在我的服务器上进行的快速测试表明,当我引用无效表时,没有报告任何依赖项。Tom H.谢谢。我想我应该测试一下,而不是假设一下。对不起,我说的是青鱼。它将返回空结果集,并且不会运行任何更新/插入等。我也只是在DDL(DROP TABLE)上运行了一个快速测试,并使用了动态SQL,但这两个测试都没有运行。UPDATE语句刚刚返回了受影响的0行计数。a好的,只有当一个sp调用另一个(尚未存在)sp时,才会收到警告。我从未在不存在表或视图的情况下看到过此警告。