CAST and TRY_CAST
View as MarkdownThe cast function and operator return a value converted to the specified
type. The try_cast function does the same, but returns NULL
instead of an error when the value cannot be converted.
Signatures
CAST ( <val> AS <type> )
| Syntax element | Description |
|---|---|
<val>
|
Any value you want to convert. |
AS <type>
|
The return value’s type. |
<val>::<type>
| Syntax element | Description |
|---|---|
<val>
|
Any value you want to convert. |
::<type>
|
The return value’s type. |
The following special syntax is permitted if val is a string literal:
<type> '<val>'
| Syntax element | Description |
|---|---|
<type>
|
The return value’s type. |
'<val>'
|
A string literal value. This special syntax is permitted if <val> is a string literal.
|
TRY_CAST ( <val> AS <type> )
| Syntax element | Description |
|---|---|
<val>
|
Any value you want to convert. |
AS <type>
|
The return value’s type. |
Return value
cast returns the value with the type specified by the type parameter.
try_cast returns the value with the type specified by the type parameter,
or NULL if the conversion fails. Its result is nullable whenever the
conversion can fail, even when the value being converted is not.
Details
Valid casts
Cast context defines when casts may occur.
| Cast context | Definition | Strictness |
|---|---|---|
| Implicit | Values are automatically converted. For example, when you add int4 to int8, the int4 value is automatically converted to int8. |
Least |
| Assignment | Values of one type are converted automatically when inserted into a column of a different type. | Medium |
| Explicit | You must invoke CAST deliberately. |
Most |
Casts allowed in less strict contexts are also allowed in stricter contexts. That is, implicit casts also occur by assignment, and both implicit casts and casts by assignment can be explicitly invoked.
| Source type | Return type | Cast context |
|---|---|---|
array1 |
text |
Assignment |
bigint |
bool |
Explicit |
bigint |
int |
Assignment |
bigint |
float |
Implicit |
bigint |
numeric |
Implicit |
bigint |
real |
Implicit |
bigint |
text |
Assignment |
bigint |
uint2 |
Assignment |
bigint |
uint4 |
Assignment |
bigint |
uint8 |
Assignment |
bool |
int |
Explicit |
bool |
text |
Assignment |
bytea |
text |
Assignment |
date |
text |
Assignment |
date |
timestamp |
Implicit |
date |
timestamptz |
Implicit |
float |
bigint |
Assignment |
float |
int |
Assignment |
float |
numeric2 |
Assignment |
float |
real |
Assignment |
float |
text |
Assignment |
float |
uint2 |
Assignment |
float |
uint4 |
Assignment |
float |
uint8 |
Assignment |
int |
bigint |
Implicit |
int |
bool |
Explicit |
int |
float |
Implicit |
int |
numeric |
Implicit |
int |
oid |
Implicit |
int |
real |
Implicit |
int |
text |
Assignment |
int |
uint2 |
Assignment |
int |
uint4 |
Assignment |
int |
uint8 |
Assignment |
interval |
text |
Assignment |
interval |
time |
Assignment |
jsonb |
bigint |
Explicit |
jsonb |
float |
Explicit |
jsonb |
int |
Explicit |
jsonb |
real |
Explicit |
jsonb |
numeric |
Explicit |
jsonb |
text |
Assignment |
list1 |
list |
Implicit |
list1 |
text |
Assignment |
map |
text |
Assignment |
mz_aclitem |
text |
Explicit |
numeric |
bigint |
Assignment |
numeric |
float |
Implicit |
numeric |
int |
Assignment |
numeric |
real |
Implicit |
numeric |
text |
Assignment |
numeric |
uint2 |
Assignment |
numeric |
uint4 |
Assignment |
numeric |
uint8 |
Assignment |
oid |
int |
Assignment |
oid |
text |
Explicit |
real |
bigint |
Assignment |
real |
float |
Implicit |
real |
int |
Assignment |
real |
numeric |
Assignment |
real |
text |
Assignment |
real |
uint2 |
Assignment |
real |
uint4 |
Assignment |
real |
uint8 |
Assignment |
record |
text |
Assignment |
smallint |
bigint |
Implicit |
smallint |
float |
Implicit |
smallint |
int |
Implicit |
smallint |
numeric |
Implicit |
smallint |
oid |
Implicit |
smallint |
real |
Implicit |
smallint |
text |
Assignment |
smallint |
uint2 |
Assignment |
smallint |
uint4 |
Assignment |
smallint |
uint8 |
Assignment |
text |
bigint |
Explicit |
text |
bool |
Explicit |
text |
bytea |
Explicit |
text |
date |
Explicit |
text |
float |
Explicit |
text |
int |
Explicit |
text |
interval |
Explicit |
text |
jsonb |
Explicit |
text |
list |
Explicit |
text |
map |
Explicit |
text |
numeric |
Explicit |
text |
oid |
Explicit |
text |
real |
Explicit |
text |
time |
Explicit |
text |
timestamp |
Explicit |
text |
timestamptz |
Explicit |
text |
uint2 |
Explicit |
text |
uint4 |
Assignment |
text |
uint8 |
Assignment |
text |
uuid |
Explicit |
time |
interval |
Implicit |
time |
text |
Assignment |
timestamp |
date |
Assignment |
timestamp |
text |
Assignment |
timestamp |
timestamptz |
Implicit |
timestamptz |
date |
Assignment |
timestamptz |
text |
Assignment |
timestamptz |
timestamp |
Assignment |
uint2 |
bigint |
Implicit |
uint2 |
float |
Implicit |
uint2 |
int |
Implicit |
uint2 |
numeric |
Implicit |
uint2 |
real |
Implicit |
uint2 |
text |
Assignment |
uint2 |
uint4 |
Implicit |
uint2 |
uint8 |
Implicit |
uint4 |
bigint |
Implicit |
uint4 |
float |
Implicit |
uint4 |
int |
Assignment |
uint4 |
numeric |
Implicit |
uint4 |
real |
Implicit |
uint4 |
text |
Assignment |
uint4 |
uint2 |
Assignment |
uint4 |
uint8 |
Implicit |
uint8 |
bigint |
Assignment |
uint8 |
float |
Implicit |
uint8 |
int |
Assignment |
uint8 |
real |
Implicit |
uint8 |
uint2 |
Assignment |
uint8 |
uint4 |
Assignment |
uuid |
text |
Assignment |
1 Arrays and lists are composite types subject to special constraints. See their respective type documentation for details.
2 Casting a float to a numeric can yield an imprecise result due to the floating point arithmetic involved in the conversion.
TRY_CAST
TRY_CAST accepts the same explicit casts as CAST, and returns NULL where
CAST would return an error: for example, text that does not parse as the
target type, a number that does not fit in the target type, or a JSON value of
the wrong kind. When the conversion succeeds, TRY_CAST and CAST return the
same value.
A CAST that fails on one row makes every query that needs that row’s value
fail, for as long as the row is present. In a materialized view or an indexed
view, that is every query against the view, whatever it selects. TRY_CAST
returns NULL for that row instead.
TRY_CAST only suppresses errors from the conversion itself. Errors raised
while computing the value being converted still propagate:
SELECT TRY_CAST(1 / 0 AS text);
ERROR: division by zero
A parameter whose type is inferred from TRY_CAST is decoded as the target
type when the statement is bound, so a bound value that does not convert is a
bind error rather than NULL. To get NULL instead, give the parameter an
explicit type:
SELECT TRY_CAST($1::text AS int);
Converting a value of a composite type (array,
list, or record) converts each
element. If any element fails to convert, TRY_CAST returns NULL for the
whole value rather than a value with NULL elements.
TRY_CAST accepts every explicit cast that CAST does, with these
differences, each of which is reported when the statement is planned:
-
TRY_CASTdoes not support the casts that look up objects in the catalog: casts to or fromregclass,regproc,regtype,aclitem, andmz_aclitem, other than those between theoidalias types and the integer types. -
A non-empty
ARRAY,LIST, orROWconstructor written directly insideTRY_CASTis typed on its own before the conversion, whereCASTwould type it from the target. Its elements must therefore already agree on a type:-- With a text column s, CAST(ARRAY[s, 2] AS int[]) plans, but this does not: -- "ARRAY types text and integer cannot be matched". SELECT TRY_CAST(ARRAY[s, 2] AS int[]) FROM t; -- Give the elements a common type instead. SELECT TRY_CAST(ARRAY[s, 2::text] AS int[]) FROM t;An empty
ARRAY,LIST, orMAPconstructor has no elements to convert, so it takes its type from the target as it does underCAST. -
A non-empty
MAPconstructor written directly insideTRY_CASTis rejected. It would be typed on its own like the other constructors, and there is no cast between twomaptypes to convert it afterward. Convert it withCASTor::instead.
Examples
SELECT INT '4';
?column?
----------
4
SELECT CAST (CAST (100.21 AS numeric(10, 2)) AS float) AS dec_to_float;
dec_to_float
--------------
100.21
SELECT 100.21::numeric(10, 2)::float AS dec_to_float;
dec_to_float
--------------
100.21
SELECT TRY_CAST('42' AS int) AS ok, TRY_CAST('forty-two' AS int) AS bad;
ok | bad
----+-----
42 |
Routing rows whose values do not convert, instead of failing the whole view:
CREATE VIEW parsed AS
SELECT raw, TRY_CAST(raw AS timestamp) AS ts
FROM events;
CREATE VIEW unparseable AS
SELECT raw FROM parsed WHERE ts IS NULL AND raw IS NOT NULL;