Qual è la causa di questo problema con CONVERT ()?


12

Considera le seguenti due affermazioni:

PRINT CONVERT(NUMERIC(38, 0), 0x0100000001, 0);
PRINT CONVERT(NUMERIC(38, 0), 0x0100010001, 0);

Entrambe le dichiarazioni ritornano -1; non è errato poiché il secondo valore binario è decimale 65.536 maggiore del primo valore, non è vero?

Sicuramente questo non può essere dovuto al troncamento silenzioso?

Se eseguo le seguenti dichiarazioni:

PRINT CONVERT(NUMERIC(38, 0),   0x00000001, 0);
PRINT CONVERT(NUMERIC(38, 0),   0x00010001, 0);

Mi viene presentato il seguente errore:

Msg 8114, Level 16, State 5, Line 1
Error converting data type varbinary to numeric.

Come posso diagnosticare cosa sta succedendo qui?

Sto eseguendo questo su SQL Server 2012, v11.0.5058. I risultati sono gli stessi su SQL Server 2008 R2 SP2, SQL Server 2005 e SQL Server 2000.


4
I numeri decimali e interi sono codificati in modo molto diverso in varbinary. I decimali hanno bisogno di più spazio. ProvaSELECT CONVERT(VARBINARY(32), 1), CONVERT(VARBINARY(32), 1.0);
Aaron Bertrand

4
Aaron è perfetto. Il tuo cervello sta convertendo i dati binari in dati interi quindi direttamente in numerici, ma SQL Server non esegue quella conversione implicita da binario -> intero -> numerico (x, y). Per SQL Server per seguire il processo di pensiero, che avrebbe dovuto fare qualcosa del genere: PRINT CONVERT(NUMERIC(38, 0), convert(int, 0x00000001), 0); PRINT CONVERT(NUMERIC(38, 0), convert(int, 0x00010001), 0);.
Thomas Stringer,

5
Il primo byte è scala (0x01 = 1), Il secondo byte è precisione (0x00 = 0), Il byte finale è il valore (0x01 = 1). Non sono sicuro a cosa servano i byte tre e quattro. Il segno è presente ma non richiede due byte. Sicuramente capovolgere quel bit non sembra aver influenzato nulla.
Martin Smith,

1
Grazie, @MartinSmith - come mai hai determinato che i primi due byte vengono usati in questo modo? È documentato?
Max Vernon,

3
@AaronBertrand: vuoi fare una risposta? Possiamo contrassegnarlo dall'elenco "senza risposta".
Jon of All Trades,

Risposte:


2

I numeri decimali e interi sono codificati in modo molto diverso in varbinary. I decimali hanno bisogno di più spazio. Provare:

SELECT CONVERT(VARBINARY(32), 1), CONVERT(VARBINARY(32), 1.0);

Per quanto riguarda il tuo obiettivo finale, memorizzare numeri interi come varbinary per risparmiare spazio, penso che tu abbia risposto a questa domanda da solo - non ne vale la pena.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.