如何在更新依赖项时重新编译SQL Server中的用户定义函数?

时间:2017-07-03 21:26:14

标签: sql sql-server sql-server-2016

我有一个表值函数A,它调用表值函数B和C.函数B和C作为迁移的一部分被更新(更改),但是表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

先谢谢你的帮助。

1 个答案:

答案 0 :(得分:2)

这是使用p2的结果以及执行TVF早期架构绑定的结果。

您可以通过运行获得所需的结果:

SELECT *

有效地将架构重新绑定到TVF,没有sp_refreshsqlmodule <tvf-name> 的详细程度

但从长远来看,请尽量避免使用ALTER x...

相关问题