SQL Server 2019 CU9 and 2016 SP2 CU16: Fixing Incorrect Query Results

Microsoft confirmed two significant bugs affecting SQL Server 2019 and SQL Server 2016 that caused incorrect query results in production environments. Both issues were patched in SQL Server 2019 Cumulative Update 9 (CU9) and SQL Server 2016 SP2 Cumulative Update 16 (CU16). If your environment was running earlier builds during late 2020 and early 2021, your applications may have been silently returning wrong data.

That last point deserves emphasis. Silent data corruption and incorrect results are among the most dangerous categories of SQL Server bugs. A query that throws an error is immediately visible. A query that returns plausible but wrong data can go undetected for weeks, feeding incorrect figures into reports, financial calculations, and business decisions.

What Bugs Were Fixed in These Updates?

The two key issues addressed in these cumulative updates were:

1. Incorrect results from the CONCAT function

The CONCAT function was returning incorrect results under specific conditions. CONCAT is widely used for string manipulation across reporting queries, application stored procedures, and ETL pipelines. A bug here has broad reach because it's not an obscure edge-case function. It's everyday SQL.

2. Incorrect results from in-memory optimised tables with clustered columnstore indexes

This one is more targeted but potentially more damaging in high-performance environments. In-memory OLTP tables (sometimes called Hekaton tables) combined with clustered columnstore indexes are a common architecture choice for workloads that need both fast transactional inserts and analytical query performance. If your environment uses this combination, incorrect results from analytical queries could have been affecting dashboards and reporting without any error being raised.

Why Were These Patches Delayed?

Microsoft delayed the release of these fixes at the end of 2020. The stated reasons included the disruption caused by the pandemic and the holiday period affecting engineering and release schedules.

That explanation is understandable in context, but it highlights a real operational risk that many organisations don't account for: patch release schedules are not always predictable, and critical fixes can sit in Microsoft's pipeline for weeks or months longer than expected.

This is not a criticism unique to Microsoft. Any complex software platform with a structured release process faces the same challenge. The lesson for SQL Server administrators is to stay informed about known bugs and their workarounds, not just wait for patches to arrive.

How Do You Know If You Were Affected?

Determining whether your environment was exposed to these bugs requires checking two things: your SQL Server build number and your workload characteristics.

Check your current SQL Server build

Run this query against any instance you want to verify:

SELECT
    @@SERVERNAME AS ServerName,
    @@VERSION AS FullVersion,
    SERVERPROPERTY('ProductVersion') AS ProductVersion,
    SERVERPROPERTY('ProductLevel') AS ProductLevel,
    SERVERPROPERTY('ProductUpdateLevel') AS CumulativeUpdate;

For SQL Server 2019, you needed to be on CU9 (build 15.0.4102.2) or later to have the fix applied. For SQL Server 2016 SP2, you needed CU16 (build 13.0.5882.1) or later.

If your build number is lower than these, and you haven't patched since, the bugs may still be present in your environment.

Check your workload for exposure

Ask these questions about your environment:

  • Do any stored procedures, views, or application queries use the CONCAT function?
  • Do you have any in-memory optimised tables (check sys.tables where is_memory_optimized = 1)?
  • Do any of those in-memory tables have clustered columnstore indexes?

If the answer to any of these is yes, and you were running an unpatched build, you should treat any query results from that period as potentially suspect and validate them against a known-good data source where possible.

What Should You Do Now?

The immediate action is straightforward: patch to a supported, current cumulative update. Microsoft releases cumulative updates for SQL Server on a regular cadence, roughly every 8 weeks for actively supported versions. Staying within two CUs of the current release is a reasonable operational target for most production environments.

Here is a practical remediation checklist:

  1. Identify all SQL Server instances in your environment and their current build numbers using the query above.
  2. Cross-reference builds against the SQL Server build list maintained at SQLServerUpdates.com or the official Microsoft documentation at learn.microsoft.com.
  3. Prioritise instances running SQL Server 2019 or 2016 that are below the patched build numbers.
  4. Test cumulative updates in a non-production environment before applying to production. CUs are generally safe, but regression testing against your specific workload is always worth doing.
  5. Apply the updates during a scheduled maintenance window with a tested rollback plan.
  6. After patching, validate results from any queries that use CONCAT or query in-memory optimised tables with columnstore indexes.

Step 6 is the one most teams skip. Patching removes the bug going forward, but it doesn't retroactively fix any incorrect results that were already written to tables or exported to downstream systems. If your environment was exposed for a significant period, a data validation exercise against source systems or audit logs is worth considering.

What Is Microsoft's Patching Philosophy for SQL Server?

Microsoft's approach to SQL Server patching has evolved significantly over the years. Cumulative updates were once considered optional and were positioned more like service packs. That changed around SQL Server 2017, when Microsoft explicitly stated that cumulative updates are now the recommended servicing vehicle for SQL Server and should be applied proactively.

The Microsoft guidance on this is clear: "We now recommend ongoing, proactive installation of CU updates as they become available." This is documented in the Microsoft support lifecycle documentation for SQL Server.

In practice, many organisations still treat CUs as optional or apply them reactively, only when a specific bug affects them. The incorrect results bugs in SQL Server 2019 and 2016 are a good example of why that approach carries real risk. You may not know a bug is affecting you until the damage is already done.

Does This Affect SQL Server 2022?

These specific bugs were reported against SQL Server 2019 and 2016. SQL Server 2022, which reached general availability in November 2022, was not affected by these particular issues. However, SQL Server 2022 has its own cumulative update history and its own set of bugs that have been fixed over time.

If you're running SQL Server 2022, the same principle applies: stay current with cumulative updates and monitor the release notes for any fixes relevant to your workload patterns.

Key Takeaways

  • SQL Server 2019 CU9 and SQL Server 2016 SP2 CU16 fixed two bugs that caused silent incorrect query results, one affecting the CONCAT function and one affecting in-memory optimised tables with clustered columnstore indexes.
  • Silent incorrect results are more dangerous than errors because they go undetected. Any environment exposed to these bugs during the unpatched period should consider validating critical query outputs.
  • Patching removes the bug going forward but does not fix data that was already written incorrectly. Downstream validation may be necessary.
  • Microsoft now recommends proactive, ongoing application of cumulative updates rather than waiting for specific issues to surface.
  • Checking your SQL Server build number regularly is a basic but often overlooked part of SQL Server health management.

Staying on top of SQL Server patching across multiple instances is time-consuming, and it's easy for builds to drift when there are other priorities competing for attention. DBA Services provides SQL Server health checks and managed support for Australian organisations that need confidence their environments are patched, configured correctly, and protected against known issues. If you're not sure what build your SQL Server instances are running, that's a good place to start.