How Long are NUMBER Datatype Values? by Kevin Loney Kevin Loney is an independent Oracle consultant and author. This article first appeared on http://www.kevinloney.com. For links to additional Oracle articles, see http://www.lonyx.com, the search directory for Oracle professionals. If you use a DATE datatype, Oracle uses 7 bytes to store the value. If you use a VARCHAR2 datatype, the stored length of the value is directly related to the length of the string. If you use a NUMBER datatype, the number of bytes required to store the value varies, and is seldom the same as the length of the value. In this article, you will see how to match the length of a number to its maximum number of storage bytes. To simplify matters, you will see a table that matches the number of significant digits in a number to its stored length. Testimony from The Oracle8i Server Concepts Guide The Oracle8i Server Concepts Guide offers the following guidance on the length of a number as it is stored: Oracle stores numeric data in variable-length format. Each value is stored in scientific notation, with one byte used to store the exponent and up to 20 bytes to store the mantissa. (The resulting value is limited to 38 digits of precision.) Oracle does not store leading and trailing zeros. For example, the number 412 is stored in a format similar to 4.12 x 102, with one byte used to store the exponent (2) and two bytes used to store the three significant digits of the mantissa (4, 1, 2). Taking this into account, the column data size for a particular numeric data value NUMBER (p), where p is the precision of a given value (scale has no effect), can be calculated using the following formula: 1 byte + FLOOR(p/2)+1 bytes + 1 byte (exponent) (mantissa) (only for a negative number where the number of significant digits is less than 38) _______________________ number of bytes of data Simplifying the Math While correct, the description from the Concepts guide does not provide a quick way to estimate the stored length, in bytes, of a numeric value. There are some standard rules: 1. The precision is limited to 38 digits. 2. The exponent does not impact the length. The stored length for 123.45 and 1234.5 and 12345 and 123450000000 will be identical. 3. 4. 5. 6. The minimum length is 2 bytes. The maximum length for the mantissa is 20 bytes. Negative numbers take one byte more than positive numbers. The stored length is impacted by the number of significant digits in a number, not its number of digits. To generate a simple table that can provide the length/stored bytes relationship for NUMBER tables, I created a table called NUMBERS. The table was then populated with numeric values from 1 to 38 significant digits of precision. Negative numbers were also tested, following the same methodology. Using the LENGTH and VSIZE functions, the actual storage lengths were then determined. The scripts used to generate the data are found in the “Generating the Numbers” section at the end of this article. In all cases, the value was a string of 9’s of the specified length. For the following table, Number of Significant Digits column: LENGTH(value). If the number does not end in zero, then this is the number of significant digits. Vsize column: VSIZE(value) NegLength column: LENGTH(negative value). If the number does not end in zero, then this is the number of significant digits. NegVsize column: VSIZE(negative value) Number of Significant Digits 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 Vsize NegLength NegVsize 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 10 11 11 12 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 10 11 11 12 12 13 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 12 13 13 14 14 15 15 16 16 17 17 18 18 19 19 20 20 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 13 14 14 15 15 16 16 17 17 18 18 19 19 20 20 21 21 NOTE: This table was generated using all 9’s for the digits. Because of the algorithm Oracle uses, you will get slightly lower VSIZE results for smaller numbers of the same length. A three-digit number with only 1 significant digit, 100, will use only two bytes. 101, which as 3 significant digits, uses 3 bytes. You should evaluate the distribution of numeric values within your NUMBER fields to accurately predict the number of significant digits stored. In general, only about 81% of numbers have lengths that match their number of significant digits. Generating the Numbers To generate the results, a table named NUMBERS was created and populated with a single record. The following script creates the table, populates it, and selects the length values from it. In these examples, all digits are significant. create table NUMBERS ( number1 number(1), negnumber1 number(1), number2 number(2), negnumber2 number(2), number3 number(3), negnumber3 number(3), number4 number(4), negnumber4 number(4), number5 number(5), negnumber5 number(5), number6 number(6), negnumber6 number(6), number7 number(7), negnumber7 number(7), number8 number(8), negnumber8 number(8), number9 number(9), negnumber9 number(9), number10 number(10), negnumber10 number(10), number11 number(11), negnumber11 number(11), number12 number(12), negnumber12 number(12), number13 number(13), negnumber13 number(13), number14 number(14), negnumber14 number(14), number15 number(15), negnumber15 number(15), number16 number(16), negnumber16 number(16), number17 number(17), negnumber17 number(17), number18 number(18), negnumber18 number(18), number19 number(19), negnumber19 number(19), number20 number(20), negnumber20 number(20), number21 number(21), negnumber21 number(21), number22 number(22), negnumber22 number(22), number23 number(23), negnumber23 number(23), number24 number(24), negnumber24 number(24), number25 number(25), negnumber25 number(25), number26 number(26), negnumber26 number(26), number27 number(27), negnumber27 number(27), number28 number(28), negnumber28 number(28), number29 number(29), negnumber29 number(29), number30 number(30), negnumber30 number(30), number31 number(31), negnumber31 number(31), number32 number(32), negnumber32 number(32), number33 number(33), negnumber33 number(33), number34 number(34), negnumber34 number(34), number35 number(35), negnumber35 number(35), number36 number(36), negnumber36 number(36), number37 number(37), negnumber37 number(37), number38 number(38), negnumber38 number(38) ); insert into numbers values ( 9, -9, 99, -99, 999, -999, 9999, -9999, 99999, -99999, 999999, -999999, 9999999, -9999999, 99999999, -99999999, 999999999, -999999999, 9999999999, -9999999999, 99999999999, -99999999999, 999999999999, -999999999999, 9999999999999, -9999999999999, 99999999999999, -99999999999999, 999999999999999, -999999999999999, 9999999999999999, -9999999999999999, 99999999999999999, -99999999999999999, 999999999999999999, -999999999999999999, 9999999999999999999, -9999999999999999999, 99999999999999999999, -99999999999999999999, 999999999999999999999, -999999999999999999999, 9999999999999999999999, -9999999999999999999999, 99999999999999999999999, -99999999999999999999999, 999999999999999999999999, -999999999999999999999999, 9999999999999999999999999, -9999999999999999999999999, 99999999999999999999999999, -99999999999999999999999999, 999999999999999999999999999, -999999999999999999999999999, 9999999999999999999999999999, -9999999999999999999999999999, 99999999999999999999999999999, -99999999999999999999999999999, 999999999999999999999999999999, -999999999999999999999999999999, 9999999999999999999999999999999, -9999999999999999999999999999999, 99999999999999999999999999999999, -99999999999999999999999999999999, 999999999999999999999999999999999, -999999999999999999999999999999999, 9999999999999999999999999999999999, -9999999999999999999999999999999999, 99999999999999999999999999999999999, -99999999999999999999999999999999999, 999999999999999999999999999999999999, -999999999999999999999999999999999999, 9999999999999999999999999999999999999, -9999999999999999999999999999999999999, 99999999999999999999999999999999999999, -99999999999999999999999999999999999999) ; select length(number1), vsize(number1), length(negnumber1), vsize(negnumber1) from numbers; select length(number2), vsize(number2), length(negnumber2), vsize(negnumber2) from numbers; select length(number3), vsize(number3), length(negnumber3), vsize(negnumber3) from numbers; select length(number4), vsize(number4), length(negnumber4), vsize(negnumber4) from numbers; select length(number5), vsize(number5), length(negnumber5), vsize(negnumber5) from numbers; select length(number6), vsize(number6), length(negnumber6), vsize(negnumber6) from numbers; select length(number7), vsize(number7), length(negnumber7), vsize(negnumber7) from numbers; select length(number8), vsize(number8), length(negnumber8), vsize(negnumber8) from numbers; select length(number9), vsize(number9), length(negnumber9), vsize(negnumber9) from numbers; select length(number10), vsize(number10), length(negnumber10), vsize(negnumber10) from numbers; select length(number11), vsize(number11), length(negnumber11), vsize(negnumber11) from numbers; select length(number12), vsize(number12), length(negnumber12), vsize(negnumber12) from numbers; select length(number13), vsize(number13), length(negnumber13), vsize(negnumber13) from numbers; select length(number14), vsize(number14), length(negnumber14), vsize(negnumber14) from numbers; select length(number15), vsize(number15), length(negnumber15), vsize(negnumber15) from numbers; select length(number16), vsize(number16), length(negnumber16), vsize(negnumber16) from numbers; select length(number17), vsize(number17), length(negnumber17), vsize(negnumber17) from numbers; select length(number18), vsize(number18), length(negnumber18), vsize(negnumber18) from numbers; select length(number19), vsize(number19), length(negnumber19), vsize(negnumber19) from numbers; select length(number20), vsize(number20), length(negnumber20), vsize(negnumber20) from numbers; select length(number21), vsize(number21), length(negnumber21), vsize(negnumber21) from numbers; select length(number22), vsize(number22), length(negnumber22), vsize(negnumber22) from numbers; select length(number23), vsize(number23), length(negnumber23), vsize(negnumber23) from numbers; select length(number24), vsize(number24), length(negnumber24), vsize(negnumber24) from numbers; select length(number25), vsize(number25), length(negnumber25), vsize(negnumber25) from numbers; select length(number26), vsize(number26), length(negnumber26), vsize(negnumber26) from numbers; select length(number27), vsize(number27), length(negnumber27), vsize(negnumber27) from numbers; select length(number28), vsize(number28), length(negnumber28), vsize(negnumber28) from numbers; select length(number29), vsize(number29), length(negnumber29), vsize(negnumber29) from numbers; select length(number30), vsize(number30), length(negnumber30), vsize(negnumber30) from numbers; select length(number31), vsize(number31), length(negnumber31), vsize(negnumber31) from numbers; select length(number32), vsize(number32), length(negnumber32), vsize(negnumber32) from numbers; select length(number33), vsize(number33), length(negnumber33), vsize(negnumber33) from numbers; select length(number34), vsize(number34), length(negnumber34), vsize(negnumber34) from numbers; select length(number35), vsize(number35), length(negnumber35), vsize(negnumber35) from numbers; select length(number36), vsize(number36), length(negnumber36), vsize(negnumber36) from numbers; select length(number37), vsize(number37), length(negnumber37), vsize(negnumber37) from numbers; select length(number38), vsize(number38), length(negnumber38), vsize(negnumber38) from numbers;