更改SQL Server 2008中的标量函数,该函数在表的计算列中引用

时间:2015-06-04 06:57:41

标签: sql-server calculated-columns

我在scalar function中创建了一个SQL Server 2008,而我在几个表中的计算列中也是如此。现在我想在不丢弃表的情况下改变函数。但它引发了一个错误:

  

无法改变&#d ;.boetStatus'因为它被对象引用   '订单'

是否可以改变功能?或者我先删除并创建所有可靠的表,然后更改函数?

这是我的功能:

CREATE FUNCTION [dbo].[GetStatus]
(
    @FromDate datetime,
    @ToDate datetime
)
RETURNS tinyint
AS
BEGIN

    declare @ret tinyint;
    if(@FromDate<=GETDATE() and (@ToDate>=GETDATE() or @ToDate is null))
        set @ret= 1
    else
        set @ret= 0
    return @ret
END

它在表中提到:

CREATE TABLE [dbo].[Order](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [Name] [varchar](200) NOT NULL,
    [EffectiveFromDate] [datetime] NOT NULL,
    [EffectiveToDate] [datetime] NULL,
    [Status]  AS ([dbo].[GetStatus]([EffectiveFromDate],[EffectiveToDate]))
)

2 个答案:

答案 0 :(得分:0)

这是设计的。您应首先删除所有默认值/约束,然后更改您的函数并添加这些约束。无需放弃表格。

但你可以通过以下技巧解决这个问题:

添加将调用实际功能的中间函数; 改变计算列以调用中间函数而不是实际函数。

示例:

CREATE FUNCTION dbo.fnActual ( @p INT )
RETURNS INT
AS
    BEGIN
        RETURN @p + 1
    END
GO


CREATE FUNCTION dbo.fnIntermediate ( @p INT )
RETURNS INT
AS
    BEGIN
        RETURN dbo.fnActual(@p)
    END
GO


CREATE TABLE TestTable(id INT, fn AS dbo.fnIntermediate(id))
GO

插入一些值:

INSERT INTO dbo.TestTable VALUES  ( 1 )

SELECT * FROM dbo.TestTable --selects 2

--throws exception
ALTER FUNCTION dbo.fnIntermediate ( @p INT )
RETURNS INT
AS
    BEGIN
        RETURN dbo.fnActual(@p)
    END
GO


--succseeds
ALTER FUNCTION dbo.fnActual ( @p INT )
RETURNS INT
AS
    BEGIN
        RETURN @p + 2
    END
GO

SELECT * FROM dbo.TestTable --selects 3

答案 1 :(得分:0)

ALTER TABLE [dbo].[Order]
    DROP COLUMN [Status]
GO
ALTER  FUNCTION [dbo].[GetStatus] ...
GO

ALTER TABLE [dbo].[Order]
    ADD [Status]  AS ([dbo].[GetStatus]([EffectiveFromDate],[EffectiveToDate]))
GO

甚至

ALTER TABLE [dbo].[Order]
    DROP COLUMN [Status]
GO
ALTER TABLE [dbo].[Order]
    ADD [Status]  AS CAST(CASE WHEN [EffectiveFromDate] <= GETDATE() AND ([EffectiveToDate] >= GETDATE() OR [EffectiveToDate] IS NULL) THEN 1 ELSE 0 END as tinyint) 
GO