私はテーブル値関数BとCを呼び出すテーブル値関数Aを持っています。関数BとCは、移行の一環として更新(変更)されていますが、テーブルAは更新されません。 Aを変更せずにAを再構築するにはどうすればよいですか?依存関係が更新されたときにSQL Serverでユーザー定義関数を再コンパイルする方法はありますか?
例(ロールバックがちょうど便宜のために追加されます)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) 'SELECT *'が悪魔であり、2)本当に 'WITH SCHEMABINDING'が必要な理由を示しています。確かに、今あなたは迷惑なエラーを得るが、少なくとも物事は静かに失敗しない。 –