跪拜 Guibai
← All articles
Database

The Two Oracle-to-Postgres Migration Traps That Never Throw an Error

By 一只牛博 ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

Migration tools and syntax checkers catch the obvious incompatibilities. These two traps bypass every automated check because the SQL is syntactically valid and executes successfully. A team that trusts tooling alone will ship silently corrupted financial, inventory, or approval logic to production.

Summary

Two silent data-corruption traps sit at the top of any Oracle-to-KES migration checklist. The first is outer join elimination: a `WHERE` clause filter on a right-table column causes the optimizer to rewrite an outer join as an inner join, dropping rows that should be preserved. The SQL runs without error, but row counts shrink, and the mismatch only surfaces when financial reports or reconciliations fail post-launch. The fix is pushing the filter into the `ON` clause, but detection requires row-by-row comparison of pre- and post-migration results, not just syntax validation.

The second trap is whether an empty string equals NULL. KES in Oracle compatibility mode replicates Oracle's behavior of treating `''` as NULL, but this is governed by the `ora_input_emptystr_isnull` parameter. If operations later switches to PostgreSQL mode or flips that parameter, all legacy code relying on the Oracle assumption silently breaks. Both traps share a common thread: they produce no error messages, no failed migration report entries, and no warning signs until business logic produces wrong answers.

Takeaways
An outer join with a `WHERE` filter on a right-table column gets rewritten by the optimizer as an inner join, silently dropping rows.
The `(+)` Oracle syntax and ANSI `LEFT JOIN` behave identically under this optimization; switching syntax does not avoid the trap.
Moving the filter from `WHERE` into the `ON` clause preserves the outer join semantics and restores the correct row count.
KES in Oracle compatibility mode treats empty strings as NULL, matching Oracle behavior, but this depends on the `ora_input_emptystr_isnull` parameter being `on`.
Switching KES to PostgreSQL compatibility mode or toggling the empty-string parameter will silently break all code that assumes `''` equals NULL.
Migration verification must include row-count comparison for every outer-join query and explicit confirmation of the target database's compatibility mode and empty-string parameter.
Conclusions

Automated migration tools create a false sense of safety because they only flag syntax failures, not semantically equivalent queries that produce different results.

The optimizer's outer join elimination is correct by formal semantics but wrong by business intent, exposing a gap that no static analysis tool currently bridges.

Empty-string NULL handling is not a database property but a configuration property, meaning the same KES instance can behave like Oracle or like PostgreSQL depending on a single parameter.

Both traps are most dangerous in finance, inventory, and approval workflows where wrong row counts produce downstream reconciliation failures that are expensive to trace back to a migration change.

Concepts & terms
Outer join elimination
An optimizer transformation that rewrites an outer join as an inner join when a `WHERE` clause filter on the nullable side would discard all NULL-extended rows anyway, making the outer join semantically redundant but potentially violating the original query's intent to preserve all rows from the preserved table.
ora_input_emptystr_isnull
A KingbaseES configuration parameter that, when set to `on` in Oracle compatibility mode, causes zero-length strings (`''`) to be treated as NULL, replicating Oracle's behavior. When `off`, empty strings and NULL are distinct, matching standard PostgreSQL behavior.
Source: juejin.cn ↗ Google Translate ↗ Backup ↗