如果將表的列設置爲其公式調用函數的計算列,那麼更改該基礎函數會很麻煩。隨着每一個變化,你必須找到每一個列的公式引用函數,刪除引用,保存表,改變函數,添加一切回來,並再次保存。即使微小的變化也是噩夢。修改計算列引用的SQL函數
您可以告訴SQL Server您不關心函數是否被公式引用,並且繼續前進並更改基礎函數?
附加信息: 計算列不被FK約束持久或引用,因爲它是非確定性的。該功能考慮當前時間。它正在處理記錄是否過期的問題。
如果將表的列設置爲其公式調用函數的計算列,那麼更改該基礎函數會很麻煩。隨着每一個變化,你必須找到每一個列的公式引用函數,刪除引用,保存表,改變函數,添加一切回來,並再次保存。即使微小的變化也是噩夢。修改計算列引用的SQL函數
您可以告訴SQL Server您不關心函數是否被公式引用,並且繼續前進並更改基礎函數?
附加信息: 計算列不被FK約束持久或引用,因爲它是非確定性的。該功能考慮當前時間。它正在處理記錄是否過期的問題。
不,據我所知,你不能這樣做 - 你必須首先刪除引用函數的所有計算列,改變函數,然後重新創建計算列。
也許MS會在SQL Server 2010/2011中爲我們提供「CREATE OR ALTER FUNCTION」命令? :-)
馬克
嗯,我想你不能這樣做。這就是你說的,你先說。 – colithium 2009-02-17 21:23:24
真的嗎?難道你不能從列中刪除約束,然後改變函數,然後重新應用約束? – 2014-12-08 20:17:36
的ALTER的後果可能是巨大的。
您是否爲索引編制了索引?在具有模式綁定的視圖中使用它?堅持嗎?外鍵關係到它?
如果ALTER更改數據類型,NULLability或確定性會怎麼樣?
使用依賴關係更容易停止ALTER FUNCTION,而不是處理如此多的場景。
您可以將列更改爲不計算,並通過TRIGGER進行更新。
或者您可以將表格重命名爲其他內容,刪除計算列,然後創建一個代替原始表格(即使用原始表格名稱)的VIEW,幷包括您需要的「計算」列。
編輯:請注意,這可能會混淆你的INSERT到原始表名稱(現在一個VIEW)。顯然你可以保留舊錶,刪除計算列,並創建一個包含計算列的單獨的VIEW。
我們不得不圍繞Computed Columns足夠多的時間來決定他們比他們獲得更多的麻煩。失敗安全插入(1),嘗試將VIEWs插入到具有計算列的表格中,需要使用SET ARITHABORT等等。
(1)我們已經故障安全刀片,如:
INSERT INTO MyTable的SELECT * FROM MyOtherTable WHERE ...
其目的是失敗,如果一個新列添加一個表,而不是其他。對於計算列,我們必須明確命名所有列,這會使我們失去安全網。
假設表T1與列C1,C2,C3,C4,C5,其中C4是計算列
還假定所述的C4文獻功能OldFunc要由NewFunc
首先更換,移動從所有行的非計算列到一個臨時表
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
很抱歉這麼晚的答案,但它可能有用。
您可以爲每個計算列使用一個虛函數來調用您的實函數。
實施例:
計算列使用以下公式:dbo.link_comp(「123」)
此功能向前參數和調用和返回功能dbo.link(「123」)(真實功能)
這兩個函數只需要使用相同的參數並返回相同的類型。
然後,被鎖定的函數是dbo.link_comp,你仍然可以ALTER dbo.link。
另外,如果你的函數是從其他SQL調用的,你仍然可以使用你的真實函數名dbo.link,虛擬函數dbo.link_comp只適用於計算列。
我知道這對派對晚了,但我今天有這個相同的問題,並沒有找到任何事實上解決了這個問題,所以我趕緊寫了一個。
本質上,它使用該函數創建一個臨時表,爲每個計算列保存列信息,從表中刪除列。然後你更新你的函數,並讓它重新創建所有的列和他們的定義。
如果您必須對定義中的參數進行更改(如我需要),您可以簡單地將該部分編寫到定義的創建位置。
如果您在索引或其他需求中計算了列,則可以輕鬆地在代碼上進行擴展,但這超出了我的需求範圍。
希望它對其他人有用。
/* 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
我同意這是一個很大的痛苦!現在感覺它! – 2009-11-26 21:29:58
我遇到同樣的問題。我認爲MS SQL不允許它有一個很好的理由,但它仍然是一個真正的痛苦(共同的悲傷+1) – 2012-12-05 12:31:37