Case q04 · fact
Our app relies on empty string being NULL in VARCHAR2 columns. Which Azure targets keep that behaviour?
Expected: None of Azure SQL DB/MI or PostgreSQL treat '' as NULL; flags this as a semantic difference requiring code review; Oracle Database@Azure keeps Oracle semantics.
The dataset had no mapping from empty-string-equals-NULL to Oracle Database@Azure. The mapping was added and the question re-run. The re-run is shown at the bottom; the frozen totals are not updated.
No tools
larger model · 1 turn · 21 s · 16.5k in / 2.0k out✓ verdict ✗ grounded ✗ cited
Grader: Correct verdict; many uncited specifics like edb_redwood_strings and LENGTH
Answer
Only Azure targets that actually run Oracle Database keep '' = NULL: Oracle Database@Azure (Exadata or Autonomous) and Oracle on Azure VMs. Azure SQL Database, Azure SQL Managed Instance, SQL Server on a VM and Azure Database for PostgreSQL all treat '' as a real value that is not NULL. None of them has a setting to change that.
| Target | '' becomes NULL? |
Notes |
|---|---|---|
| Oracle Database@Azure (Exadata Database Service, Autonomous Database) | ✅ Yes | Real Oracle running in Azure datacenters. Same behaviour, including 23ai. https://learn.microsoft.com/azure/oracle/oracle-db/database-overview |
| Oracle on Azure VMs (you manage it) | ✅ Yes | Same engine, so the same behaviour. https://learn.microsoft.com/azure/virtual-machines/workloads/oracle/oracle-overview |
| Azure SQL Database / Managed Instance / SQL Server on a VM | ❌ No | '' and NULL are different values. ANSI_NULLS and CONCAT_NULL_YIELDS_NULL don't change this. |
| Azure Database for PostgreSQL – Flexible Server | ❌ No | Standard PostgreSQL behaviour. The orafce extension adds Oracle-style functions but doesn't change how '' is stored. https://www.postgresql.org/docs/current/functions-comparison.html |
| EDB Postgres Advanced Server (on a VM or EDB's managed service) | ❌ No, as far as I know | Its Oracle-compatibility settings (e.g. edb_redwood_strings) change how NULL behaves in || concatenation. I don't believe any of them turn stored '' into NULL. Test it before relying on it. |
Where things break if you move to SQL Server or PostgreSQL:
WHERE col IS NULLstops finding rows that were written as''. The same applies toNVL/COALESCE, and to NOT NULL constraints, which will now accept''.- Length:
LENGTH('')returns NULL in Oracle but 0 in PostgreSQL. SQL Server'sLEN('')also returns 0. - Concatenation:
NULL || 'x'gives'x'in Oracle but NULL in PostgreSQL. In SQL Server,+gives NULL by default.CONCAT()treats NULL as empty on both. - Application and ORM code that sends
''expecting it to be stored as NULL (common with JDBC and .NET binds). - Migration tools: Microsoft's SQL Server Migration Assistant (SSMA) and ora2pg (for PostgreSQL) convert the schema and code, but they won't rewrite this logic for you. Your existing data is fine, because Oracle never stored
''in the first place. The risk is new rows written after cutover.
How to handle it if you still move to SQL Server or PostgreSQL:
- Add a BEFORE INSERT/UPDATE trigger (on SQL Server, an INSTEAD OF trigger) that sets
col = NULLIF(col, ''). Or do the same conversion in the data-access layer, which scales better. - Add
CHECK (col <> '')constraints so any''that slips through fails loudly. - Search the code for
IS NULL,NVL,LENGTH,||andDECODEon string columns, and add regression tests for the''cases.
Recommendation: if this behaviour runs throughout the app and you don't want to refactor, go with Oracle Database@Azure or Oracle on VMs. If you're moving off Oracle to cut licence costs, treat ''-vs-NULL as a separate workstream with its own tests. It's one of the most common reasons these migrations go wrong after cutover.
Keyword search
larger model · 1 turn · 14 s · 18.8k in / 1.3k out✗ verdict ✓ grounded ✗ cited
Grader: Headline 'none'; only hedges on Oracle Database@Azure with 'presumably'
8 keyword-search passages
caveat_empty-string-sqlserver-not-nullscore 28.686feature_empty-string-nullscore 22.67mapping_empty-string-null--azure-pg-flexscore 20.166mapping_empty-string-null--azure-sql-dbscore 19.12source_orafce-readmescore 16.265target_ora2pgscore 15.56mapping_varchar2-byte-semantics--azure-pg-flexscore 14.356caveat_empty-string-postgres-not-nullscore 13.349
Answer
Verdict: None of the Azure targets these passages cover treats '' as NULL natively. Azure SQL / SQL Server and Azure Database for PostgreSQL Flexible Server both keep an empty string as a real value, separate from NULL. You can get Oracle's behaviour back on either one, but only by changing code or data.
Azure SQL Database and SQL Server-family targets [1][4]
- An empty string is stored as a zero-length value. Microsoft's documentation says a null value is different from an empty or zero value.
- What changes after migration:
- Inserting
''now stores a non-null row. IS NULLno longer matches those rows.NOT NULLcolumns now accept'', where Oracle rejected it.
- Inserting
- How to work around it:
- Pick one policy: either convert
''to NULL when writing (in the application or a trigger), or useNULLIFin queries to treat the two as the same. - Add CHECK constraints or triggers that reject
''on columns where Oracle'sNOT NULLused to do that. - Turn on SSMA's ISNULL-in-concatenation option.
- Review every
= ''and<> ''comparison. In Oracle these were never true, so they now behave differently.
- Pick one policy: either convert
Azure Database for PostgreSQL Flexible Server [3][8]
- PostgreSQL separates
''from NULL in the same way SQL Server does. You have two options:- Ora2Pg
NULL_EQUAL_EMPTY: rewritesIS NULLandIS NOT NULLtests intocoalesce()-based checks so the converted code behaves like Oracle [6]. - Convert the data when it's written: use orafce's
replace_empty_stringstrigger or an application rule. Ora2Pg's documentation recommends this if you can change the application.
- Ora2Pg
- Rewrite
NVL(col,'x')ascoalesce(nullif(col,''),'x'), and testNOT NULLcolumns. - orafce's
varchar2type only changes length counting to bytes. It does not make''behave as NULL, and orafce's own README says empty strings differ from NULL in PostgreSQL [5][7].
Two more points
- Oracle itself says applications shouldn't depend on this behaviour and that it may change in future releases. It is still unchanged as of 26ai [2]. Every empty-string literal and every
IS NULLtest on a character column needs review, whichever target you pick. - These passages don't cover running Oracle Database itself on Azure (for example Oracle Database@Azure or Oracle on Azure VMs). I can't confirm from them which targets would keep the behaviour unchanged, although running Oracle itself presumably would.
Sources: orafce README, https://github.com/orafce/orafce/blob/master/README.asciidoc. The other passages [1]–[4] and [6]–[8] came without URLs.
Sanity Context · GROQ
smaller model · 6 turns · 31 s · 35.5k in / 2.5k out✗ verdict ✓ grounded ✗ cited
Grader: Headline 'none'; Oracle@Azure only hedged with 'presumably'
5 tool calls
- initial_context on groq · 4,126 chars back
- groq_query on groq · 3,384 chars back
*[_type=="oracleFeature" && (name match "*empty*" || name match "*null*" || name match "*NULL*" || name match "*VARCHAR*")]{_id, name, slug, category, summary} - groq_query on groq · 358 chars back
*[_type=="glossary" && (term match "*empty*" || term match "*null*" || term match "*NULL*")]{_id, term, definition, alsoKnownAs} - groq_query on groq · 4,092 chars back
*[_type=="mapping" && oracleFeature._ref=="feature_empty-string-null"]{ _id, fidelity, effort, rationale, appliesToOracleVersions, "azureTarget": azureTarget->{name, slug, service}, "sources": sources[]->{title, url}, "caveats": *[_type=="caveat" && references(^._id)]{ severity, statement, appliesTo, firsthand, "evidence": evidence->{title, url, publisher} } } - groq_query on groq · 761 chars back
*[_type=="dispute" && (claimA->mapping->oracleFeature._ref=="feature_empty-string-null" || claimB->mapping->oracleFeature._ref=="feature_empty-string-null")]{ title, whatDisagrees, resolution, "claimA": claimA->{statement, "evidence": evidence->{title,url,publisher}}, "claimB": claimB->{statement, "evidence": evidence->{title,url,publisher}}, "resolvedBy": resolvedBy->{title,url} }
Answer
Verdict: None. The dataset shows no Azure target that preserves Oracle's "empty string = NULL" behavior for VARCHAR2 natively — only workarounds exist for the two mapped targets.
Feature
Empty string equals NULL — "Oracle treats a character value of zero length as NULL... Oracle's SQL reference explicitly says this may not remain true in future releases and advises applications not to depend on it." Documented, unchanged as of 26ai, applies to Oracle 11.2–26ai.
Mapped Azure targets (both fidelity = workaround)
Azure SQL Database
- Fidelity: workaround, Effort: M
- "Oracle stores a zero-length VARCHAR2 as NULL... SQL Server keeps '' as a real value distinct from NULL... After migration the same INSERT of '' produces a non-null row, IS NULL predicates stop matching it, and NOT NULL constraints that used to reject '' now accept it." — NULL and UNKNOWN (Transact-SQL) (Microsoft)
- Caveat (major): "In SQL Server and Azure SQL an empty string '' is a stored zero-length value that is distinct from NULL." — same source.
- Applies to Oracle 11.2–26ai.
Azure Database for PostgreSQL Flexible Server
- Fidelity: workaround, Effort: M
- "PostgreSQL distinguishes '' from NULL exactly as SQL Server does. Ora2Pg offers NULL_EQUAL_EMPTY, which rewrites IS NULL and IS NOT NULL tests into coalesce()-based checks so converted code keeps Oracle's behaviour... orafce adds a trigger function that replaces empty strings with NULL on write." — Ora2Pg documentation (community), orafce README
- Caveat (major): "PostgreSQL treats '' as a non-NULL value." — same Ora2Pg source.
- Applies to Oracle 11.2–26ai.
Gaps
- No dispute is recorded on this feature.
- The dataset has no mapping entry for this feature against Oracle Database@Azure or Oracle on Azure VM (both run real Oracle, which would presumably preserve the behavior natively) — the dataset has no evidence either way for those targets.
- No other azureTarget (Azure SQL Managed Instance, Fabric, etc.) has a mapping for this feature in the dataset.
Bottom line for your app: if you move VARCHAR2-empty-string-as-NULL logic to Azure SQL Database or Azure PostgreSQL Flexible Server, the native behavior does not carry over — you need the cited workarounds (application-level coalesce rewrites, Ora2Pg's NULL_EQUAL_EMPTY, or orafce's empty-to-NULL trigger). No mapped target reproduces the behavior with exact fidelity per this dataset.
GROQ + Knowledge Base
smaller model · 7 turns · 63 s · 64.8k in / 2.6k out✗ verdict ✓ grounded ✓ cited
Grader: Correct on SQL and PostgreSQL; won't answer for Oracle@Azure
6 tool calls
- initial_context on groq · 4,126 chars back
- initial_context on kb · 7,679 chars back
- groq_query on groq · 3,360 chars back
*[_type=="oracleFeature" && (name match "*empty*" || name match "*NULL*" || name match "*VARCHAR2*")]{_id, name, slug, category, summary} - groq_query on groq · 4,018 chars back
*[_type=="mapping" && oracleFeature._ref=="feature_empty-string-null"]{ _id, fidelity, effort, rationale, appliesToOracleVersions, "azureTarget": azureTarget->{name, slug, service}, "sources": sources[]->{title, url}, "caveats": *[_type=="caveat" && references(^._id)]{ severity, statement, appliesTo, firsthand, "evidence": evidence->{title, url} } } - groq_query on groq · 1,081 chars back
*[_type=="oracleFeature" && slug.current=="empty-string-null"]{ "sources": sources[]->{title, url}, "disputes": *[_type=="dispute" && (claimA->mapping->oracleFeature._ref==^._id || claimB->mapping->oracleFeature._ref==^._id)]{title, whatDisagrees, resolution, "claimA": claimA->{statement, "evidence": evidence->{title,url}}, "claimB": claimB->{statement, "evidence": evidence->{title,url}}, "resolvedBy": resolvedBy->{title,url}} } - knowledge_base_read on kb · 2,832 chars back
{ "knowledgeBase": "kb6MdvV3ZA3Q", "paths": [ "oracle_concepts/terminology" ] }
Answer
Verdict: None of the mapped Azure targets preserve Oracle's "empty string = NULL" behaviour natively. The dataset records this as a "workaround" (i.e., no native equivalent — must be rebuilt via extra logic) for both targets it covers, and has no mapping entry at all for the other Azure targets (Azure SQL Managed Instance, Oracle Database@Azure, Oracle on Azure VMs).
Scoped facts — Oracle feature: Empty string equals NULL (Nulls (SQL Language Reference 19c)), applies to Oracle 11.2 through 26ai (long-standing, undeprecated, but Oracle itself warns not to rely on it).
Azure SQL Database — fidelity workaround, effort M. "Oracle stores a zero-length VARCHAR2 as NULL... SQL Server keeps '' as a real value distinct from NULL... After migration the same INSERT of '' produces a non-null row, IS NULL predicates stop matching it, and NOT NULL constraints that used to reject '' now accept it." — NULL and UNKNOWN (Transact-SQL), SSMA for Oracle: Project Settings (Conversion). Caveat (major): "In SQL Server and Azure SQL an empty string '' is a stored zero-length value that is distinct from NULL" — Microsoft's NULL documentation states a null value is different from an empty or zero value.
Azure Database for PostgreSQL Flexible Server — fidelity workaround, effort M. "PostgreSQL distinguishes '' from NULL exactly as SQL Server does." Ora2Pg's
NULL_EQUAL_EMPTYdirective can rewriteIS NULL/IS NOT NULLtests intocoalesce()-based checks to reproduce Oracle's behaviour, though Ora2Pg's own docs recommend instead converting empty strings to NULL if the application can be changed;orafceoffers a trigger to replace empty strings with NULL on write. — Ora2Pg documentation, orafce README. Caveat (major): "PostgreSQL treats '' as a non-NULL value" — same sources.
Gap: The dataset has no mapping or caveat entry for this feature against Azure SQL Managed Instance, Oracle Database@Azure, or Oracle on Azure VMs. I can't say whether those preserve the behaviour — no evidence either way in this dataset. (Note: no dispute record touches this feature either.)
Practical implication: since fidelity is "workaround" rather than "exact" or "partial" on both covered targets, keeping the empty-string-is-NULL behaviour is not automatic on either — it requires explicit rewriting of IS NULL checks, coalesce-style logic, or trigger-based normalization, per the citations above.
After the fix
No tools
larger model · 1 turn · 21 s · 16.5k in / 2.0k out✓ verdict ✗ grounded ✗ cited
Grader: Correct verdict; EDB, LENGTH, 23ai and VM claims unsupported
Answer
Only Azure targets that actually run Oracle Database keep '' = NULL: Oracle Database@Azure (Exadata or Autonomous) and Oracle on Azure VMs. Azure SQL Database, Azure SQL Managed Instance, SQL Server on a VM and Azure Database for PostgreSQL all treat '' as a real value that is not NULL. None of them has a setting to change that.
| Target | '' becomes NULL? |
Notes |
|---|---|---|
| Oracle Database@Azure (Exadata Database Service, Autonomous Database) | ✅ Yes | Real Oracle running in Azure datacenters. Same behaviour, including 23ai. https://learn.microsoft.com/azure/oracle/oracle-db/database-overview |
| Oracle on Azure VMs (you manage it) | ✅ Yes | Same engine, so the same behaviour. https://learn.microsoft.com/azure/virtual-machines/workloads/oracle/oracle-overview |
| Azure SQL Database / Managed Instance / SQL Server on a VM | ❌ No | '' and NULL are different values. ANSI_NULLS and CONCAT_NULL_YIELDS_NULL don't change this. |
| Azure Database for PostgreSQL – Flexible Server | ❌ No | Standard PostgreSQL behaviour. The orafce extension adds Oracle-style functions but doesn't change how '' is stored. https://www.postgresql.org/docs/current/functions-comparison.html |
| EDB Postgres Advanced Server (on a VM or EDB's managed service) | ❌ No, as far as I know | Its Oracle-compatibility settings (e.g. edb_redwood_strings) change how NULL behaves in || concatenation. I don't believe any of them turn stored '' into NULL. Test it before relying on it. |
Where things break if you move to SQL Server or PostgreSQL:
WHERE col IS NULLstops finding rows that were written as''. The same applies toNVL/COALESCE, and to NOT NULL constraints, which will now accept''.- Length:
LENGTH('')returns NULL in Oracle but 0 in PostgreSQL. SQL Server'sLEN('')also returns 0. - Concatenation:
NULL || 'x'gives'x'in Oracle but NULL in PostgreSQL. In SQL Server,+gives NULL by default.CONCAT()treats NULL as empty on both. - Application and ORM code that sends
''expecting it to be stored as NULL (common with JDBC and .NET binds). - Migration tools: Microsoft's SQL Server Migration Assistant (SSMA) and ora2pg (for PostgreSQL) convert the schema and code, but they won't rewrite this logic for you. Your existing data is fine, because Oracle never stored
''in the first place. The risk is new rows written after cutover.
How to handle it if you still move to SQL Server or PostgreSQL:
- Add a BEFORE INSERT/UPDATE trigger (on SQL Server, an INSTEAD OF trigger) that sets
col = NULLIF(col, ''). Or do the same conversion in the data-access layer, which scales better. - Add
CHECK (col <> '')constraints so any''that slips through fails loudly. - Search the code for
IS NULL,NVL,LENGTH,||andDECODEon string columns, and add regression tests for the''cases.
Recommendation: if this behaviour runs throughout the app and you don't want to refactor, go with Oracle Database@Azure or Oracle on VMs. If you're moving off Oracle to cut licence costs, treat ''-vs-NULL as a separate workstream with its own tests. It's one of the most common reasons these migrations go wrong after cutover.
Keyword search
larger model · 1 turn · 12 s · 18.9k in / 1.2k out✓ verdict ✓ grounded ✗ cited
Grader: Correct: only DB@Azure keeps it; SQL/PG workarounds, grounded
8 keyword-search passages
caveat_empty-string-sqlserver-not-nullscore 28.556feature_empty-string-nullscore 22.551mapping_empty-string-null--azure-pg-flexscore 19.939mapping_empty-string-null--azure-sql-dbscore 18.932mapping_empty-string-null--oracle-db-at-azurescore 18.127source_orafce-readmescore 16.099target_ora2pgscore 15.422mapping_varchar2-byte-semantics--azure-pg-flexscore 14.135
Answer
Only Oracle Database@Azure keeps this behaviour. Azure SQL and Azure Database for PostgreSQL Flexible Server both treat '' and NULL as different values, so you'd need workarounds on either.
Oracle Database@Azure: works as-is [5]
- You still run Oracle Database (Exadata Database Service, Base Database Service or Autonomous Database), just in Azure datacenters. An empty VARCHAR2 is still stored and compared as NULL.
- Your existing NULL-handling code doesn't need rewriting.
- Record this dependency in your migration inventory. A later move to Azure SQL or PostgreSQL would bring the problem back.
Azure SQL Database (and Azure SQL generally): behaviour changes [1][4]
''is stored as a real zero-length value, not NULL. Microsoft's docs say a null value is different from an empty or zero value.- What breaks:
- Inserting
''now creates a non-null row. IS NULLno longer matches those rows.- NOT NULL columns now accept
''. = ''and<> ''comparisons, which never matched in Oracle, start matching.
- Inserting
- Fixes:
- Choose one policy: either convert
''to NULL when writing (in the app or a trigger), or treat them as equal in queries withNULLIF. - Add CHECK constraints or triggers that reject
''where NOT NULL used to block it. - Turn on SSMA's ISNULL-in-concatenation option so
NULL || 'x'gives the same result as in Oracle.
- Choose one policy: either convert
Azure Database for PostgreSQL Flexible Server: behaviour changes [3][6][7]
- PostgreSQL also treats
''and NULL as different. - Fixes (estimated as medium effort):
- Ora2Pg
NULL_EQUAL_EMPTY: rewritesIS NULLandIS NOT NULLtests intocoalesce()checks. Ora2Pg's documentation recommends converting empty strings to NULL instead, if you can change the application. - orafce trigger: its
replace_empty_stringstrigger turns''into NULL on write. Installing orafce alone doesn't fix this; its README says empty strings still differ from NULL in PostgreSQL. - Rewrite
NVL(col,'x')ascoalesce(nullif(col,''),'x'), and test NOT NULL columns.
- Ora2Pg
Longer-term caveat [2][5]
Oracle has behaved this way through 26ai, but its SQL reference warns this may change in future releases and tells applications not to rely on it. Even on Oracle Database@Azure, plan to review empty-string literals and IS NULL tests on character columns eventually.
Sources:
- orafce README: https://github.com/orafce/orafce/blob/master/README.asciidoc
- The other passages had no URLs.
Sanity Context · GROQ
smaller model · 4 turns · 29 s · 32.6k in / 1.7k out✓ verdict ✓ grounded ✓ cited
Grader: Correct verdict with workarounds; grounded; code review only implied
3 tool calls
- initial_context on groq · 4,126 chars back
- groq_query on groq · 614 chars back
*[_type=="oracleFeature" && (name match "*empty*" || name match "*NULL*" || name match "*VARCHAR*")]{_id, name, "slug": slug.current, category} - groq_query on groq · 5,738 chars back
*[_type=="oracleFeature" && slug.current=="empty-string-null"][0]{ _id, name, category, introducedIn, deprecatedIn, desupportedIn, oracleReplacement, "sources": sources[]->{title, url, publisher}, "mappings": *[_type=="mapping" && oracleFeature._ref==^._id]{ _id, fidelity, effort, rationale, appliesToOracleVersions, "azureTarget": azureTarget->{name, "slug": slug.current, service}, "sources": sources[]->{title, url}, "caveats": *[_type=="caveat" && mapping._ref==^._id]{ _id, severity, statement, appliesTo, firsthand, "evidence": evidence->{title, url, publisher} } } }
Answer
Verdict: Only Oracle Database@Azure preserves Oracle's "empty string = NULL" behaviour exactly. Azure SQL Database and Azure Database for PostgreSQL Flexible Server do not — they treat '' as a real, non-NULL value, requiring workarounds.
Scope: Oracle 11.2 through 26ai, all Oracle editions covered by this feature (Empty string equals NULL, introduced pre-11.2, not deprecated/desupported).
Azure targets, by fidelity
Oracle Database@Azure — fidelity: exact, effort S. Runs Oracle Database itself (Exadata Database Service, Base Database Service, or Autonomous Database) inside Azure datacenters, so SQL semantics are unchanged: a zero-length VARCHAR2 is still stored and compared as NULL. No caveats recorded. — Overview: Oracle Database@Azure, Nulls (SQL Language Reference 19c)
Azure SQL Database — fidelity: workaround, effort M. SQL Server/Azure SQL stores
''as a distinct, non-null zero-length value. After migration, an INSERT of''produces a non-null row,IS NULLpredicates stop matching it, andNOT NULLconstraints that used to reject''now accept it — Major caveat: "a null value is different from an empty or zero value." — NULL and UNKNOWN (Transact-SQL), SSMA for Oracle: Project Settings (Conversion)Azure Database for PostgreSQL Flexible Server — fidelity: workaround, effort M. PostgreSQL also distinguishes
''from NULL. Major caveat notes Ora2Pg'sNULL_EQUAL_EMPTYdirective rewritesIS NULL/IS NOT NULLtests intocoalesce()-based checks to preserve Oracle's behaviour, though Ora2Pg's own docs recommend instead converting empty strings to NULL in the application where feasible; theorafceextension offers a trigger to replace''with NULL on write. — Ora2Pg documentation, orafce README
No dispute is recorded on this feature in the dataset.
Gap: No mapping exists in this dataset for other Azure targets (e.g., Oracle on Azure VM, Azure SQL Managed Instance) regarding this specific behavior — only the three above are covered for the "empty-string-null" feature.
GROQ + Knowledge Base
smaller model · 5 turns · 28 s · 57.7k in / 2.5k out✓ verdict ✓ grounded ✓ cited
Grader: Correct verdict, flags code review; MI gap noted honestly
4 tool calls
- initial_context on groq · 4,126 chars back
- initial_context on kb · 7,679 chars back
- groq_query on groq · 17,141 chars back
*[_type=="oracleFeature" && (name match "*empty*" || name match "*NULL*" || name match "*VARCHAR2*" || category=="datatype")]{_id, name, "slug": slug.current, category, summary} - groq_query on groq · 5,233 chars back
*[_type=="mapping" && oracleFeature._ref=="feature_empty-string-null"]{ _id, fidelity, effort, rationale, appliesToOracleVersions, "azureTarget": azureTarget->{name, "slug": slug.current}, "sources": sources[]->{title, url}, "caveats": *[_type=="caveat" && references(^._id)]{severity, statement, appliesTo, firsthand, "evidence": evidence->{title, url}, "disputes": *[_type=="dispute" && (claimA._ref==^._id || claimB._ref==^._id)]{title, whatDisagrees, resolution, "claimA": claimA->{statement}, "claimB": claimB->{statement}, "resolvedBy": resolvedBy->{title,url}}} }
Answer
Verdict: Only Oracle Database@Azure preserves Oracle's "empty string = NULL" behavior exactly. Azure SQL Database and Azure Database for PostgreSQL – Flexible Server do NOT preserve it natively — both require a workaround. The dataset has no mapping for Azure SQL Managed Instance or Oracle on Azure VMs for this feature.
Oracle feature
Empty string equals NULL — "Oracle treats a character value of zero length as NULL... Oracle's SQL reference explicitly says this may not remain true in future releases and advises applications not to depend on it." Applies to Oracle 11.2 through 26ai; long-standing and unchanged, documented but not guaranteed. [Empty string equals NULL feature summary] (source not URL-bearing itself; see per-target citations below).
Azure targets, by fidelity
Oracle Database@Azure — fidelity: exact, effort: S "Oracle Database@Azure runs Oracle Database itself (Exadata Database Service, Base Database Service or Autonomous Database) inside Azure datacenters, so SQL semantics are unchanged and a zero-length VARCHAR2 is still stored and compared as NULL. The behaviour moves with the database; only a later move to a non-Oracle engine reintroduces the difference." No caveats recorded. Sources: Overview: Oracle Database@Azure, Nulls (SQL Language Reference 19c) Applies to Oracle 11.2–26ai.
Azure SQL Database — fidelity: workaround, effort: M "SQL Server keeps '' as a real value distinct from NULL... After migration the same INSERT of '' produces a non-null row, IS NULL predicates stop matching it, and NOT NULL constraints that used to reject '' now accept it, so data and code need explicit handling." Caveat (major): "In SQL Server and Azure SQL an empty string '' is a stored zero-length value that is distinct from NULL; Microsoft's NULL documentation states that a null value is different from an empty or zero value, so Oracle code that relied on '' being NULL changes behaviour." Evidence: NULL and UNKNOWN (Transact-SQL) Sources: also SSMA for Oracle: Project Settings (Conversion) Applies to Oracle 11.2–26ai.
Azure Database for PostgreSQL Flexible Server — fidelity: workaround, effort: M "PostgreSQL distinguishes '' from NULL exactly as SQL Server does. Ora2Pg offers NULL_EQUAL_EMPTY, which rewrites IS NULL and IS NOT NULL tests into coalesce()-based checks so converted code keeps Oracle's behaviour... orafce adds a trigger function that replaces empty strings with NULL on write." Caveat (major): "PostgreSQL treats '' as a non-NULL value; Ora2Pg's NULL_EQUAL_EMPTY directive exists to rewrite IS NULL tests into coalesce()-based checks precisely because PostgreSQL differentiates empty strings from NULL, and its documentation recommends converting empty strings to NULL when the application can be changed." Evidence: Ora2Pg documentation (configuration directives) Sources: also orafce README Applies to Oracle 11.2–26ai.
Gaps
- No mapping in the dataset for Azure SQL Managed Instance or Oracle on Azure VMs (Azure VM would presumably inherit Oracle semantics since it's the same engine, but this is not stated in any retrieved document — I won't assume it).
- No
disputeentries touch this feature.
Bottom line for your app: if you must keep '' == NULL semantics without code changes, Oracle Database@Azure is the only target with exact fidelity in this dataset. Azure SQL Database or PostgreSQL Flexible Server require workaround tooling (SSMA conversion settings / Ora2Pg's NULL_EQUAL_EMPTY or orafce triggers) and code review of every empty-string literal and IS NULL test.