如何在更新依赖项时在 SQL 服务器中重新编译用户定义的函数?
How to recompile a user defined function in SQL Server when a dependency is updated?
我有一个 table 值函数 A,它调用 table 值函数 B 和 C。函数 B 和 C 作为迁移的一部分正在更新(更改)但是 table A 不会因此而更新。如何在不改变 A 的情况下重建它?
示例(回滚只是为了方便)SQL Fiddle:
BEGIN TRANSACTION
SET NOCOUNT ON;
CREATE TABLE DOGS
(
Id UNIQUEIDENTIFIER PRIMARY KEY,
Name NVARCHAR(255) NOT NULL,
Age INT NOT NULL,
)
INSERT INTO DOGS VALUES (NEWID(), 'Rocky', 12);
INSERT INTO DOGS VALUES (NEWID(), 'Sammy', 2);
INSERT INTO DOGS VALUES (NEWID(), 'Porthos', 5);
CREATE TABLE CATS
(
Id UNIQUEIDENTIFIER PRIMARY KEY,
Name NVARCHAR(255) NOT NULL,
Age INT NOT NULL,
)
INSERT INTO CATS VALUES (NEWID(), 'Mr. T', 15);
INSERT INTO CATS VALUES (NEWID(), 'Old Timer', 37);
INSERT INTO CATS VALUES (NEWID(), 'Mittens', 1);
SET NOCOUNT OFF;
GO
CREATE FUNCTION [GetCatsYoungerThan]
(
@age INT
)
RETURNS TABLE AS
RETURN (
SELECT Name FROM CATS WHERE Age < @age
);
GO
CREATE FUNCTION [GetDogsYoungerThan]
(
@age INT
)
RETURNS TABLE AS
RETURN (
SELECT Name FROM DOGS WHERE Age < @age
);
GO
CREATE FUNCTION [GetAnimalsYoungerThan]
(
@age INT
)
RETURNS TABLE AS
RETURN (
SELECT * FROM [GetCatsYoungerThan](@age)
UNION
SELECT * FROM [GetDogsYoungerThan](@age)
);
GO
ALTER FUNCTION [dbo].[GetDogsYoungerThan]
(
@age INT
)
RETURNS TABLE AS
RETURN (
SELECT Name, Age FROM DOGS WHERE Age < @age
);
GO
ALTER FUNCTION [dbo].[GetCatsYoungerThan]
(
@age INT
)
RETURNS TABLE AS
RETURN (
SELECT Name, Age FROM CATS WHERE Age < @age
);
GO
EXEC sp_recompile '[GetAnimalsYoungerThan]';
--results
SELECT * FROM [GetAnimalsYoungerThan](15);
--Shows expected results
SELECT * FROM [GetCatsYoungerThan](15)
UNION
SELECT * FROM [GetDogsYoungerThan](15)
ROLLBACK TRANSACTION
结果:
Name
-------
Mittens
Porthos
Rocky
Sammy
预期结果:
Name Age
-----------
Mittens 1
Porthos 5
Rocky 12
Sammy 2
我的预期是 sp_recompile
会导致函数被重新编译;但是,这要么没有发生,要么不足以更新 A.
的值 return
我最初的计划是使用以下代码重新编译数据库中的所有对象,但这需要 sp_recompile
才能工作。
DECLARE @ObjectName NVARCHAR(MAX);
DECLARE MY_CURSOR CURSOR
LOCAL STATIC READ_ONLY FORWARD_ONLY
FOR
SELECT [ROUTINE_SCHEMA] + '.' + [ROUTINE_NAME] AS [NAME]
FROM information_schema.routines
WHERE [ROUTINE_SCHEMA] = 'my_domain';
OPEN MY_CURSOR
FETCH NEXT FROM MY_CURSOR INTO @ObjectName
WHILE @@FETCH_STATUS = 0
BEGIN
PRINT 'Recompiling ' + @ObjectName + '...';
EXEC sp_recompile @ObjectName;
FETCH NEXT FROM MY_CURSOR INTO @ObjectName;
END
CLOSE MY_CURSOR
DEALLOCATE MY_CURSOR
在此先感谢您的帮助。
这是使用 SELECT *
的结果,也是执行 TVF 早期架构绑定的结果。
您可以通过运行宁得到想要的结果:
sp_refreshsqlmodule <tvf-name>
这有效地将模式重新绑定到 TVF,而没有 ALTER x...
的冗长
但在长运行中,尽量避免使用SELECT *
。
我有一个 table 值函数 A,它调用 table 值函数 B 和 C。函数 B 和 C 作为迁移的一部分正在更新(更改)但是 table A 不会因此而更新。如何在不改变 A 的情况下重建它?
示例(回滚只是为了方便)SQL Fiddle:
BEGIN TRANSACTION
SET NOCOUNT ON;
CREATE TABLE DOGS
(
Id UNIQUEIDENTIFIER PRIMARY KEY,
Name NVARCHAR(255) NOT NULL,
Age INT NOT NULL,
)
INSERT INTO DOGS VALUES (NEWID(), 'Rocky', 12);
INSERT INTO DOGS VALUES (NEWID(), 'Sammy', 2);
INSERT INTO DOGS VALUES (NEWID(), 'Porthos', 5);
CREATE TABLE CATS
(
Id UNIQUEIDENTIFIER PRIMARY KEY,
Name NVARCHAR(255) NOT NULL,
Age INT NOT NULL,
)
INSERT INTO CATS VALUES (NEWID(), 'Mr. T', 15);
INSERT INTO CATS VALUES (NEWID(), 'Old Timer', 37);
INSERT INTO CATS VALUES (NEWID(), 'Mittens', 1);
SET NOCOUNT OFF;
GO
CREATE FUNCTION [GetCatsYoungerThan]
(
@age INT
)
RETURNS TABLE AS
RETURN (
SELECT Name FROM CATS WHERE Age < @age
);
GO
CREATE FUNCTION [GetDogsYoungerThan]
(
@age INT
)
RETURNS TABLE AS
RETURN (
SELECT Name FROM DOGS WHERE Age < @age
);
GO
CREATE FUNCTION [GetAnimalsYoungerThan]
(
@age INT
)
RETURNS TABLE AS
RETURN (
SELECT * FROM [GetCatsYoungerThan](@age)
UNION
SELECT * FROM [GetDogsYoungerThan](@age)
);
GO
ALTER FUNCTION [dbo].[GetDogsYoungerThan]
(
@age INT
)
RETURNS TABLE AS
RETURN (
SELECT Name, Age FROM DOGS WHERE Age < @age
);
GO
ALTER FUNCTION [dbo].[GetCatsYoungerThan]
(
@age INT
)
RETURNS TABLE AS
RETURN (
SELECT Name, Age FROM CATS WHERE Age < @age
);
GO
EXEC sp_recompile '[GetAnimalsYoungerThan]';
--results
SELECT * FROM [GetAnimalsYoungerThan](15);
--Shows expected results
SELECT * FROM [GetCatsYoungerThan](15)
UNION
SELECT * FROM [GetDogsYoungerThan](15)
ROLLBACK TRANSACTION
结果:
Name
-------
Mittens
Porthos
Rocky
Sammy
预期结果:
Name Age
-----------
Mittens 1
Porthos 5
Rocky 12
Sammy 2
我的预期是 sp_recompile
会导致函数被重新编译;但是,这要么没有发生,要么不足以更新 A.
我最初的计划是使用以下代码重新编译数据库中的所有对象,但这需要 sp_recompile
才能工作。
DECLARE @ObjectName NVARCHAR(MAX);
DECLARE MY_CURSOR CURSOR
LOCAL STATIC READ_ONLY FORWARD_ONLY
FOR
SELECT [ROUTINE_SCHEMA] + '.' + [ROUTINE_NAME] AS [NAME]
FROM information_schema.routines
WHERE [ROUTINE_SCHEMA] = 'my_domain';
OPEN MY_CURSOR
FETCH NEXT FROM MY_CURSOR INTO @ObjectName
WHILE @@FETCH_STATUS = 0
BEGIN
PRINT 'Recompiling ' + @ObjectName + '...';
EXEC sp_recompile @ObjectName;
FETCH NEXT FROM MY_CURSOR INTO @ObjectName;
END
CLOSE MY_CURSOR
DEALLOCATE MY_CURSOR
在此先感谢您的帮助。
这是使用 SELECT *
的结果,也是执行 TVF 早期架构绑定的结果。
您可以通过运行宁得到想要的结果:
sp_refreshsqlmodule <tvf-name>
这有效地将模式重新绑定到 TVF,而没有 ALTER x...
但在长运行中,尽量避免使用SELECT *
。