2012-08-10 8 views
5

sto facendo un SELECT che utilizza CASE per convertire i valori nvarchar in un tipo corretto, qualcosa di simile:caso allora clausola sempre valutata

SELECT CASE 
    WHEN @propType = 'money' THEN convert(money, datavalue) 
    [...] 
    ELSE datavalue 
END 
FROM [...] 

Tuttavia, sembra che il convert viene sempre eseguito, anche quando @propType è non uguale al denaro. Esempio eseguibile:

declare @proptype nvarchar(50)= 'nvarchar' 
declare @val nvarchar(10) = 'test' 
select 
    case @proptype 
     when 'money' then convert(money, @val) 
     else @val 
    end 

Perché è questo e come posso aggirarlo? La documentazione MSDN dice:

L'istruzione CASE valuta le sue condizioni in sequenza e si ferma con la prima condizione la cui condizione è soddisfatta. In alcune situazioni , un'espressione viene valutata prima che un'istruzione CASE riceva i risultati dell'espressione come input. Sono possibili errori nella valutazione di queste espressioni. Le espressioni aggregate che appaiono negli argomenti WHEN a un'istruzione CASE vengono valutate per prime, quindi fornito all'istruzione CASE. Ad esempio, la seguente query produce un errore di divisione per zero durante la produzione del valore dell'aggregato MAX . Ciò si verifica prima di valutare l'espressione CASE.

Non sono sicuro che questo sia rilevante, ma il linguaggio è piuttosto pesante per un non nativo, quindi forse lo è?

+0

L'unico scopo di convertire in modo esplicito un 'varchar' a' money' quando è implicitamente riconvertito 'varchar' è, per quanto ne so per la formattazione di scopi e allora perché non si fa né riporlo nella formattazione desiderata per iniziare con o lasciare che il client gestisca la formattazione? –

+1

I dati di origine non sono sotto il mio controllo. Nel caso concreto devo passare attraverso un bel po 'di cerchi per ottenere i dati in un formato tale da poterlo inserire nella tabella dei report per cui è destinato (che è correttamente digitato) – carlpett

risposta

3

Dai un'occhiata alla seguente Use caution when Using CONVERT() with CASE or IF functions in Transact SQL (T-SQL)

I primi pensieri sono generalmente uno dei seguenti "Dal momento che il primo valore valutato è numerico, viene convertito in decimale, e tutti gli altri dati è prevista per essere anche un decimale "O" Se SQL Server è in grado di convertire QUALSIASI dei valori nel tipo specificato, , tutti i valori sono che si prevede siano del tipo convertito ". Tuttavia, non è corretto (anche se il secondo è vicino)!

Il vero problema è che se si sceglie di convertire i valori ovunque all'interno dell'istruzione caso, il tipo di dati si sta convertendo i valori per è il tipo atteso di tutti i valori a prescindere se sono di quel tipo o non. Inoltre, anche se NONE dei valori può essere convertito in (anche se la riga di codice Convert non viene mai eseguita), TUTTI i valori devono ancora essere del tipo specificato dalla funzione di conversione Converti!

+0

Grazie, questo illumina il perché, ma non c'è davvero nessuna via da seguire? – carlpett

1

essere chiari su ciò che sta accadendo è la clausola thennon in corso di valutazione.

si vede lo stesso errore se si fa

SELECT CASE @proptype 
     WHEN 'money' THEN $1.0 /*<-- Literal of datatype money*/ 
     ELSE @val 
     END 

La documentazione per CASE spiega che il tipo di ritorno

Restituisce il tipo più elevato di precedenza dal set di tipi in result_expressions e opzionale else_result_expression. Per ulteriori informazioni su , vedere Data Type Precedence (Transact-SQL).

money ha precedenza maggiore rispetto tipo di dati in modo che il nvarcharelse @val viene valutata allora che ottiene gettati a money e fallisce.

Una possibile soluzione sarebbe quella di trasmettere il valore a sql_variant in quanto ha una precedenza di dati superiore rispetto a entrambi.

declare @proptype nvarchar(50)= 'nvarchar' 
declare @val nvarchar(10) = 'test' 
select 
    case @proptype 
     when 'money' then convert(money, @val) 
     else cast(@val as SQL_VARIANT) 
    end 
Problemi correlati