我是大型开发团队的最后一名成员,负责将大型现有系统移交给新团队。作为迁移的一部分,ID 列将被添加到数据库中的每个表中(即使该表已经有一个)。问题是在数百个存储过程中,一些旧的 INSERTS 没有命名列:
INSERT INTO tablename VALUES (blah, blah, blah)
当然,这些会随着添加的新列而中断,因为表中的列数与 INSERT
中的列数不匹配。我需要更改所有 INSERT
。
没问题,除了我首先需要找到它们。此查询返回超过 900 个结果和太多误报(因为它返回命名列和未命名列的 INSERT
):
SELECT OBJECT_NAME(object_id)
FROM sys.sql_modules
WHERE definition LIKE '%insert into%'
AND OBJECT_NAME(object_id) NOT LIKE 'MSmerge%'
ORDER BY OBJECT_NAME(object_id)
这个返回了一个不错的小数字,但错过了一些我知道是不好的:
SELECT OBJECT_NAME(object_id)
FROM sys.sql_modules
WHERE definition LIKE '%insert into%'
AND definition NOT LIKE '%) value%'
AND definition NOT LIKE '%)%' + CHAR(10) + '%value%'
AND definition NOT LIKE '%)%' + CHAR(13) + '%value%'
AND definition LIKE '%value%'
AND OBJECT_NAME(object_id) NOT LIKE 'MSmerge%'
这是上次查询错过的存储过程的一部分:
BEGIN
IF @someFlag = 1
INSERT INTO tablename VALUES (@myCode, @myYear, @myMonth, 1, 1, 0)
ELSE
INSERT INTO tablename VALUES (@myCode, @myYear, @myMonth, 1, 0, 1)
END
有没有办法可靠地找到我需要修复的存储过程?
最佳答案
对于本例sp_refreshsqlmodule
非常有用。它不仅按照文档所述更新元数据,而且还进行大量检查。它可以检测 View 、存储过程、触发器和函数中的大量错误。
以下存储过程在数据库中的所有 SQL 模块上调用 sp_refreshsqlmodule
并打印出它发现的所有错误:
CREATE PROCEDURE [dbo].[RefreshAllModules]
AS
DECLARE m CURSOR FOR
SELECT '[' + s.name + ']' + '.[' + o.name + ']' AS name, o.type_desc
FROM
sys.sql_modules m
INNER JOIN sys.objects o
on m.object_id = o.object_id
INNER JOIN sys.schemas s
on o.schema_id = s.schema_id
WHERE
m.is_schema_bound = 0
OPEN m
DECLARE @name sysname, @type_desc sysname
FETCH NEXT FROM m into @name, @type_desc
WHILE @@FETCH_STATUS = 0
BEGIN
BEGIN TRY
EXEC sp_refreshsqlmodule @name
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0 ROLLBACK
PRINT ERROR_MESSAGE()
PRINT @type_desc + ': ' + @name
PRINT ''
END CATCH
FETCH NEXT FROM m INTO @name, @type_desc
END
CLOSE m
DEALLOCATE m
GO
例如,假设您有下表和存储过程:
CREATE TABLE T
(
name varchar(50) NOT NULL
)
GO
CREATE PROCEDURE p
AS
INSERT INTO T VALUES ('John Doe')
GO
稍后,您更改表格:
ALTER TABLE t ADD id int;
现在,存储过程无效。但您可以检测到它正在执行 RefreshAllModules
:
EXEC RefreshAllModules
哪些输出:
Column name or number of supplied values does not match table definition. SQL_STORED_PROCEDURE: [dbo].[p]
关于SQL 查询查找未命名列的 INSERT 存储过程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49241339/