如何在更新依赖项时在 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 *