web-dev-qa-db-ja.com

計算列を永続化できません-決定論的ではありません

私は計算列に対してこの関数を持っています:

_CREATE FUNCTION [dbo].[GetAllocatedStartTime](@Year INT, @Week INT)
RETURNS DATETIME

WITH schemabinding
AS BEGIN
    RETURN dateadd(week,@Week-(1),dateadd(day,(-1),dateadd(week,datediff(week,(0),CONVERT([varchar](4),@Year,(0))+'-01-01'),(1))))
END

GO
_

_WITH schemabinding_を追加して、それが決定論的になり、永続化できるようになることを期待しています。 2つの入力_[Week]_と_[Year]_は常に同じ結果を生成するためです。

正確なエラーは次のとおりです。

テーブル 'Tmp_Bookings'の計算列 'AllocatedTimeStart'は、列が非決定論的であるため、永続化できません。

私はこの式を列で使用しています:

_([dbo].[GetAllocatedStartTime]([Year],[Week]))
_

そして、列の定義:

_[Week] [int] NOT NULL,
[Year] [int] NOT NULL,
[AllocatedTimeStart]  AS ([dbo].[GetAllocatedStartTime]([Year],[Week])),
_

何か案は?

編集:

行を:に変更しました

_RETURN dateadd(week,@Week-(1),dateadd(day,(-1),dateadd(week,datediff(week,(0),CONVERT(datetime,CONVERT([varchar](4),@Year,(0))+'0101',112)),(1))))
_

しかし、列の数式が無効であるというエラーが表示されます。関数はうまく保存されますが。

編集2:

私は自分がしていることを正確に示しました(または少なくとも私が試したことはあります)。特別なことは何もありません。列内の式ref[dbo].AllocatedStartDate(...)と結合された前の関数(元の関数)は機能しましたが、持続していなかったため、非決定論的であると述べました。したがって、提案に従って、関数を変更し、変換部分を新しいコードに置き換えたので、関数は次のようになります。

_FUNCTION [dbo].[GetSTime](@Year INT, @Week INT)

RETURNS DATETIME
WITH schemabinding
AS BEGIN
    RETURN dateadd(week,@Week-(1),dateadd(day,(-1),dateadd(week,datediff(week,(0),CONVERT(datetime,CONVERT([varchar](4),@Year,(0))+'0101',112)),(1))))
END
_

次に、計算フィールド_(([dbo].[GetAllocatedStartTime]([Year],[Week])))_で以前と同じ数式を試しましたが、数式が拒否され、無効であると表示されます...数式が同じであるため奇妙なため、何らかの処理を行う必要があります変更された関数をチェックし、それが無効であることがわかったのですが、これも、単純なSELECT dbo.GetAllocatedStartTime(2012,13)を実行して機能したため、奇妙です。

そうです、私は混乱していて、SqlFiddleがそれを使用してもかまわないのを見たことがありません。しかし、実際には私が今言ったこと以上のものはありません。

13
sprocket12

CONVERT([varchar](4),@Year,(0))+'-01-01'DATEDIFF呼び出しに渡され、日付が予想される位置で、暗黙的な変換が強制的に発生します。

決定論的関数 のルールから:

CAST

datetimesmalldatetime、または_sql_variant_と一緒に使用しない限り、決定論的です。

CONVERT

これらの条件のいずれかが存在しない限り、決定論的です。

.。

ソースまたはターゲットのタイプはdatetimeまたはsmalldatetimeであり、他のソースまたはターゲットのタイプは文字列であり、非決定的なスタイルが指定されています。決定論的であるためには、スタイルパラメータは定数でなければなりません。さらに、100以下のスタイルは、スタイル20および21を除いて、非決定論的です。100を超えるスタイルは、スタイル106、107、109、および113を除いて決定論的です。

どちらも呼び出していませんが、暗黙の変換に依存しています。これは、CASTのように動作すると予想されます。これに依存するのではなく、CONVERTの使用に切り替えて、決定論的なスタイルパラメーターを指定します。

だから、私はそうします:代わりにCONVERT(datetime,CONVERT([varchar](4),@Year,(0))+'0101',112)。そうすると、関数自体が決定論的になります

19