3.2 KiB
Oracle to PostgreSQL: Date Functions, Sequences, and DUAL
Problem
Oracle relies on several built-in constructs — SYSDATE, SYSTIMESTAMP, sequence NEXTVAL syntax, and the DUAL dummy table — that do not exist in PostgreSQL. Each requires a direct substitution.
SYSDATE and SYSTIMESTAMP
Oracle:
SYSDATE— returns the current date and time (no time zone) as an OracleDATEtypeSYSTIMESTAMP— returns the current timestamp with time zone
PostgreSQL:
- Use
NOW()orCURRENT_TIMESTAMPfor timestamp with time zone - Use
CURRENT_DATEfor date only - Use
LOCALTIMESTAMPfor timestamp without time zone (closer to Oracle'sSYSDATEsemantics)
-- Oracle
SELECT SYSDATE FROM DUAL;
INSERT INTO t (created_at) VALUES (SYSDATE);
-- PostgreSQL
SELECT NOW();
INSERT INTO t (created_at) VALUES (NOW());
-- or, if the column is DATE-only:
INSERT INTO t (created_at) VALUES (CURRENT_DATE);
Warning: Oracle
DATEstores date and time; PostgreSQLDATEstores date only. If Oracle columns typed asDATEcarry a time component, the PostgreSQL target column should beTIMESTAMP, notDATE.
Sequence NEXTVAL Syntax
Oracle:
SELECT my_sequence.NEXTVAL FROM DUAL;
INSERT INTO t (id) VALUES (my_sequence.NEXTVAL);
PostgreSQL:
SELECT nextval('my_sequence');
INSERT INTO t (id) VALUES (nextval('my_sequence'));
Key differences:
- PostgreSQL
nextval()is a function call with the sequence name as a quoted string argument - Oracle uses dot notation:
sequence_name.NEXTVAL - Oracle also has
CURRVAL→ PostgreSQLcurrval('sequence_name') - If the column uses a
DEFAULT nextval(...)constraint (set during Phase 4 DDL migration), application code can omit the sequence call entirely and omit the column from theINSERT
DUAL Table
Oracle requires a FROM DUAL clause in SELECT statements that evaluate expressions without a real table. PostgreSQL does not have DUAL — expressions can be selected without a FROM clause.
-- Oracle
SELECT 1 + 1 FROM DUAL;
SELECT SYSDATE FROM DUAL;
SELECT my_sequence.NEXTVAL FROM DUAL;
-- PostgreSQL
SELECT 1 + 1;
SELECT NOW();
SELECT nextval('my_sequence');
orafce extension: If
orafceis installed, it provides aDUALview that makes Oracle-styleFROM DUALqueries work without changes. This is a useful transitional aid but should not be relied on permanently.
Migration Actions
1. Stored Procedures
- Replace all
SYSDATE/SYSTIMESTAMPreferences withNOW()orCURRENT_TIMESTAMP(verify column type — useLOCALTIMESTAMPif the target isTIMESTAMP WITHOUT TIME ZONE) - Replace
sequence_name.NEXTVALwithnextval('sequence_name') - Replace
sequence_name.CURRVALwithcurrval('sequence_name') - Remove
FROM DUALfrom all expression-onlySELECTstatements
2. Application Code (inline SQL strings)
Search C# string literals for SYSDATE, SYSTIMESTAMP, .NEXTVAL, .CURRVAL, and FROM DUAL. Apply the same substitutions.
3. Tests
- Verify datetime assertions use timezone-safe comparisons (see
oracle-to-postgres-timestamp-timezone.mdfor Npgsql-specific behavior) - Verify sequence-dependent IDs are correctly populated in assertions