pingcap / pingcap/tidb

rows unexpectedly become less after changing EXCEPT to UNION

Open
#67,018 4 comments 0 reactions 1 assignee Claimed by @xhebox View on GitHub
contribution may-affects-7.1 may-affects-7.5 may-affects-8.1 may-affects-8.5 severity/major sig/sql-infra type/bug
Dominant language
Go
Stars
40.5k
Forks
6.2k
PR merge metrics
PR metrics pending

Description

## Bug Report

Please answer these questions before submitting your issue. Thanks!

### 1. Minimal reproduce step (Required)

```
DROP DATABASE IF EXISTS repro44;
CREATE DATABASE repro44;
USE repro44;

CREATE TABLE t1 (
c1 INT PRIMARY KEY,
c4 INT NULL
);

CREATE TABLE t2 (
c10 ENUM('value1','value2','value3') NULL
);

CREATE TABLE t3 (
c14 SET('x','y','z') NULL
);

INSERT INTO t1 VALUES (1, NULL);
INSERT INTO t2 VALUES (NULL);
INSERT INTO t3 VALUES ('x');

-- original
UPDATE IGNORE t1
SET c4 = 1
WHERE c1 IN (
SELECT c14 FROM t3
EXCEPT
SELECT c10 FROM t2
);

-- reset
UPDATE t1 SET c4 = NULL;

-- mutated
UPDATE IGNORE t1
SET c4 = 1
WHERE c1 IN (
SELECT c14 FROM t3
UNION
SELECT c10 FROM t2
);

```

### 2. What did you expect to see? (Required)
mutated row matched rows should be greater than the original
Additionally,the root cause :
The issue is a Logic Bug stemming from Inconsistent Type Coercion.
When the database evaluates SELECT c14 FROM t3 UNION SELECT c10 FROM t2, it attempts to unify the data types of c14 and c10. If this unification results in a type that is incompatible with the comparison to t1.c1, or if the conversion logic differs from that used in EXCEPT, the WHERE clause evaluates to false or NULL incorrectly.
```
mysql> -- original
mysql> UPDATE IGNORE t1
-> SET c4 = 1
-> WHERE c1 IN (
-> SELECT c14 FROM t3
-> EXCEPT
-> SELECT c10 FROM t2
-> );
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
```

### 3. What did you see instead (Required)
```
mysql> -- mutated
mysql> UPDATE IGNORE t1
-> SET c4 = 1
-> WHERE c1 IN (
-> SELECT c14 FROM t3
-> UNION
-> SELECT c10 FROM t2
-> );
Query OK, 0 rows affected, 1 warning (0.01 sec)
Rows matched: 0 Changed: 0 Warnings: 1
```
### 4. What is your TiDB version? (Required)

```
mysql> SELECT tidb_version();
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| tidb_version() |
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Release Version: v8.5.5
Edition: Community
Git Commit Hash: 1fa258b833ff113883beeba40bc130be7ce66610
Git Branch: HEAD
UTC Build Time: 2026-03-12 08:34:59
GoVersion: go1.25.5
Race Enabled: false
Check Table Before Drop: false
Store: unistore |
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.