You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

UNION操作排序规则非法混合错误排查:SQL语句问题咨询

解决UNION操作的排序规则冲突问题

这个错误Illegal mix of collations for operation 'UNION'本质是因为你用UNION合并的两个查询结果里,对应位置的列使用了不同的字符排序规则(collation)。UNION操作要求两个结果集的对应列不仅数据类型要一致,连字符排序规则也得完全匹配才行。

先看你的SQL语句:

SELECT a.paid, a.total, a.remain, a.date, a.patient_id 
FROM ( 
    (SELECT paid, total, remain, date, patient_id FROM payment ) 
    UNION 
    (SELECT paid, total_need AS total, remain, date, patient_id FROM patient_vouchers ) 
) a 
WHERE a.patient_id ='.$patient_id.' 
ORDER BY a.date ASC

具体来说,payment表和patient_vouchers表中,至少有一列(比如paidtotal/total_needremainpatient_id这类字符类型的列)的collation设置不一样——比如一个是utf8mb4_general_ci,另一个是utf8mb4_unicode_ci,甚至字符集本身就不同(比如一个是utf8,一个是utf8mb4),这就导致UNION无法正常合并结果。

两种快速解决方法:

方法1:强制指定统一的collation

在每个查询的对应字符列后面,用COLLATE关键字指定相同的排序规则(根据你的数据库实际字符集调整,这里以utf8mb4_general_ci为例):

SELECT a.paid, a.total, a.remain, a.date, a.patient_id 
FROM ( 
    (SELECT 
        paid COLLATE utf8mb4_general_ci, 
        total COLLATE utf8mb4_general_ci, 
        remain COLLATE utf8mb4_general_ci, 
        date, 
        patient_id COLLATE utf8mb4_general_ci 
     FROM payment ) 
    UNION 
    (SELECT 
        paid COLLATE utf8mb4_general_ci, 
        total_need COLLATE utf8mb4_general_ci AS total, 
        remain COLLATE utf8mb4_general_ci, 
        date, 
        patient_id COLLATE utf8mb4_general_ci 
     FROM patient_vouchers ) 
) a 
WHERE a.patient_id ='.$patient_id.' 
ORDER BY a.date ASC

注意:date是日期类型,不需要指定collation,只有字符类型的列需要处理。

方法2:修改表结构统一collation

如果业务允许,可以直接修改两个表中对应列的collation为同一个值,一劳永逸解决后续的冲突问题:

-- 修改payment表的冲突列
ALTER TABLE payment MODIFY COLUMN paid VARCHAR(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE payment MODIFY COLUMN total VARCHAR(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE payment MODIFY COLUMN remain VARCHAR(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE payment MODIFY COLUMN patient_id VARCHAR(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;

-- 修改patient_vouchers表的冲突列
ALTER TABLE patient_vouchers MODIFY COLUMN paid VARCHAR(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE patient_vouchers MODIFY COLUMN total_need VARCHAR(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE patient_vouchers MODIFY COLUMN remain VARCHAR(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE patient_vouchers MODIFY COLUMN patient_id VARCHAR(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;

你可以根据实际的列类型和长度调整上面的语句。

另外补充个小建议:如果你的需求不需要去重,应该用UNION ALL替代UNIONUNION会自动去重,性能比UNION ALL差不少,根据业务场景选择即可。

内容的提问来源于stack exchange,提问作者nashwa

火山引擎 最新活动