Data Types for PostgreSQL

Overview of Data Types

Every column in a table has a name and a data type. The data type tells PostgreSQL how much physical storage to set aside for the column and the form in which the data is stored. This section includes information about PostgreSQL data types, null and default values, and data conversions.

For more information about PostgreSQL data types and to determine which data types are available for your version of PostgreSQL, see your PostgreSQL documentation.

PostgreSQL Null Values

PostgreSQL has a special value called NULL. A PostgreSQL NULL value means an absence of information and is analogous to a SAS missing value. When SAS/ACCESS reads a PostgreSQL NULL value, it interprets it as a SAS missing value.

You can define a column in a PostgreSQL table so that it requires data. To do this in SQL, you specify a column as NOT NULL. This tells SQL to allow a row to be added to a table only if a value exists for the field. For example, NOT NULL assigned to the CUSTOMER field in the SASDEMO.CUSTOMER table does not allow a row to be added unless there is a value for CUSTOMER. When creating a table with SAS/ACCESS, you can use the DBNULL= data set option to indicate whether NULL is a valid value for specified columns.

You can also specify PostgreSQL columns as NOT NULL DEFAULT. For more information about using the NOT NULL DEFAULT value, see your PostgreSQL documentation.

Once you know whether a PostgreSQL column enables NULLs or the host system provides a default value for a column that is specified as NOT NULL WITH DEFAULT, you can write selection criteria and enter values to update a table. Unless a column is specified as NOT NULL or NOT NULL DEFAULT, it allows NULL values.

For more information about how SAS handles NULL values, see Potential Result Set Differences When Processing Null Data.

To control how SAS missing character values are handled, use the NULLCHAR= and NULLCHARVAL= data set options.

Working with Long Character Values in PostgreSQL

The PostgreSQL open-source driver automatically assigns a length of 255 characters to varying-length character variables, such as the VARCHAR(n) data type. Therefore, if you know that character data in a data set is longer than 255 characters, you should specify the MaxVarcharSize attribute for the CONOPTS= LIBNAME option when you connect to your PostgreSQL library. Specify a value for MaxVarcharSize that is as large as the longest column value to ensure that you retrieve all of the available data.

The following LIBNAME statement, sample tables, and SQL query would create a new data set that does not truncate the character data from the Testb data set.

libname x postgres preserve_col_names=no 
  preserve_tab_names=no database=mydb1 dbmax_text=32767 
  server='myserver' port=5432 user=pgadmin password='pgpwd' 
  conopts='MaxVarcharSize=300;';
 
/* Create example tables Testa and Testb */
proc sql; 
create table testa(idnum int, myflag int, col1 varchar(20))
create table testb(idnum int, col1 varchar(300))

insert into testa values (1, 1, 'from a 1')
insert into testa values (2, 0, 'from a 2')

insert into testb values (1, 'from b 1*from b 1*from b 1*from b 1*from b 1*
   from b 1*from b 1*from b 1*from b 1*from b 1*from b 1*from b 1*from b 1*
   from b 1*from b 1*from b 1*from b 1*from b 1*from b 1*from b 1*from b 1*
   from b 1*from b 1*from b 1*from b 1*from b 1*from b 1*from b 1*from b 1*
   from b 1*274')
insert into testb values (2, 'from b 2*from b 2*from b 2*from b 2*from b 2*
   from b 2*from b 2*from b 2*from b 2*from b 2*from b 2*from b 2*from b 2*
   from b 2*from b 2*from b 2*from b 2*from b 2*from b 2*from b 2*from b 2*
   from b 2*from b 2*from b 2*from b 2*from b 2*from b 2*from b 2*from b 2*
   from b 2*274')
quit;

/* Verify that data is not truncated */
proc sql;
create table work.SASTEST as 
   select case when myflag = 1 then a.col1 else b.col1 end as 
      col1 from x.testa a, x.testb b
      where a.idnum = b.idnum;

/* Select the end of col1 from position 200 to the end to show that all of */
/* the data is retrieved                                                   */
select substr(col1, 200) from work.SASTEST;
quit;

The output from the final SELECT statement appears as shown here. This statement selects a substring starting at column position 200 from the Col1 value.

rom b 2*from b 2*from b 2*from b 2*from b 2*from b 2*from b 2*from b 2*274

You can see that the end of the value does include the ‘*274’ from the end of the VARCHAR value.

LIBNAME Statement Data Conversions

This table shows the default formats that SAS/ACCESS Interface to PostgreSQL assigns to SAS variables when using the LIBNAME statement to read from a PostgreSQL table. These default formats are based on PostgreSQL column attributes. SAS/ACCESS does not support PostgreSQL data types that do not appear in this table.

LIBNAME Statement: Default SAS Formats for PostgreSQL Data Types

PostgreSQL Data Type

ODBC Data Type

Default SAS Format

CHAR(n)1

SQL_CHAR

$w.

VARCHAR(n)1

SQL_LONGCHAR(n)

BYTEA

SQL_VARBINARY

$w4

SQL_LONGVARBINARY3

DECIMAL

SQL_DECIMAL

w or w.d or none if you do not specify w and d2

NUMERIC

SQL_NUMERIC

INTEGER

SQL_INTEGER

11.

SMALLINT

SQL_SMALLINT

6.

SQL_TINYINT

4.

BIT(1)

SQL_BIT

1.

REAL

SQL_REAL

none

FLOAT

SQL_FLOAT

DOUBLE PRECISION

SQL_DOUBLE

BIGINT

SQL_BIGINT

20.

INTERVAL

SQL_INTERVAL

$w.

UUID

SQL_GUID

$w.

DATE

SQL_TYPE_DATE

DATE9.

1 n in PostgreSQL character data types is equivalent to w in SAS formats.
2 m and n in PostgreSQL numeric data types are equivalent to w and d in SAS formats.
3 This conversion occurs when you specify "ByteAsLongVarBinary=1" with the CONOPS= LIBNAME option.
4 Because the Postgres ODBC driver does the actual conversion, this field is displayed as if the $HEXw. format were applied.

The following table shows the default data types that SAS/ACCESS Interface to PostgreSQL uses when creating tables. The PostgreSQL engine lets you specify nondefault data types by using the DBTYPE= data set option.

LIBNAME Statement: Default SAS Formats for PostgreSQL Data Types When Creating Tables

PostgreSQL Data Type

ODBC Data Type

Default SAS Format

NUMERIC(m,n)2

SQL_DOUBLE or SQL_NUMERIC using m,n if the DBMS allows it

w.d

VARCHAR(n)1

SQL_VARCHAR using n

$w.

TIMESTAMP3

SQL_TIMESTAMP

DATETIME formats

DATE

SQL_DATE

DATE formats

TIME

SQL_TIME

TIME formats

1 n in PostgreSQL character data types is equivalent to w in SAS formats.
2 m and n in PostgreSQL numeric data types are equivalent to w and d in SAS formats.
3 Although the PostgreSQL engine supports TIMESTAMP, it has no TIMESTAMP WITH TIMEZONE data type that maps to the corresponding Postgres data type.
Last updated: February 3, 2026