PostgreSQL – Data Type

In this chapter, we will discuss about the data types used in PostgreSQL. While creating table, for each column, you specify a data type, i.e., what kind of data you want to store in the table fields.

This enables several benefits βˆ’

  • Consistency βˆ’ Operations against columns of same data type give consistent results and are usually the fastest.
  • Validation βˆ’ Proper use of data types implies format validation of data and rejection of data outside the scope of data type.
  • Compactness βˆ’ As a column can store a single type of value, it is stored in a compact way.
  • Performance βˆ’ Proper use of data types gives the most efficient storage of data. The values stored can be processed quickly, which enhances the performance.

PostgreSQL supports a wide set of Data Types. Besides, users can create their own custom data type using CREATE TYPE SQL command. There are different categories of data types in PostgreSQL. They are discussed below.

Numeric Types

Numeric types consist of two-byte, four-byte, and eight-byte integers, four-byte and eight-byte floating-point numbers, and selectable-precision decimals. The following table lists the available types.

NameStorage SizeDescriptionRange
smallint2 bytessmall-range integer-32768 to +32767
integer4 bytestypical choice for integer-2147483648 to +2147483647
bigint8 byteslarge-range integer-9223372036854775808 to 9223372036854775807
decimalvariableuser-specified precision,exactup to 131072 digits before the decimal point; up to 16383 digits after the decimal point
numericvariableuser-specified precision,exactup to 131072 digits before the decimal point; up to 16383 digits after the decimal point
real4 bytesvariable-precision,inexact6 decimal digits precision
double precision8 bytesvariable-precision,inexact15 decimal digits precision
smallserial2 bytessmall autoincrementing integer1 to 32767
serial4 bytesautoincrementing integer1 to 2147483647
bigserial8 byteslarge autoincrementing integer1 to 9223372036854775807

Monetary Types

The money type stores a currency amount with a fixed fractional precision. Values of the numeric, int, and bigint data types can be cast to money. Using Floating point numbers is not recommended to handle money due to the potential for rounding errors.

NameStorage SizeDescriptionRange
money8 bytescurrency amount-92233720368547758.08 to +92233720368547758.07

Character Types

The table given below lists the general-purpose character types available in PostgreSQL.

S. No.Name & Description
1character varying(n), varchar(n)variable-length with limit
2character(n), char(n)fixed-length, blank padded
3textvariable unlimited length

Binary Data Types

The bytea data type allows storage of binary strings as in the table given below.

NameStorage SizeDescription
bytea1 or 4 bytes plus the actual binary stringvariable-length binary string

Date/Time Types

PostgreSQL supports a full set of SQL date and time types, as shown in table below. Dates are counted according to the Gregorian calendar. Here, all the types have resolution of 1 microsecond / 14 digits except date type, whose resolution is day.

NameStorage SizeDescriptionLow ValueHigh Value
timestamp [(p)] [without time zone ]8 bytesboth date and time (no time zone)4713 BC294276 AD
TIMESTAMPTZ8 bytesboth date and time, with time zone4713 BC294276 AD
date4 bytesdate (no time of day)4713 BC5874897 AD
time [ (p)] [ without time zone ]8 bytestime of day (no date)00:00:0024:00:00
time [ (p)] with time zone12 bytestimes of day only, with time zone00:00:00+145924:00:00-1459
interval [fields ] [(p) ]12 bytestime interval-178000000 years178000000 years

Boolean Type

PostgreSQL provides the standard SQL type Boolean. The Boolean data type can have the states truefalse, and a third state, unknown, which is represented by the SQL null value.

NameStorage SizeDescription
boolean1 bytestate of true or false

Enumerated Type

Enumerated (enum) types are data types that comprise a static, ordered set of values. They are equivalent to the enum types supported in a number of programming languages.

Unlike other types, Enumerated Types need to be created using CREATE TYPE command. This type is used to store a static, ordered set of values. For example compass directions, i.e., NORTH, SOUTH, EAST, and WEST or days of the week as shown below βˆ’

CREATE TYPE week AS ENUM ('Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun');

Enumerated, once created, can be used like any other types.

Geometric Type

Geometric data types represent two-dimensional spatial objects. The most fundamental type, the point, forms the basis for all of the other types.

NameStorage SizeRepresentationDescription
point16 bytesPoint on a plane(x,y)
line32 bytesInfinite line (not fully implemented)((x1,y1),(x2,y2))
lseg32 bytesFinite line segment((x1,y1),(x2,y2))
box32 bytesRectangular box((x1,y1),(x2,y2))
path16+16n bytesClosed path (similar to polygon)((x1,y1),…)
path16+16n bytesOpen path[(x1,y1),…]
polygon40+16nPolygon (similar to closed path)((x1,y1),…)
circle24 bytesCircle<(x,y),r> (center point and radius)

Network Address Type

PostgreSQL offers data types to store IPv4, IPv6, and MAC addresses. It is better to use these types instead of plain text types to store network addresses, because these types offer input error checking and specialized operators and functions.

NameStorage SizeDescription
cidr7 or 19 bytesIPv4 and IPv6 networks
inet7 or 19 bytesIPv4 and IPv6 hosts and networks
macaddr6 bytesMAC addresses

Bit String Type

Bit String Types are used to store bit masks. They are either 0 or 1. There are two SQL bit types: bit(n) and bit varying(n), where n is a positive integer.

Text Search Type

This type supports full text search, which is the activity of searching through a collection of natural-language documents to locate those that best match a query. There are two Data Types for this βˆ’

S. No.Name & Description
1tsvectorThis is a sorted list of distinct words that have been normalized to merge different variants of the same word, called as “lexemes”.
2tsqueryThis stores lexemes that are to be searched for, and combines them honoring the Boolean operators & (AND), | (OR), and ! (NOT). Parentheses can be used to enforce grouping of the operators.

UUID Type

A UUID (Universally Unique Identifiers) is written as a sequence of lower-case hexadecimal digits, in several groups separated by hyphens, specifically a group of eight digits, followed by three groups of four digits, followed by a group of 12 digits, for a total of 32 digits representing the 128 bits.

An example of a UUID is βˆ’ 550e8400-e29b-41d4-a716-446655440000

XML Type

The XML data type can be used to store XML data. For storing XML data, first you have to create XML values using the function xmlparse as follows βˆ’

XMLPARSE (DOCUMENT '<?xml version="1.0"?>
<tutorial>
<title>PostgreSQL Tutorial </title>
   <topics>...</topics>
</tutorial>')

XMLPARSE (CONTENT 'xyz<foo>bar</foo><bar>foo</bar>')

JSON Type

The json data type can be used to store JSON (JavaScript Object Notation) data. Such data can also be stored as text, but the json data type has the advantage of checking that each stored value is a valid JSON value. There are also related support functions available, which can be used directly to handle JSON data type as follows.

ExampleExample Result
array_to_json(‘{{1,5},{99,100}}’::int[])[[1,5],[99,100]]
row_to_json(row(1,’foo’)){“f1″:1,”f2″:”foo”}

Array Type

PostgreSQL gives the opportunity to define a column of a table as a variable length multidimensional array. Arrays of any built-in or user-defined base type, enum type, or composite type can be created.

Declaration of Arrays

Array type can be declared as

CREATE TABLE monthly_savings (
   name text,
   saving_per_quarter integer[],
   scheme text[][]
);

or by using the keyword “ARRAY” as

CREATE TABLE monthly_savings (
   name text,
   saving_per_quarter integer ARRAY[4],
   scheme text[][]
);

Inserting values

Array values can be inserted as a literal constant, enclosing the element values within curly braces and separating them by commas. An example is shown below βˆ’

INSERT INTO monthly_savings 
VALUES (β€˜Manisha’, 
β€˜{20000, 14600, 23500, 13250}’, 
β€˜{{β€œFD”, β€œMF”}, {β€œFD”, β€œProperty”}}’); 

Accessing Arrays

An example for accessing Arrays is shown below. The command given below will select the persons whose savings are more in second quarter than fourth quarter.

SELECT name FROM monhly_savings WHERE saving_per_quarter[2] > saving_per_quarter[4];

Modifying Arrays

An example of modifying arrays is as shown below.

UPDATE monthly_savings SET saving_per_quarter = '{25000,25000,27000,27000}'
WHERE name = 'Manisha';

or using the ARRAY expression syntax βˆ’

UPDATE monthly_savings SET saving_per_quarter = ARRAY[25000,25000,27000,27000]
WHERE name = 'Manisha';

Searching Arrays

An example of searching arrays is as shown below.

SELECT * FROM monthly_savings WHERE saving_per_quarter[1] = 10000 OR
saving_per_quarter[2] = 10000 OR
saving_per_quarter[3] = 10000 OR
saving_per_quarter[4] = 10000;

If the size of array is known, the search method given above can be used. Else, the following example shows how to search when the size is not known.

SELECT * FROM monthly_savings WHERE 10000 = ANY (saving_per_quarter);

Composite Types

This type represents a list of field names and their data types, i.e., structure of a row or record of a table.

Declaration of Composite Types

The following example shows how to declare a composite type

CREATE TYPE inventory_item AS (
   name text,
   supplier_id integer,
   price numeric
);

This data type can be used in the create tables as below βˆ’

CREATE TABLE on_hand (
   item inventory_item,
   count integer
);

Composite Value Input

Composite values can be inserted as a literal constant, enclosing the field values within parentheses and separating them by commas. An example is shown below βˆ’

INSERT INTO on_hand VALUES (ROW('fuzzy dice', 42, 1.99), 1000);

This is valid for the inventory_item defined above. The ROW keyword is actually optional as long as you have more than one field in the expression.

Accessing Composite Types

To access a field of a composite column, use a dot followed by the field name, much like selecting a field from a table name. For example, to select some subfields from our on_hand example table, the query would be as shown below βˆ’

SELECT (item).name FROM on_hand WHERE (item).price > 9.99;

You can even use the table name as well (for instance in a multitable query), like this βˆ’

SELECT (on_hand.item).name FROM on_hand WHERE (on_hand.item).price > 9.99;

Range Types

Range types represent data types that uses a range of data. Range type can be discrete ranges (e.g., all integer values 1 to 10) or continuous ranges (e.g., any point in time between 10:00am and 11:00am).

The built-in range types available include the following ranges βˆ’

  • int4range βˆ’ Range of integer
  • int8range βˆ’ Range of bigint
  • numrange βˆ’ Range of numeric
  • tsrange βˆ’ Range of timestamp without time zone
  • tstzrange βˆ’ Range of timestamp with time zone
  • daterange βˆ’ Range of date

Custom range types can be created to make new types of ranges available, such as IP address ranges using the inet type as a base, or float ranges using the float data type as a base.

Range types support inclusive and exclusive range boundaries using the [ ] and ( ) characters, respectively. For example ‘[4,9)’ represents all the integers starting from and including 4 up to but not including 9.

Object Identifier Types

Object identifiers (OIDs) are used internally by PostgreSQL as primary keys for various system tables. If WITH OIDS is specified or default_with_oids configuration variable is enabled, only then, in such cases OIDs are added to user-created tables. The following table lists several alias types. The OID alias types have no operations of their own except for specialized input and output routines.

NameReferencesDescriptionValue Example
oidanynumeric object identifier564182
regprocpg_procfunction namesum
regprocedurepg_procfunction with argument typessum(int4)
regoperpg_operatoroperator name+
regoperatorpg_operatoroperator with argument types*(integer,integer) or -(NONE,integer)
regclasspg_classrelation namepg_type
regtypepg_typedata type nameinteger
regconfigpg_ts_configtext search configurationEnglish
regdictionarypg_ts_dicttext search dictionarysimple

Pseudo Types

The PostgreSQL type system contains a number of special-purpose entries that are collectively called pseudo-types. A pseudo-type cannot be used as a column data type, but it can be used to declare a function’s argument or result type.

The table given below lists the existing pseudo-types.

S. No.Name & Description
1anyIndicates that a function accepts any input data type.
2anyelementIndicates that a function accepts any data type.
3anyarrayIndicates that a function accepts any array data type.
4anynonarrayIndicates that a function accepts any non-array data type.
5anyenumIndicates that a function accepts any enum data type.
6anyrangeIndicates that a function accepts any range data type.
7cstringIndicates that a function accepts or returns a null-terminated C string.
8internalIndicates that a function accepts or returns a server-internal data type.
9language_handlerA procedural language call handler is declared to return language_handler.
10fdw_handlerA foreign-data wrapper handler is declared to return fdw_handler.
11recordIdentifies a function returning an unspecified row type.
12triggerA trigger function is declared to return trigger.
13voidIndicates that a function returns no value.

Leave a Reply