2013-01-02 11 views
12

を:は計算列存続することはできません - 私は計算列のため、この機能を持って決定論的ではない

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]は常に同じ結果が得られるはずです。

正確なエラーである:カラムは非決定的であるため、テーブル内の

計算カラム 'AllocatedTimeStart「Tmp_Bookings」が持続することはできません。

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

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

と列DEFS:

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

任意のアイデア?

EDIT:

変更行に:

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

しかし、今、私は列の式は無効であるというエラーを取得します。この関数はうまく節約されます。

EDIT 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それを使用しないでください。しかし、実際には私が今言ったこと以外は何もありません。

+1

問題は関数ではなく、テーブル上の計算列にあります。その定義をあなたの質問に投稿してください。 – Lamak

+0

これはどのバージョンのSQL-Serverですか? –

+0

@ypercube 2008 R2 – sprocket12

答えて

16

CONVERT([varchar](4),@Year,(0))+'-01-01'は、DATEDIFFコールに、日付が予想される位置に渡されているため、暗黙の変換が行われます。 deterministic functionsためのルールから

CAST

決定的datetimesmalldatetime、またはsql_variantで使用する場合を除きます。

...

ソースまたはターゲットのタイプがdatetimeまたはsmalldatetime、他のソースであるかターゲット型が文字列である、と:

CONVERT

決定的これらの条件のうちの1つが存在しない限り、非決定性スタイルが指定されています。確定的であるためには、styleパラメータは定数でなければなりません。さらに、100以下のスタイルは、スタイル20と21を除いて非決定的です。スタイル106,107,109,113を除き、100を超えるスタイルは決定的です。

しかし、あなたは暗黙の変換に頼っています。これはCASTのように動作すると期待しています。これに頼るのではなく、CONVERTを使用して、決定論的なスタイルパラメータを与えます。

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

+0

SQL Server 2012の場合、CONVERT([varchar](4)、@ Year、(0))+ '01-01' 'の代わりに、DATEFROMPARTS([Year]、 1,1) 'function:[SQL-Fiddle test](http://sqlfiddle.com/#!6/7a872) –

+0

こんにちは、私はその部分を置き換えようとしましたが、別の問題が発生しました。 – sprocket12

関連する問題