web-dev-qa-db-ja.com

今日の日付を取得するための確定関数

次のコードを使用してインデックス付きビューを作成しようとしています(それをテーブルとしてレプリケーションにパブリッシュできるように)。

_CREATE VIEW lc.vw_dates
WITH SCHEMABINDING
AS

SELECT DATEADD(day, DATEDIFF(day, 0, GETDATE()), number) AS SettingDate
FROM lc.numbers
WHERE number<8

GO

CREATE UNIQUE CLUSTERED INDEX
idx_LCDates ON lc.vw_dates(SettingDate)
_

lc.numbersは、1列(number)を1行100ずつ増やしたテーブルです。

ただし、エラーが発生し続けます。

ビュー 'lc.vw_dates'の列 'SettingDate'は、非決定的であるため、インデックスまたは統計で、またはパーティションキーとして使用できません。

GETDATE()は非決定的であることを理解しています。しかし、カレンダーテーブルを描画せずにこれを機能させる方法はありますか?

4
bbailes

関数の出力は時々刻々と変化するため、永続ビューの関数として関数GETDATE()を使用することはできません。これは、SQL Serverがエラーで「非決定的であるため」という意味です。関数の結果は、SQL Serverが結果を保持するために、呼び出されるたびに予測可能に同じでなければなりません。

幸い、スケジュールされたジョブを使用して、このデータを1日に1回保持する簡単な方法があります。おそらく、SQL Serverエージェント、またはWindowsジョブスケジューラなどを使用しています。

ここでは、数値テーブルと、次の7日間を保持するテーブルを作成しています。

CREATE TABLE dbo.Numbers
(
    Number INT NOT NULL
        CONSTRAINT PK_Numbers
        PRIMARY KEY CLUSTERED
);

;WITH cte AS
(
    SELECT TOP(100) Number = ROW_NUMBER() OVER (ORDER BY t1.num, t2.num)
    FROM (VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10)) t1(num)
        , (VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10)) t2(num)
    ORDER BY t1.num * t2.num
)
INSERT INTO dbo.Numbers (Number)
SELECT cte.Number
FROM cte;

CREATE TABLE dbo.Next7Days
(
    SettingDate DATETIME NOT NULL
        CONSTRAINT PK_Next8Days
        PRIMARY KEY CLUSTERED
);

これを1日に1回発生するようにスケジュールします。

TRUNCATE TABLE dbo.Next7Days;

INSERT INTO dbo.Next7Days(SettingDate)
SELECT SettingDate = DATEADD(DAY, n.Number, DATEDIFF(DAY, 0, GETDATE()))
FROM dbo.Numbers n
WHERE n.Number < 8;

次の7日間の日付は1日に1回しか変更されないため、このソリューションは適切に機能するはずです。

dbo.Next7Daysテーブルには、上記のコードを実行した後の次のものが含まれています。

enter image description here

4
Max Vernon