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

Posted

技术标签:

【中文标题】更改 SQL Server 2008 中在表的计算列中引用的标量函数【英文标题】:Alter scalar function in SQL server 2008 that referring in the computed column of a table 【发布时间】:2015-06-04 06:57:41 【问题描述】:

我在SQL Server 2008 中创建了一个scalar function,我在几个表的计算列中引用了同样的内容。现在我想在不删除表格的情况下更改函数。但是它会抛出一个错误:

不能 ALTER 'dbo.GetStatus' 因为它被对象引用 '订单'。

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

这是我的功能:

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]))
)

【问题讨论】:

【参考方案1】:

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

但您可以通过以下技巧解决此问题:

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

例子:

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

【讨论】:

【参考方案2】:
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

【讨论】:

以上是关于更改 SQL Server 2008 中在表的计算列中引用的标量函数的主要内容,如果未能解决你的问题,请参考以下文章

oracle 中在添加分区中如果要在表的开始或中间的位置添加分区,怎么使用split语句,帮忙举个例子谢谢

sql server 2008不用查询语句怎样查看新建的表的信息?像2000中的企业管理器中有个返回所有列一样

SQL Server 为啥我必须在表更改后刷新视图

sqlserver 2008问题!

为啥C#中数据库sql语句中在表的前面加上.dbo,不加也能正常执行,两者有啥区别!

从 SQL Server 2005 迁移到 SQL Server 2008:强制在表名之前使用架构名