Files
awesome-copilot/skills/reviewing-oracle-to-postgres-migration/references/oracle-sysdate-sequences-dual.md
T
Paul Delannoy f7e8aaa2d8 'Oracle-to-PostgreSQL Migration Expert' Custom Agent: Update Custom Agent & Plugin & Skills (#2566)
* Enhance Oracle-to-PostgreSQL migration skills and documentation

- Update migration agent guidelines to prioritize extension tool usage for code migration.
- Refine migration phases with detailed steps for pre-migration review and schema migration.
- Add new reviewing skill references for PostgreSQL materialized view refresh and UNION ALL planner risks.
- Ensure consistency in collation handling and testing strategies across skills.

* - Review migration phases to ensure correct order of execution
- Add exit criteria to each migration phase
- Remove invocation of `ms-ossdata.vscode-pgsql` extension due to dependency on VSCode
- Update README.md to reflect changes in migration phases and exit criteria
- Update broken reference to custom agent in plugin.json

* Enhance downstream migration skills and following custom agent improvements

- Added new skill for migrating .NET data access code from Oracle to PostgreSQL.
- Updated README to include new migration skill.
- Improved existing skills with clearer file naming conventions and migration actions.
- Added reference documents for handling Oracle-specific functions and pagination.
- Created detailed guides for NVL, DECODE, ROWNUM, SYSDATE, and DUAL replacements.

* Clarify PostgreSQL schema immutability and stored procedure migration risks

* Update target schema path in migration documentation for clarity

* fix(skills): clarify Phase 3-only scope for Oracle test skills

Both Oracle test skills were ambiguously worded in ways that could
cause a model to invoke them during Phase 6 (PostgreSQL test migration)
instead of using them exclusively in Phase 3.

Key changes:
- Rewrite descriptions to explicitly state Phase 3-only usage and
  warn against invoking during Phase 6
- Replace "scaffold for Oracle first" with "Oracle only" to remove
  the false implication of a second PostgreSQL scaffolding step
- Replace "Tests validate behavior consistency when running against
  Oracle or PostgreSQL" with clear Oracle-only framing
- Rename "DB-agnostic assertions" → "Assertion portability" and
  explain the why (survive Phase 6 migration without rewrites)
- Fix datetime bullet in integration tests skill to use generic
  Oracle column precision language instead of PostgreSQL type syntax
- Name Oracle NuGet package explicitly (Oracle.ManagedDataAccess.Core)

* feat(oracle-to-postgres): gate Phase 1 on DDL presence; add DDL scan to Phase 2 risk analysis

- Phase 1 success criteria now requires Oracle DDL artifacts to be
  confirmed present at the recorded location before proceeding.
  If missing, the agent stops and prompts the user to provide them.

- Phase 2 risk analysis now explicitly scans DDL/Oracle/{ProjectName}/
  as supplemental context, summarising procedure complexity indicators
  (dynamic SQL, DBMS_* / UTL_* references, autonomous transactions,
  pipelined functions, BULK COLLECT/FORALL, REF CURSOR, TYPE bodies)
  rather than ingesting DDL files wholesale. This ensures schema-level
  migration risk is captured even when it isn't visible in application
  code alone.

* - Merge in latest 'main' changes
- Update custom agent plugin (eg resolve conflict and add new skill)
- Validate skills
- Run build

* chore(plugin.json): update version to 1.1.0

* feat(oracle-to-postgres): update version to 1.1.0 for migration expert plugin

* fix: add INOUT to ignore-words-list for PostgreSQL migration

---------

Co-authored-by: TCPrimedPaul <paul.delannoy@tc.gc.ca>
2026-08-11 12:47:51 +10:00

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 Oracle DATE type
  • SYSTIMESTAMP — returns the current timestamp with time zone

PostgreSQL:

  • Use NOW() or CURRENT_TIMESTAMP for timestamp with time zone
  • Use CURRENT_DATE for date only
  • Use LOCALTIMESTAMP for timestamp without time zone (closer to Oracle's SYSDATE semantics)
-- 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 DATE stores date and time; PostgreSQL DATE stores date only. If Oracle columns typed as DATE carry a time component, the PostgreSQL target column should be TIMESTAMP, not DATE.

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 → PostgreSQL currval('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 the INSERT

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 orafce is installed, it provides a DUAL view that makes Oracle-style FROM DUAL queries work without changes. This is a useful transitional aid but should not be relied on permanently.

Migration Actions

1. Stored Procedures

  • Replace all SYSDATE / SYSTIMESTAMP references with NOW() or CURRENT_TIMESTAMP (verify column type — use LOCALTIMESTAMP if the target is TIMESTAMP WITHOUT TIME ZONE)
  • Replace sequence_name.NEXTVAL with nextval('sequence_name')
  • Replace sequence_name.CURRVAL with currval('sequence_name')
  • Remove FROM DUAL from all expression-only SELECT statements

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.md for Npgsql-specific behavior)
  • Verify sequence-dependent IDs are correctly populated in assertions