如果将表的列设置为公式调用函数的计算列,则更改基础函数将成为一种痛苦。每次更改,您都必须找到每个列的列,其公式引用该函数,删除参考,保存表,更改功能,添加所有内容,然后再次保存。甚至很小的变化也是噩梦。

您能否告诉SQL Server,您不在乎公式正在引用该功能并继续更改基础功能?

其他详细信息:FK约束不持续或引用计算的列,因为它是非确定性的。该功能考虑当前时间。它正在处理记录是否过期的问题。

有帮助吗?

解决方案

不,据我所知,您不能这样做 - 您必须首先删除所有引用函数的计算列,更改函数,然后重新创建计算的列。

也许MS会在SQL Server 2010/2011中给我们一个“创建或更改函数”命令? :-)

马克

其他提示

Alter的后果可能是巨大的。

您是否索引了列?在带有schemabinding的视图中使用了它?坚持吗?外国钥匙关系吗?

如果Alter更改数据类型,无效或确定性,该怎么办?

与处理如此多的方案相比,使用依赖关系停止函数更容易。

抱歉,这个较晚的答案很有用。

您可以为每个计算的列使用虚拟功能,以调用您的真实功能。

例子:
计算列使用公式:dbo.link_comp('123')
此函数转发参数和调用并返回函数dbo.link('123')(您的实际函数)
这两个功能都只需要使用相同的参数并返回相同的类型。

然后,锁定的功能是dbo.link_comp,您仍然可以更改dbo.link。
另外,如果您的函数是从其他SQL调用的,则仍然可以使用您的真实函数名称dbo.link,虚拟函数dbo.link_comp仅适用于计算列。

假设表T1带有C1,C2,C3,C4,C5的表T1其中C4是计算列

还假设您想由newfunc替换的C4参考功能oldfunc

首先,将未计算的列从所有行移动到临时表

Select C1, C2, C3, C5 into TmpT1 from T1
Go

接下来,从T1删除所有行

Delete From T1
go

现在您可以修改C4列

Alter table T1 alter column C4 as dbo.NewFunc()
Go

现在将保存的数据放回原始表中

Insert Into T1 (C1,C2,C3,C5) select C1,C2,C3,C5 from TmpT1

现在删除临时表

Drop Table TmpT1

您可以尝试使用一些良好的模式比较工具,以为您创建脚本:)

您可以更改未计算的列,并通过触发器更新。

或者,您可以将表重命名为其他东西,丢弃计算的列,并创建一个视图代替原始表(即带有原始表名称),并包括您需要的“计算”列。

编辑:请注意,这可能会使您插入原始表名称(现在是视图)。显然,您可以保留旧表,丢弃计算的列,并创建一个包含计算列的单独视图。

我们不得不围绕计算的列工作,以确定它们比收获更多的麻烦。 Fail-SAF插入(1),试图将视图插入具有计算列的表格上,这些内容需要与Set Arithabort混在一起等。

(1)我们有故障安全插件,例如:

插入Mytable Select *从Myothertable中插入...

如果添加了一个新列,则设计为失败,而不是另一个表。使用计算的列,我们必须明确命名所有列,这使我们失去了安全网。

我知道这对聚会很晚,但是我今天遇到了同样的问题,没有找到真正解决该问题的任何东西,因此我很快就将一个问题拼写出来。

从本质上讲,它创建了一个临时表,使用该函数将每个计算的列的列信息保存,从表中删除列。然后,您更新您的功能,并让其再次重新创建所有列的定义。

如果您必须更改定义中的参数(就像我需要的那样),则可以简单地将该部分脚本脚本脚本到创建定义的位置。

如果您在索引或其他需求中计算了列,则可以轻松地扩展代码,但这超出了我的需求范围。

希望它对别人有用。

/* Create temporary table to hold definitions */
CREATE TABLE [#FUNCTION]
(
    [TABLE_NAME] nvarchar(255) NOT NULL,
    [COLUMN_NAME] nvarchar(255) NOT NULL,
    [DEFINITION] nvarchar(255) NOT NULL
)
GO

/* Add data to temp table */
INSERT INTO [#FUNCTION] ( [TABLE_NAME], [COLUMN_NAME], [DEFINITION] )
SELECT TABLE_NAME, COLUMN_NAME, definition FROM INFORMATION_SCHEMA.COLUMNS
INNER JOIN sys.computed_columns ON ( object_id = object_id( TABLE_NAME ) AND name = COLUMN_NAME )
WHERE definition LIKE '%MyFunctionName%'
GO

/* Remove columns */
DECLARE @TABLE_NAME nvarchar(255)
DECLARE @COLUMN_NAME nvarchar(255)

DECLARE c_CursorName CURSOR LOCAL FOR SELECT [TABLE_NAME], [COLUMN_NAME] FROM [#FUNCTION]
OPEN c_CursorName

FETCH NEXT FROM c_CursorName INTO @TABLE_NAME, @COLUMN_NAME

WHILE @@FETCH_STATUS = 0
BEGIN
    EXEC( 'ALTER TABLE [' + @TABLE_NAME + '] DROP COLUMN [' + @COLUMN_NAME + ']' )

    FETCH NEXT FROM c_CursorName INTO @TABLE_NAME, @COLUMN_NAME
END

CLOSE c_CursorName
DEALLOCATE c_CursorName
GO

/* Update function */
-- Update function here
GO

/* Recreate computed columns */
DECLARE @TABLE_NAME nvarchar(255)
DECLARE @COLUMN_NAME nvarchar(255)
DECLARE @DEFINITION nvarchar(255)

DECLARE c_CursorName CURSOR LOCAL FOR SELECT [TABLE_NAME], [COLUMN_NAME], [DEFINITION] FROM [#FUNCTION]
OPEN c_CursorName

FETCH NEXT FROM c_CursorName INTO @TABLE_NAME, @COLUMN_NAME, @DEFINITION

WHILE @@FETCH_STATUS = 0
BEGIN
    EXEC( 'ALTER TABLE [' + @TABLE_NAME + '] ADD [' + @COLUMN_NAME + '] AS ' + @DEFINITION )

    FETCH NEXT FROM c_CursorName INTO @TABLE_NAME, @COLUMN_NAME, @DEFINITION
END

CLOSE c_CursorName
DEALLOCATE c_CursorName
GO

/* Remove temp table */
DROP TABLE [#FUNCTION]
GO
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top