2013-01-02 26 views
12

Ho questa funzione per una colonna calcolata:non possono persistere calcolata colonna - non deterministico

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 

ho aggiunto il WITH schemabinding nella speranza che renderebbe deterministica modo che io possa persistere esso. Dovrebbe essere come i due ingressi [Week] e [Year] restituiranno sempre gli stessi risultati.

L'errore esatto è:

colonna calcolata 'AllocatedTimeStart' nella tabella 'Tmp_Bookings' non può essere persistente perché la colonna è non-deterministico.

sto usando questa formula nella colonna:

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

E i defs colonne:

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

Tutte le idee?

EDIT:

linea cambiato in:

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

Ma ora ottengo un errore che dice la formula per la colonna non è valido. Anche se la funzione salva correttamente.

EDIT 2:

ho mostrato esattamente quello che sto facendo (o almeno ho provato). Non c'è niente in più. Come dice la funzione precedente (quella originale) accoppiata con la formula ref [dbo].AllocatedStartDate(...) ad essa nella colonna funzionava, ma non persisteva, diceva che non era deterministica. Quindi, secondo il suggerimento ho cambiato FUNCTION, sostituendo la parte conversione con il nuovo codice, per cui la funzione ora assomiglia:

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 

Poi provai la stessa formula di prima nel campo calcolato (([dbo].[GetAllocatedStartTime]([Year],[Week]))) ... e rifiuta la formula, dice che non è valida ... il che è strano dato che la formula è la stessa, quindi deve fare una sorta di controllo della funzione modificata e scoprire che non è valido, il che è anche strano perché ho fatto un semplice SELECT dbo.GetAllocatedStartTime(2012,13) e ha funzionato ...

Quindi sì, sono confuso, e non ho mai visto SqlFiddle non importa usarlo. Ma in realtà non c'è niente di più di quello che ho appena detto.

+1

Il problema non è con la tua funzione, è con la colonna calcolata sul tuo tavolo. Pubblica questa definizione sulla tua domanda in modo che possiamo aiutarti. – Lamak

+0

Per quale versione di SQL-Server è? –

+0

@ypercube 2008 R2 – sprocket12

risposta

16

CONVERT([varchar](4),@Year,(0))+'-01-01' sta passando ad una chiamata DATEDIFF, in una posizione in cui è prevista una data, forzando una conversione implicita a verificarsi.

Dalle regole per deterministic functions:

CAST

deterministica a meno utilizzato con datetime, smalldatetime o sql_variant.

CONVERT

deterministica a meno che una di queste condizioni:

...

Sorgente o destinazione tipo è datetime o smalldatetime, l'altra fonte o tipo di destinazione è una stringa di caratteri, ed un è specificato lo stile non deterministico. Per essere deterministico, il parametro di stile deve essere una costante. Inoltre, gli stili inferiori o uguali a 100 sono non deterministico, fatta eccezione per gli stili 20 e 21. Gli stili superiori a 100 sono deterministici, tranne che per gli stili 106, 107, 109 e 113.

Beh, stai chiamando né , ma stai facendo affidamento su una conversione implicita, che mi aspetto di agire come CAST. Invece di fare affidamento su questo, passerei ad usare CONVERT e dare un parametro di stile deterministico.

Quindi, farei: CONVERT(datetime,CONVERT([varchar](4),@Year,(0))+'0101',112) al suo posto. Fatto ciò, la funzione stessa diventa deterministica

+0

Se su SQL-Server 2012, potrebbero anche usare - invece del 'CONVERT ([varchar] (4), @ Year, (0)) + '- 01-01'' - il' DATEFROMPARTS ([Anno], 1,1) 'function: [SQL-Fiddle test] (http://sqlfiddle.com/#!6/7a872) –

+0

Salve, ho provato a sostituire la parte, ma ho riscontrato un altro problema:/vedere la modifica sopra. – sprocket12