我使用此存储过程来验证SQL Server中的所有对象。
此存储过程在当前数据库中存在的每个对象上使用sp_refreshsqlmodule
。除了我重命名表格外,它都能正常工作。
之后,所有使用重命名表的对象都会引发错误,但是下面的过程无法检测到这些错误。
我该如何解决?
DECLARE @NumberRecords INT
DECLARE @RowCount INT
DECLARE @Name NVARCHAR(MAX)
DECLARE @Command NVARCHAR(MAX)
DECLARE @Result int
DECLARE @Names TABLE
(
[RowId] INT NOT NULL IDENTITY(1, 1),
[Name] NVARCHAR(MAX),
[Type] NVARCHAR(MAX)
)
INSERT INTO @Names
SELECT
QUOTENAME(SCHEMA_NAME([Objects].schema_id)) + '.' + QUOTENAME(OBJECT_NAME([Objects].object_id)) [Name],
type_desc [Type]
FROM
sys.objects [Objects]
WHERE
type_desc IN ('SQL_STORED_PROCEDURE',
'SQL_TRIGGER',
'SQL_SCALAR_FUNCTION',
'SQL_TABLE_VALUED_FUNCTION',
'SQL_INLINE_TABLE_VALUED_FUNCTION',
'VIEW')
ORDER BY
[Name]
SET @RowCount = 1
SET @NumberRecords = (SELECT COUNT(*) FROM @Names)
WHILE (@RowCount <= @NumberRecords)
BEGIN
SELECT @Name = [Name]
FROM @Names
WHERE [RowId] = @RowCount
SET @Command = N'EXEC sp_refreshsqlmodule ''' + @Name + ''''
BEGIN TRY
EXEC @Result = sp_executesql @Command
IF @Result <> 0
BEGIN
RAISERROR('Failed', 16, 1)
END
ELSE
BEGIN
DELETE @Names
WHERE [RowId] = @RowCount
END
END TRY
BEGIN CATCH
-- Nothing
END CATCH
SET @RowCount = @RowCount + 1
END
SELECT
[Name], [Type]
FROM @Names
答案 0 :(得分:3)
T-SQL语言有很多奇怪之处。当您创建或更改视图或函数时,如果SQL Server无法找到该定义所依赖的所有表,视图和函数,则SQL Server将不接受您提供的定义。您可以进一步处理这些对象,并指定WITH SCHEMABINDING
以防止在视图/函数仍然存在时更改其从属对象。
对于存储过程,SQL Server将不会抱怨存储过程 1 的定义中缺少表/视图/函数。当过程开始执行时,服务器将根据当前存在的对象编译尽可能多的代码并开始执行。随着执行过程的进行,它可能根据已经存在但在过程开始执行之前不存在的对象重新编译过程的后续部分。这被称为“延迟名称解析”,并且没有退出的选择(我们已经要求了多年)。
对于编写依赖于例如临时表。但这意味着没有机制可以提前验证存储过程所引用的所有对象确实存在。
1 它会验证定义在语法上是否有效。
答案 1 :(得分:1)
高兴,我有一个解决方案:
while read sign; do