web-dev-qa-db-ja.com

SQLServerの計算列のベストプラクティス

ユーザーテーブルを使用していて、「試用期間の終了日」を入力したいと思います。基本的に、各新規ユーザーは、試用期間の一部として参加してから2か月があります。ユーザーテーブルの列に数式を入力できることを確認しましたが、代わりにこれを更新するスクリプトが必要なのか、それとも計算列を使用するのに許容できる時間なのか疑問に思っています。私はさまざまな目的でこのテーブルにアクセスし、パフォーマンスのマイルストーンの達成に基づいてユーザーの行を更新することがあります。申請日が変更/更新されることはありません。

私の質問は、この状況で計算列を使用することは良い習慣ですか、それともその行を更新するたびに再計算されますか(アプリの日付を更新するつもりはありませんが)?将来、行を更新するときに、これ以上のオーバーヘッドを作成したくありません。

保護観察終了日の列定義で使用している式:

(dateadd(day,(-1),dateadd(month,(3),dateadd(day,(1)-datepart(day,[APP_DT]),[APP_DT]))))
12
Brian

この日付は、一度設定すると変更されない可能性が高いため、計算列の候補としては適切ではない可能性があります。

結局のところ、そのテーブルに行を挿入すると、その「試用期間の終了」の日付をその場で簡単に計算でき(トリガーなどで)、一度設定すると、その日付は変更されません。

したがって、この方法で確実に実行できますが、1回だけ計算してその日付を格納するAFTER INSERTトリガー(またはINSERT操作のストアドプロシージャ)を使用することをお勧めします。

また、ヘッズアップと同じように、数式だけを含む計算列は、それにアクセスするたびに計算されます。これに注意してください。つまり、PERSISTEDキーワードを指定しない限り、その場合、結果は行の他のデータと一緒に保存されます。この値は一度計算されるため、ここでもはるかに適しています。 、二度と変わることはありません。

15
marc_s

申請日を変更せずに後で誰かの試用期間を延長したい場合は、計算列を使用することはできません。両方の列にDEFAULT制約を使用しないのはなぜですか?

USE tempdb;
GO

CREATE TABLE dbo.foo
(
  MemberID INT IDENTITY(1,1),
  JoinDate DATE NOT NULL DEFAULT SYSDATETIME(),
  ProbationEndDate NOT NULL DEFAULT 
    DATEADD(DAY, -1, DATEADD(MONTH, DATEDIFF(MONTH,0,SYSDATETIME())+3, 0))
);

INSERT dbo.foo DEFAULT VALUES;

SELECT MemberID, JoinDate, ProbationEndDate FROM dbo.foo;

結果:

MemberID    JoinDate      ProbationEndDate
--------    ----------    ----------------
1           2013-04-05    2013-06-30

(2か月間、月末を取得するために、少し混乱の少ないアプローチを使用したことに注意してください。)

11
Aaron Bertrand

データを挿入するときにオーバーヘッドはありません。列を読み取る場合にのみ、この列の値が計算されます。ですから、あなたのアプローチは正しいと思います。

0
Adam Luniewski