本文共 15603 字,大约阅读时间需要 52 分钟。
SQL> set numwidth 50SQL> create table test(id int);Table created.SQL> insert into test values (9999999999999999999);1 row created.SQL> select * from test; ID-------------------------------------------------- 9999999999999999999在sqlplus客户端中,数字长度显示默认为10,超出的话会用科学方法表示,所以不要误以为这是精度问题哦。
SQL> set numwidth 10SQL> select * from test; ID----------1.0000E+19精度实际上是NUMBER(38)。超过可能遇到BUG,虽然可以存储进去。例如以下,40个9显示正常,但是41个9时进位了,已经精度不准确。
SQL> insert into test values (9999999999999999999999999999999999999999);SQL> insert into test values (99999999999999999999999999999999999999999);SQL> select * from test; ID-------------------------------------------------- 9999999999999999999999999999999999999999 100000000000000000000000000000000000000000使用NUMERIC表现一样:SQL> drop table test;Table dropped.SQL> create table test(id numeric);Table created.SQL> insert into test values (9999999999999999999999999999999999999999);SQL> insert into test values (99999999999999999999999999999999999999999);SQL> select * from test; ID-------------------------------------------------- 9999999999999999999999999999999999999999 100000000000000000000000000000000000000000在PostgreSQL中,我们要使用对应的numeric类型来代替Oracle的int类型,并且非常完美,超出40位没有问题。
postgres=# select 9999999999999999999999999999999999999999::numeric; numeric ------------------------------------------ 9999999999999999999999999999999999999999(1 row)postgres=# select 99999999999999999999999999999999999999999::numeric; numeric ------------------------------------------- 99999999999999999999999999999999999999999(1 row)postgres=# select 99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999::numeric; numeric ------------------------------------------------------------------------------------------------- 99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999(1 row)postgres=# select 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999::numeric; numeric --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999(1 row)postgres=# select 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999::numeric; numeric ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999(1 row)postgres=# select 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999998888888888888888888888888888888888888888888888888888888888888888888888888888::numeric; numeric -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999998888888888888888888888888888888888888888888888888888888888888888888888888888(1 row)postgres=# create table test(id numeric);CREATE TABLEpostgres=# insert into test values (9999999999999999999999999999999999999999);INSERT 0 1postgres=# insert into test values (99999999999999999999999999999999999999999);INSERT 0 1postgres=# select * from test; id ------------------------------------------- 9999999999999999999999999999999999999999 99999999999999999999999999999999999999999(2 rows)postgres=# insert into test values (9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999991111111111111111111111111111111111111111111111111111111111111111111);INSERT 0 1postgres=# select * from test; id ------------------------------------------------------------------------------------------------------------------------------------------------------------------ 9999999999999999999999999999999999999999 99999999999999999999999999999999999999999 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999991111111111111111111111111111111111111111111111111111111111111111111(3 rows)
/*------------------------------------------------------------------------- * * numeric.h * Definitions for the exact numeric data type of Postgres * * Original coding 1998, Jan Wieck. Heavily revised 2003, Tom Lane. * * Copyright (c) 1998-2010, PostgreSQL Global Development Group * * $PostgreSQL: pgsql/src/include/utils/numeric.h,v 1.29 2010/01/02 16:58:10 momjian Exp $ * *------------------------------------------------------------------------- *//* * The Numeric data type stored in the database * * NOTE: by convention, values in the packed form have been stripped of * all leading and trailing zero digits (where a "digit" is of base NBASE). * In particular, if the value is zero, there will be no digits at all! * The weight is arbitrary in that case, but we normally set it to zero. */typedef struct NumericData{ int32 vl_len_; /* varlena header (do not touch directly!) */ uint16 n_sign_dscale; /* Sign + display scale */ int16 n_weight; /* Weight of 1st digit */ char n_data[1]; /* Digits (really array of NumericDigit) */} NumericData;typedef NumericData *Numeric;/* * Hardcoded precision limit - arbitrary, but must be small enough that * dscale values will fit in 14 bits. */#define NUMERIC_MAX_PRECISION 1000
postgres=# select 2^16 + 2^16; ?column? ---------- 131072(1 row)postgres=# select repeat('9',131073)::numeric;ERROR: 22003: value overflows numeric formatLOCATION: make_result, numeric.c:4202postgres=# select repeat('9',131072)::numeric;正常返回postgres=# select (repeat('9',131072)||'.'||repeat('9',16384))::numeric;ERROR: 22003: value overflows numeric formatLOCATION: make_result, numeric.c:4202postgres=# select (repeat('9',131072)||'.'||repeat('9',16383))::numeric;正常返回
/* * The Numeric type as stored on disk. * * If the high bits of the first word of a NumericChoice (n_header, or * n_short.n_header, or n_long.n_sign_dscale) are NUMERIC_SHORT, then the * numeric follows the NumericShort format; if they are NUMERIC_POS or * NUMERIC_NEG, it follows the NumericLong format. If they are NUMERIC_NAN, * it is a NaN. We currently always store a NaN using just two bytes (i.e. * only n_header), but previous releases used only the NumericLong format, * so we might find 4-byte NaNs on disk if a database has been migrated using * pg_upgrade. In either case, when the high bits indicate a NaN, the * remaining bits are never examined. Currently, we always initialize these * to zero, but it might be possible to use them for some other purpose in * the future. * * In the NumericShort format, the remaining 14 bits of the header word * (n_short.n_header) are allocated as follows: 1 for sign (positive or * negative), 6 for dynamic scale, and 7 for weight. In practice, most * commonly-encountered values can be represented this way. * * In the NumericLong format, the remaining 14 bits of the header word * (n_long.n_sign_dscale) represent the display scale; and the weight is * stored separately in n_weight. * * NOTE: by convention, values in the packed form have been stripped of * all leading and trailing zero digits (where a "digit" is of base NBASE). * In particular, if the value is zero, there will be no digits at all! * The weight is arbitrary in that case, but we normally set it to zero. */struct NumericShort{ uint16 n_header; /* Sign + display scale + weight */ NumericDigit n_data[1]; /* Digits */};struct NumericLong{ uint16 n_sign_dscale; /* Sign + display scale */ int16 n_weight; /* Weight of 1st digit */ NumericDigit n_data[1]; /* Digits */};union NumericChoice{ uint16 n_header; /* Header word */ struct NumericLong n_long; /* Long form (4-byte header) */ struct NumericShort n_short; /* Short form (2-byte header) */};struct NumericData{ int32 vl_len_; /* varlena header (do not touch directly!) */ union NumericChoice choice; /* choice of format */};
/* * make_result() - * * Create the packed db numeric format in palloc()'d memory from * a variable. */static Numericmake_result(NumericVar *var){ Numeric result; NumericDigit *digits = var->digits; int weight = var->weight; int sign = var->sign; int n; Size len; if (sign == NUMERIC_NAN) { result = (Numeric) palloc(NUMERIC_HDRSZ_SHORT); SET_VARSIZE(result, NUMERIC_HDRSZ_SHORT); result->choice.n_header = NUMERIC_NAN; /* the header word is all we need */ dump_numeric("make_result()", result); return result; } n = var->ndigits; /* truncate leading zeroes */ while (n > 0 && *digits == 0) { digits++; weight--; n--; } /* truncate trailing zeroes */ while (n > 0 && digits[n - 1] == 0) n--; /* If zero result, force to weight=0 and positive sign */ if (n == 0) { weight = 0; sign = NUMERIC_POS; } /* Build the result */ if (NUMERIC_CAN_BE_SHORT(var->dscale, weight)) { len = NUMERIC_HDRSZ_SHORT + n * sizeof(NumericDigit); result = (Numeric) palloc(len); SET_VARSIZE(result, len); result->choice.n_short.n_header = (sign == NUMERIC_NEG ? (NUMERIC_SHORT | NUMERIC_SHORT_SIGN_MASK) : NUMERIC_SHORT) | (var->dscale << NUMERIC_SHORT_DSCALE_SHIFT) | (weight < 0 ? NUMERIC_SHORT_WEIGHT_SIGN_MASK : 0) | (weight & NUMERIC_SHORT_WEIGHT_MASK); } else { len = NUMERIC_HDRSZ + n * sizeof(NumericDigit); result = (Numeric) palloc(len); SET_VARSIZE(result, len); result->choice.n_long.n_sign_dscale = sign | (var->dscale & NUMERIC_DSCALE_MASK); result->choice.n_long.n_weight = weight; } memcpy(NUMERIC_DIGITS(result), digits, n * sizeof(NumericDigit)); Assert(NUMERIC_NDIGITS(result) == n); /* Check for overflow of int16 fields */ if (NUMERIC_WEIGHT(result) != weight || NUMERIC_DSCALE(result) != var->dscale) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("value overflows numeric format"))); dump_numeric("make_result()", result); return result;}
numeric | variable | user-specified precision, exact | no limit |
转载地址:http://hhsel.baihongyu.com/