9

テーブルの列を、式が関数を呼び出す計算列になるように設定すると、その基になる関数を変更するのが面倒になります。変更するたびに、関数を参照する数式を持つすべての列を見つけ、参照を削除し、テーブルを保存し、関数を変更し、すべてを元に戻して、再度保存する必要があります。小さな変化でさえ悪夢です。

関数が数式によって参照されていることを気にせず、基になる関数を変更するだけでよいことを SQL Server に伝えることができますか?

追加の詳細: 計算列は非決定的であるため、FK 制約によって永続化または参照されません。この関数は、現在の時刻を考慮します。レコードの有効期限が切れているかどうかの問題を扱っています。

4

7 に答える 7

6

いいえ、私の知る限り、これを行うことはできません。最初に、関数を参照するすべての計算列を削除し、関数を変更してから、計算列を再作成する必要があります。

おそらく、MS は SQL Server 2010/2011 で「CREATE OR ALTER FUNCTION」コマンドを発行するのでしょうか? :-)

マルク

于 2009-02-12T22:12:42.207 に答える
3

この遅い回答で申し訳ありませんが、役に立つ場合があります。

実際の関数を呼び出す計算列ごとにダミー関数を使用できます。

例:
計算列は次の式を使用します: dbo.link_comp('123')
この関数は引数と呼び出しを転送し、関数 dbo.link('123') を返します (実際の関数)
両方の関数が同じ引数を使用する必要があるだけです同じ型を返します。

次に、ロックされている関数は dbo.link_comp であり、dbo.link を変更できます。
また、関数が他の SQL から呼び出された場合でも、実際の関数名 dbo.link を使用できます。ダミー関数 dbo.link_comp は計算列専用です。

于 2015-01-07T20:19:46.703 に答える
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
于 2011-04-28T14:07:40.610 に答える
1

これがパーティーに遅れていることは知っていますが、今日同じ問題を抱えていて、実際に問題を解決するものは何も見つからなかったので、すぐにスクリプトを作成しました。

基本的に、関数を使用して各計算列の列情報を保持する一時テーブルを作成し、テーブルから列を削除します。次に、関数を更新し、定義を使用してすべての列を再作成します。

定義内のパラメーターに変更を加える必要がある場合 (私の場合のように)、定義が再度作成される場所にその部分を単純にスクリプト化することができます。

インデックスまたはその他のニーズ内に計算列がある場合は、コードを簡単に拡張できますが、これは私のニーズの範囲を超えていました。

それが他の誰かに役立つことを願っています。

/* 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
于 2015-06-23T09:52:01.913 に答える
0

スクリプトを作成する優れたスキーマ比較ツールを試すことができます:)

于 2009-02-13T16:41:22.760 に答える
0

列を非計算に変更し、TRIGGER で更新できます。

または、テーブルの名前を別の名前に変更し、計算列を削除して、元のテーブルの代わりに (元のテーブル名で) VIEW を作成し、必要な "計算" 列を含めることもできます。

編集:これにより、元のテーブル名(現在はビュー)へのINSERTが混乱する可能性があることに注意してください。明らかに、古いテーブルを保持し、計算列を削除して、計算列を含む別の VIEW を作成できます。

計算列が得られるよりも問題が大きいと判断するのに十分な回数、計算列を回避する必要がありました。フェイルセーフ挿入 (1)、計算列を含むテーブルの VIEW に挿入しようとすること、SET ARITHABORT をいじる必要があることなど。

(1) 次のようなフェイルセーフ インサートがあります。

INSERT INTO MyTable SELECT * FROM MyOtherTable WHERE ...

これは、新しい列が一方のテーブルに追加され、もう一方のテーブルには追加されない場合に失敗するように設計されています。計算列では、すべての列に明示的に名前を付ける必要があり、セーフティ ネットが失われます。

于 2009-02-16T07:23:33.267 に答える