【问题标题】:Alter scalar function in SQL server 2008 that referring in the computed column of a table更改 SQL Server 2008 中在表的计算列中引用的标量函数
【发布时间】: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]))
)

【问题讨论】:

    标签: sql-server calculated-columns


    【解决方案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
      

      【讨论】:

        猜你喜欢
        • 2022-01-11
        • 2010-10-07
        • 1970-01-01
        • 2012-04-09
        • 1970-01-01
        • 2023-04-08
        • 1970-01-01
        相关资源
        最近更新 更多