Perché la precisione numerica di SQL è specificata come numero di cifre?

6

Capisco che questa potrebbe essere una domanda caricata. Ad esempio, in Sql Server 2008, facendo DECLARE @someNum NUMERIC(10); significa che l'intervallo della variabile sarà limitato di 10 cifre. In altri linguaggi come C, Java, ecc., Gli standard per rappresentare numeri interi e frazionari sono diversi. L'intervallo dei valori viene suddiviso in multipli di byte e ciò è comprensibile, a causa del modo in cui l'hardware funziona. Un linguaggio potrebbe fornire qualcosa che la maggior parte dell'hardware non supporta ancora, come un tipo intero a 256 bit, che funzionerà velocemente su un computer a 64 bit, se implementato correttamente.

I tipi numerici nei database sembrano non essere legati all'hardware sottostante. Capisco che i valori potrebbero aver bisogno di essere null-ablle, il che può costare un paio di bit, ma perché una tale precisione arbitraria non sembra ottimizzare la velocità di archiviazione o calcolo?

Forse i database non hanno bisogno di eseguire spesso calcoli numerici. Forse la larghezza delle cifre di una colonna è un'estensione naturale della larghezza del carattere. Forse SQL doveva essere un linguaggio non programmatore (perché sembra inglese :))? Forse la storia ha preso una svolta strana, come quella che ha permesso al formato VHS inferiore di prosperare.

Per favore aiutami a capire questo.

    
posta Job 10.06.2011 - 00:41
fonte

5 risposte

7

doing DECLARE @someNum NUMERIC(10); means that the range of the variable will be limited by 10 digits.

In realtà, si sbaglia molto in tale asserzione, o il server SQL è estremamente incompatibile con altri motori di database. In genere, hai:

  • NUMERICO (precisione, scala)
  • NUMERIC (precisione)

Nel secondo caso, la scala è zero, cioè puoi gestire solo interi; precisione è il numero totale massimo di cifre con la scala specificata (che significa interi nel secondo caso).

Al contrario, sembra che tu stia leggendo numeric (10) come "qualsiasi numero finché ci sono 10 cifre o meno", per il quale non esiste (meglio comunque lo so) SQL costruisce a corto di single / tipi double float (il cui nome è diverso per motore DB).

The numeric types in the databases seem to be not tied to underlying hardware.

In effetti, non lo sono. Numeric / Decimal è un numero di precisione arbitrario , memorizzato molto simile a un varchar di lunghezza enorme (1000+ cifre). Puoi effettivamente usarlo per memorizzare 1e100 + 1 come valore esatto. Otterrai 1 seguito da zero e infine 1 .

Sembra che tu abbia bisogno di un float ... Quest'ultimo memorizzerebbe 1e100 quando viene dato 1e100 + 1 , e restituirebbe 1e100 .

    
risposta data 10.06.2011 - 01:17
fonte
2

I tipi numerici a virgola fissa non vengono utilizzati allo stesso scopo dei tipi numerici a virgola mobile.

Certo, i tipi a virgola mobile (che ogni database SQL anche ha) sono ottimizzati per l'hardware della macchina, ma sono anche imprecisi. Ogni giorno possiamo vedere un altro principiante che non capisce questo (non scegliere su chiunque, questo è solo l'esempio più recente che ho trovato).

Si paga un prezzo pesante per le prestazioni e i vantaggi di spazio che un punto variabile ti dà; in particolare, si finisce con qualcosa che non può mai mai essere usato in qualsiasi sistema che richiede quantità esatte, come un sistema finanziario. Vai avanti e prova a usare i float per il tuo componente di fatturazione; i contabili ti daranno un calcio sul marciapiede dopo la decima volta consecutiva che il processo di controllo fallisce.

I numeri interi sono ottimi per immagazzinare di quantità precise, ma piuttosto miserabili quando si tratta di computazione . Abbiamo venduto 5 unità ieri e 6 unità oggi; vuoi la media? È esattamente 5, secondo il sistema!

Ci sono situazioni in cui deve usare la precisione in virgola fissa, anche se non è perfettamente ottimizzata. Generalmente, queste situazioni coinvolgono denaro o precursori in denaro (come i tassi di sconto), anche se qualsiasi cosa che riguarda quantità reali è solitamente meglio anche come punto fisso - pesi e misure sono un altro ovvio esempio.

Oh, a proposito, quel commento stupido del VHS alla fine? Nient'altro che un mito . Lascia che sia una doppia lezione per te: le cose accadono per una ragione. Luoghi comuni vapidi come "VHS vinto a causa del marketing" o " SQL originariamente doveva essere per non -technical users "può sembrare bizzarro e affascinante ma raramente sono l'intera storia e sono spesso delle vere e proprie costruzioni.

    
risposta data 10.06.2011 - 03:52
fonte
1

Questo è speculativo, ma posso pensare a un paio di ragioni plausibili:

  1. Database relazionali utilizzare i numeri come identificatori più frequentemente che come oggetti di aritmetica operazioni. Efficienza di archiviazione e il confronto sarebbe più importante dell'aritmetica veloce operazioni. Passare da 16 bit a 32 bit interi è un grande salto e comporterebbe inutili file gonfiati (sprechi in una tabella = num numerici campi * num righe * numero di byte inutilizzati)
  2. Transact SQL è una bella  vecchio linguaggio, sviluppato originariamente  per processori a 16 bit. 16-bit  gli interi sono tè piuttosto deboli per tutti  tipo di attività commerciale / commerciale utilizzata,  in particolare alla luce del punto (1).  Il T-SQL originale avrebbe avuto bisogno  un numero più potente e flessibile di quello fornito in origine. Questo potrebbe  essere guidato dall'indietro  compatibilità.
risposta data 10.06.2011 - 01:17
fonte
1

Penso che la tua idea che un valore in una colonna sia come una variabile non è accurata. SQL Server (e altri database) memorizza i dati in termini di pagine (8 KB per SQL Server). Ogni pagina avrà tutte le righe di dati che si adatteranno (più alcune spese generali). Pertanto, l'archiviazione di SQL Server non si preoccupa veramente di ogni tipo di colonna e memorizza i byte non elaborati.

Controlla questo link per maggiori informazioni
link

    
risposta data 10.06.2011 - 02:08
fonte
0

In other languages such as C, Java, etc. the standards for representing whole and fractional numbers are different.

In C e vari linguaggi di programmazione, gli interi (INT () in SQL) sono in genere stringhe di bit interi e numeri in virgola mobile (FLOAT () / DOUBLE () in SQL) vengono solitamente memorizzati come IEEE-754 / - Stringhe di bit compatibili con 854.

DECIMAL () e NUMERIC () utilizzano in genere il decimale codificato in codice binario (BCD).

Un numero intero a 32 bit, pieno e con segno, memorizzerà -2-miliardi-or-so a +2 miliardi di dollari. È possibile utilizzare in modo affidabile 9 cifre, +/-, ma non 10. Per più di 10, è necessario il passo successivo del numero intero, che probabilmente sarà di 64 bit.

IEEE-754 si occupa della memorizzazione di numeri in virgola mobile in una sequenza a 32 bit. Memorizza:

  • un bit per il segno
  • più bit per un esponente relativo
  • più bit per una mantissa

In questo modo, contiene diverse cifre significative e una serie di esponenti. L'ordine dei bit è tale che è possibile trattarli come interi con segno a 32 bit, a scopo di confronto, e si dovrebbe ottenere la risposta giusta. In questo modo, non devi avere diversi modi per confrontare interi vs float. L'IEEE-854 porta questo a 64-bit, allocando più bit all'esponente relativo e alla mantissa, consentendo più cifre di precisione e una gamma più ampia di esponenti.

Il problema con questi valori in virgola mobile è che sono tutte le approssimazioni. E loro (almeno, i formati più vecchi, più comunemente supportati) sono tutti basati su esponenti di 2, non esponenti di 10. Ergo, non esiste alcuna rappresentazione ESATTA, in nessuno dei due, per 1.1 o 1.01; non c'è un esponente di 2 che puoi moltiplicare di questi e ottenere un valore esatto. Se gestisci transazioni finanziarie, non vuoi un'approssimazione. Se devi arrotondare, vuoi occuparti di esponenti di 10, non di 2, perché è così che denominiamo denaro.

DECIMAL () e NUMERIC () sono animali diversi, usando BCD. Se si definisce DECIMAL (7,2), questo memorizzerà un totale di 7 cifre decimali, tenendo traccia del fatto che 2 di esse sono dietro il punto decimale. Sono 7 cifre significative, nessuna approssimazione. Questo probabilmente si adatta a 32 bit di spazio (4 bit per ogni cifra + 4 bit per il campo totale, per memorizzare il segno, null, ecc.). Se moltiplichi due campi DECIMAL (7,2), sai PRECISAMENTE, fino al penny, cosa otterrai. Nessuna approssimazione.

E il summenzionato DECIMAL (10) avrà probabilmente solo 48 bit di spazio da memorizzare. E puoi utilizzare tutte e 10 le cifre, positive e negative.

Perhaps databases do not need to perform numeric computations often. Perhaps digit width of a column is a natural extension of character width. Perhaps SQL was supposed to be a non-programmers language (because it sounds like English :) )? Perhaps history took a weird turn, such as one that allowed the inferior VHS format to prosper.

Ho paura di non essere d'accordo con te, lì. I database che mi occupo fanno un sacco di calcoli numerici. La maggior parte di esso, tuttavia, è di dollari e centesimi, che in gran parte RICHIEDE la precisione del BCD e dei relativi formati DECIMAL (x, y). Il fatto che BCD mastichi 4 bit / cifra, mentre ASCII ne usa 8, è per lo più casuale.

L'invenzione di SQL è accreditata a E. F. Codd, che lavorava in IBM. Nessuna sorpresa, quindi, che la formattazione di DECIMAL (x, y) venga ampiamente rubata da FORTRAN.

    
risposta data 14.01.2016 - 17:00
fonte

Leggi altre domande sui tag