PolarDB for PostgreSQL (Compatible with Oracle) supports the following numeric types: integers, arbitrary-precision numbers, floating-point numbers, serial (auto-increment) types, and Oracle-compatible extensions.
Numeric types overview
| Type | Storage size | Description | Range |
|---|---|---|---|
SMALLINT | 2 bytes | Small-range integer | -32768 to +32767 |
INTEGER | 4 bytes | Standard integer | -2147483648 to +2147483647 |
BIGINT | 8 bytes | Large-range integer | -9223372036854775808 to +9223372036854775807 |
DECIMAL | Variable | Exact, user-specified precision | Up to 131,072 digits before the decimal point; up to 16,383 digits after |
NUMERIC | Variable | Exact, user-specified precision | Up to 131,072 digits before the decimal point; up to 16,383 digits after |
REAL | 4 bytes | Inexact, variable-precision (single precision) | 6 decimal digits of precision |
DOUBLE PRECISION | 8 bytes | Inexact, variable-precision (double precision) | 15 decimal digits of precision |
SMALLSERIAL | 2 bytes | Auto-incrementing small integer | 1 to 32767 |
SERIAL | 4 bytes | Auto-incrementing integer | 1 to 2147483647 |
BIGSERIAL | 8 bytes | Auto-incrementing large integer | 1 to 9223372036854775807 |
BINARY_INTEGER | 4 bytes | Signed integer; alias for INTEGER | -2147483648 to +2147483647 |
NUMBER | Variable | Exact, user-specified precision | Up to 1,000 decimal digits of precision |
NUMBER(p [, s]) | Variable | Exact, with maximum precision (p) and optional scale (s) | Up to 1,000 decimal digits of precision |
PLS_INTEGER | 4 bytes | Signed integer; alias for INTEGER | -2147483648 to +2147483647 |
ROWID | 8 bytes | Signed 8-bit integer | -9223372036854775808 to 9223372036854775807 |
Integer types
SMALLINT, INTEGER, and BIGINT store whole numbers of different sizes. Attempting to store a value outside a type's range causes an error.
Choose based on your requirements:
INTEGER: The default choice. Offers the best balance of range, storage size, and performance.SMALLINT: Use when disk space is a concern and values fit within ±32767.BIGINT: Use whenINTEGER's range of roughly ±2.1 billion is insufficient.
The SQL standard defines INTEGER (or INT), SMALLINT, and BIGINT. The aliases INT2, INT4, and INT8 are extensions also available in many other SQL databases.
Arbitrary precision numbers
NUMERIC (equivalent to DECIMAL) stores numbers with exact precision — no rounding errors during arithmetic. Use it for monetary amounts or any data where exactness matters. The trade-off is that NUMERIC calculations are slower than integer or floating-point arithmetic.
Precision and scale
Two key terms define NUMERIC column behavior:
Precision: the total number of significant digits on both sides of the decimal point.
Scale: the number of digits to the right of the decimal point.
For example, 23.5141 has a precision of 6 and a scale of 4. Integers have a scale of 0.
Column declaration syntax
-- Specify both precision and scale
NUMERIC(precision, scale)
-- Specify precision only; scale defaults to 0
NUMERIC(precision)
-- No constraint; stores any precision and scale up to the type limit
NUMERICThe maximum explicitly specified precision is 1,000. A column declared without precision or scale accepts values up to the type's internal limit (131,072 digits before the decimal point, 16,383 digits after).
Do not assign unnecessarily high precision to NUMERIC columns. High-precision values consume more storage and can slow query execution.Insertion behavior
When inserting a value into a NUMERIC(p, s) column:
If the fractional digits exceed the column's scale, the value is rounded to the specified scale.
If the fractional digits are fewer than the column's scale, the value is stored as-is (not zero-padded).
If the digits to the left of the decimal point exceed
precision − scale, an error is reported.
The following example shows how three different column definitions handle the same input value:
CREATE TABLE decimals (
a NUMERIC PRIMARY KEY,
b NUMERIC(10, 5),
c NUMERIC
);
INSERT INTO decimals VALUES (
1.01234567890123456789,
1.01234567890123456789,
1.01234567890123456789
);
SELECT * FROM decimals; a | b | c
------------------------+---------+------------------------
1.01234567890123456789 | 1.01235 | 1.01234567890123456789
(1 row)Column a and column c store the value exactly. Column b is rounded to 5 decimal places as specified by its scale.
Storage
NUMERIC values are stored without leading or trailing zeros, so declared precision and scale are maximums, not fixed allocations — similar to VARCHAR(n) rather than CHAR(n). Storage cost is 2 bytes per group of 4 decimal digits, plus 3–8 bytes of overhead.
NaN
NUMERIC supports the special value NaN (not a number). Write it as a single-quoted string in SQL:
UPDATE table SET x = 'NaN';NaN is case-insensitive on input. In PolarDB for PostgreSQL (Compatible with Oracle), NaN values are treated as equal to each other and as greater than all non-NaN values, which allows sorting and use in tree-based indexes.
Rounding behavior
NUMERIC rounds away from zero (half-up). REAL and DOUBLE PRECISION round to the nearest even number (banker's rounding). The following query illustrates the difference:
SELECT x,
round(x::numeric) AS num_round,
round(x::double precision) AS dbl_round
FROM generate_series(-3.5, 3.5, 1) AS x; x | num_round | dbl_round
------+-----------+-----------
-3.5 | -4 | -4
-2.5 | -3 | -2
-1.5 | -2 | -2
-0.5 | -1 | -0
0.5 | 1 | 0
1.5 | 2 | 2
2.5 | 3 | 2
3.5 | 4 | 4
(8 rows)Floating-point types
REAL and DOUBLE PRECISION are inexact, variable-precision types that implement the Institute of Electrical and Electronics Engineers (IEEE) 754 standard for binary floating-point arithmetic — single precision and double precision respectively.
Before using floating-point types, consider the following:
For monetary amounts or anything requiring exact results, use
NUMERICinstead.If your logic depends on boundary-case behavior such as infinity or underflow, evaluate the implementation carefully.
Comparing two floating-point values for equality may not produce the expected result.
Ranges and precision
| Type | Range | Precision |
|---|---|---|
REAL (FLOAT4) | 1E-37 to 1E+37 | At least 6 decimal digits |
DOUBLE PRECISION (FLOAT8) | 1E-307 to 1E+308 | At least 15 decimal digits |
Values outside the supported range cause an error. Values close to zero that cannot be represented as distinct from zero cause an underflow error. Values with higher precision than the type supports are rounded on input.
Output format
By default, floating-point values are output in the shortest precise decimal representation — the closest decimal to the actual stored binary value. The output uses at most 17 significant digits for FLOAT8 and at most 9 for FLOAT4.
Use the extra_float_digits parameter to control output precision:
extra_float_digits value | Effect |
|---|---|
> 0 (e.g., 3) | Shortest-precise format (recommended for maximum precision) |
0 | Rounds to 15 digits for FLOAT8, 6 digits for FLOAT4 (legacy default) |
Negative (e.g., -2) | Further reduces output digits (13 for FLOAT8, 4 for FLOAT4) |
Set extra_float_digits = 3 for applications that require maximum precision. Set it to 0 for compatibility with older versions of PolarDB for PostgreSQL (Compatible with Oracle).
Special values
Floating-point types support three IEEE 754 special values. Write them as single-quoted strings in SQL:
UPDATE table SET x = 'Infinity';
UPDATE table SET x = '-Infinity';
UPDATE table SET x = 'NaN';These values are case-insensitive on input. Like NUMERIC, PolarDB for PostgreSQL (Compatible with Oracle) treats NaN floating-point values as equal to each other and as greater than all non-NaN values.
FLOAT(p) syntax
PolarDB for PostgreSQL (Compatible with Oracle) supports the SQL-standard FLOAT and FLOAT(p) notations, where p specifies the minimum acceptable precision in binary digits:
FLOAT(1)toFLOAT(24)maps toREALFLOAT(25)toFLOAT(53)maps toDOUBLE PRECISIONFLOATwith no precision specified is treated asDOUBLE PRECISION
Values of p outside the range 1–53 cause an error.
Serial types
SMALLSERIAL, SERIAL, and BIGSERIAL are not actual data types. They are shorthand for creating auto-incrementing integer columns — similar to AUTO_INCREMENT in other databases.
Declaring a column as SERIAL is equivalent to:
CREATE SEQUENCE tablename_colname_seq AS integer;
CREATE TABLE tablename (
colname integer NOT NULL DEFAULT nextval('tablename_colname_seq')
);
ALTER SEQUENCE tablename_colname_seq OWNED BY tablename.colname;The column gets a NOT NULL constraint automatically. Add a UNIQUE or PRIMARY KEY constraint separately to prevent duplicate values.
To insert the next sequence value, either omit the column from the INSERT statement or use the DEFAULT keyword.
The sequence is dropped automatically when the column or table is dropped. Dropping the sequence without dropping the column removes the column's default value expression.
Type aliases
| Type | Alias | Column type |
|---|---|---|
SMALLSERIAL | SERIAL2 | SMALLINT |
SERIAL | SERIAL4 | INTEGER |
BIGSERIAL | SERIAL8 | BIGINT |
Use BIGSERIAL when your table will have more than 2,147,483,647 rows over its lifetime.
Gaps may appear in serial sequences even without deleted rows. A sequence value is consumed when assigned, even if the transaction that triggered the assignment is later rolled back.
Alternatively, use the SQL-standard identity column feature described in the CREATE TABLE topic.
Oracle-compatible types
PolarDB for PostgreSQL (Compatible with Oracle) includes the following Oracle-compatible numeric types:
| Type | Equivalent | Notes |
|---|---|---|
BINARY_INTEGER | INTEGER | Signed 4-byte integer |
PLS_INTEGER | INTEGER | Signed 4-byte integer |
NUMBER | NUMERIC | Exact, up to 1,000 decimal digits |
NUMBER(p [, s]) | NUMERIC(p, s) | Exact, with precision and optional scale |
ROWID | BIGINT | Signed 8-bit integer |
Oracle's NUMBER type supports up to 38 decimal digits of precision. PolarDB for PostgreSQL (Compatible with Oracle) extends this limit to 1,000 decimal digits. If you are migrating from Oracle, verify that your application handles this difference correctly to avoid unexpected behavior.