如果将表的列设置为其公式调用函数的计算列,则更改该基础函数变得很痛苦。每次更改时,您必须找到每个引用该函数的公式的列,删除引用,保存表,更改函数,添加所有内容,然后重新保存。即使很小的变化也是噩梦。
您能否告诉SQL Server您不关心公式引用函数并继续更改基础函数?
其他细节: 计算列不会被FK约束持久化或引用,因为它是非确定性的。该功能考虑了当前时间。它正在处理记录是否过期的问题。
答案 0 :(得分:5)
不,据我所知,你不能这样做 - 你必须先删除引用函数的所有计算列,改变函数,然后重新创建计算列。
也许MS会在SQL Server 2010/2011中给我们一个“CREATE OR ALTER FUNCTION”命令? : - )
马克
答案 1 :(得分:4)
ALTER的后果可能是巨大的。
您是否已将列编入索引?在架构绑定的视图中使用它?坚持了吗?与它的外键关系?
如果ALTER更改数据类型,可空性或确定性,该怎么办?
使用依赖关系停止ALTER FUNCTION比处理这么多场景更容易。
答案 2 :(得分:3)
很抱歉这个迟到的答案,但它很有用。
您可以为每个计算列使用虚函数来调用您的实际函数。
例:
计算列使用公式:dbo.link_comp('123')
此函数转发参数并调用并返回函数dbo.link('123')(您的实函数)
这两个函数只需要使用相同的参数并返回相同的类型。
然后,锁定的功能是dbo.link_comp,你仍然可以改变dbo.link 此外,如果从其他SQL调用函数,您仍然可以使用实际函数名称dbo.link,虚函数dbo.link_comp仅用于计算列。
答案 3 :(得分:1)
假设表T1具有列C1,C2,C3,C4,C5,其中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
答案 4 :(得分:0)
您可以尝试使用一些好的架构比较工具,为您创建脚本:)
答案 5 :(得分:0)
您可以将列更改为未计算,并通过TRIGGER更新。
或者您可以将表重命名为其他内容,删除计算列,并创建一个VIEW来代替原始表(即使用原始表名)并包含您需要的“计算”列。
编辑:请注意,这可能会使您的INSERT陷入原始表名(现在是VIEW)。显然,你可以保留旧表,删除计算列,并创建一个包含计算列的单独VIEW。
我们不得不在计算列上工作足够多次,以确定他们比他们获得的更麻烦。 Fail-saf插入(1),尝试将VIEW插入到具有计算列的表中,需要使用SET ARITHABORT进行混乱等等。
(1)我们有以下的故障安全插页:
INSERT INTO MyTable SELECT * FROM MyOtherTable WHERE ...
如果新列添加一个表而不是另一个表,则设计为失败。使用Computed Column,我们必须明确命名所有列,这使我们失去了安全网。
答案 6 :(得分:0)
我知道现在已经迟到了,但我今天遇到了同样的问题而且没有找到任何可以解决问题的内容,所以我很快就编写了一个。
本质上,它创建了一个临时表,使用该函数保存每个计算列的列信息,从表中删除列。然后,您可以更新您的函数,并让它再次使用它们的定义重新创建所有列。
如果你必须对定义中的参数进行更改(比如我需要),你可以简单地将该部分编写到再次创建定义的位置。
如果您在索引或其他需求中计算了列,则可以轻松扩展代码,但这超出了我的需求。
希望它对其他人有用。
/* 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