union all两个结果集报ORA-12704: character set mismatch错误

本文介绍了解决Oracle中因字段类型不匹配导致的ORA-12704:charactersetmismatch错误的方法。通过举例说明如何使用union all操作时确保字符集一致,并提供了一种通过创建临时表来简化复杂查询中类型匹配问题排查的有效手段。

错误:当union all两个结果集时,报ORA-12704: character set mismatch错误,例如:

select colA from TableA
union
select colB from TableB

原因:是字段类型不匹配导致的,比如TableA的colA字段类型是nvarchar类型,而colB的字段类型是varchar类型,两者类型不统一,因此会报字符集不匹配的错误

解决方案:可以将其中一个结果集的类型做下转换,如:

select colA from TableA
union
select n''|| colB from TableB  --通过在=追加n''||将colB转换为nvarchar

  注意:有时,union两端的结果集的字段过多,导致排查起来特别困难,可分别将两端的结果集用create table as的方式创建一个临时表,然后再比对两个临时表的DDL,这样排查起来更方便

(--取利润 SELECT t3.fnumber 公司编码,t3.fname_l2 公司名称,t1.Fperiod 期间, -- SUM(t1.FMonthPnLLocal) C, -SUM(t1.FYearPnLLocal) Y, -1 DC, '410409' 明细科目编码, '本年净利润' 明细科目名称, '未分配利润' 表项目 FROM T_GL_AccountBalance_5L t1 INNER JOIN T_BD_AccountView t2 ON t1.FAccountID = t2.FID INNER JOIN T_ORG_BASEUNIT t3 ON t1.FOrgUnitID=t3.fid WHERE -- t1.FOrgUnitID = 'GUEAAAAAAELM567U' AND -- AND t2.FAccountTableID = 'GUEAAAAARlsXaY5t' AND t1.FPeriod IN (202412) AND t2.FNumber >= '6001' AND t2.FNumber <= '6901'AND t2.FLevel = 1 GROUP BY t3.fnumber,t3.fname_l2,t1.FPeriod ) UNION ALL (--常规科目 SELECT --SUM(t1.FBeginBalanceLocal) C, t3.fnumber 公司编码,t3.fname_l2 公司名称,t1.FPeriod 期间, CASE WHEN t2.fnumber IN ('2001','2211','2231','2232','2601','2501','2701','4001','4002','4101','4102','4103') THEN -SUM(t1.FEndBalanceLocal) WHEN t2.fnumber='2221' and SUM(t1.FEndBalanceLocal)<=0 THEN -SUM(t1.FEndBalanceLocal) WHEN t2.fnumber='224199' and SUM(t1.FEndBalanceLocal)<=0 THEN -SUM(t1.FEndBalanceLocal) WHEN t2.fnumber='121106' and SUM(t1.FEndBalanceLocal)<0 THEN -SUM(t1.FEndBalanceLocal) ELSE SUM(t1.FEndBalanceLocal) END Y, t2.FDc DC, t2.fnumber 明细科目编码, t2.FNAME_L2 明细科目名称, CASE WHEN t2.fnumber IN ('101206','1002','1001','101205') THEN '货币资金' WHEN t2.fnumber IN ('1101','101204') THEN '交易性金融资产' WHEN t2.fnumber = '1111' THEN '应收票据' WHEN t2.fnumber = '122101' THEN '应收账款' WHEN t2.fnumber IN ('1401','1402','1403','1404','1405','1406','1407','1408','1409','1410','1411','5001') THEN '存货' WHEN t2.fnumber IN ('1501','1502') THEN '持有至到期投资' WHEN t2.fnumber IN ('1504','1505') THEN '长期股权投资' WHEN t2.fnumber IN ('1506','1507','1508') THEN '投资性房地产' WHEN t2.fnumber IN ('1601','1602','1603','1606') THEN '固定资产' WHEN t2.fnumber IN ('1604','1605','1607') THEN '在建工程' WHEN t2.fnumber IN ('1701','1702','1703') THEN '无形资产' WHEN t2.fnumber ='1711' THEN '商誉' WHEN t2.fnumber ='1804' THEN '长期待摊费用' WHEN t2.fnumber ='1805' THEN '递延所得税资产' WHEN t2.fnumber ='2001' THEN '短期借款' WHEN t2.fnumber ='2201' THEN '应付票据' WHEN t2.fnumber ='2211' THEN '应付职工薪酬' WHEN t2.fnumber ='2601' THEN '长期借款' WHEN t2.fnumber ='2411' THEN '预计负债' WHEN t2.fnumber ='2501' THEN '递延收益' WHEN t2.fnumber ='2701' THEN '递延所得税负债' WHEN t2.fnumber ='4001' THEN '实收资本(或股本)' WHEN t2.fnumber ='4002' THEN '资本公积' WHEN t2.fnumber ='4003' THEN '减:库存股' WHEN t2.fnumber ='4101' THEN '盈余公积' WHEN t2.fnumber IN ('4102','4103') THEN '未分配利润' WHEN t2.fnumber='2221' and SUM(t1.FEndBalanceLocal)>0 THEN '其他流动资产' WHEN t2.fnumber='2221' and SUM(t1.FEndBalanceLocal)<=0 THEN '应交税费' WHEN t2.fnumber IN ('2231','2232') THEN '其他应付款' WHEN t2.fnumber IN ('224199') AND SUM(t1.FEndBalanceLocal)<=0 THEN '其他应付款' WHEN t2.fnumber IN ('1114','1115','122102') THEN '其他应收款' WHEN t2.fnumber IN ('224199') AND SUM(t1.FEndBalanceLocal)>0 THEN '其他应收款' WHEN t2.fnumber IN ('1801','1802','1901') THEN '其他非流动资产' WHEN t2.fnumber IN ('121106') AND SUM(t1.FEndBalanceLocal)>=0 THEN '其他应收款' WHEN t2.fnumber IN ('121106') AND SUM(t1.FEndBalanceLocal)<0 THEN '其他应付款' END 表项目 FROM T_GL_AccountBalance_5L t1 INNER JOIN T_BD_AccountView t2 ON t1.FAccountID = t2.FID INNER JOIN T_ORG_BASEUNIT t3 ON t1.FOrgUnitID=t3.fid WHERE --t1.FOrgUnitID = 'GUEAAAAAAELM567U' AND t1.FPeriod =202412 AND t2.fnumber IN('121106','224199','122101','122102','101206','101205','101204','5001','4103','4102','4101','4003', '4002','4001','2701','2601','2501','2232','2231','2221','2211','2001','1901','1805','1804','1802','1702','1701','1606', '1604','1602','1601','1505','1504','1502','1501','1410','1408','1407','1406','1405','1404','1403','1401','1115','1114','1111','1101','1002','1001') GROUP BY t3.fnumber,t3.fname_l2,t1.FPeriod,t2.fnumber,t2.FDC,t2.FNAME_L2 )ORA-12704: character set mismatch
最新发布
06-24
### SQL ORA-12704 字符不匹配问题的解决方案 ORA-12704 错误通常发生在 Oracle 数据库中,当查询涉及不同字符的数据时出现。此错误表明在 SQL 语句中,某些列或表达式的字符不一致。以下是解决该问题的详细方法: #### 1. 确保数据类型一致性 在使用 `UNION` 或 `UNION ALL` 操作符时,确保所有结果中的对应列具有相同的数据类型和字符。例如,如果一个结果中某列为 `VARCHAR2`,另一个结果中对应的列也应为 `VARCHAR2`,并且它们的字符必须一致[^1]。 ```sql -- 示例:确保 colA 和 colB 的数据类型及字符一致 SELECT CAST(colA AS NVARCHAR2(50)) FROM TableA UNION ALL SELECT CAST(colB AS NVARCHAR2(50)) FROM TableB; ``` #### 2. 使用 `CAST` 或 `TO_CHAR` 强制转换 如果无法直接更改表结构,可以使用 `CAST` 或 `TO_CHAR` 函数将列转换为相同的字符或数据类型。例如: ```sql -- 将所有列转换为 NVARCHAR2 类型 SELECT CAST(colA AS NVARCHAR2(50)) FROM TableA UNION ALL SELECT CAST(colB AS NVARCHAR2(50)) FROM TableB; ``` 或者: ```sql -- 使用 TO_CHAR 转换为字符串 SELECT TO_CHAR(colA) FROM TableA UNION ALL SELECT TO_CHAR(colB) FROM TableB; ``` #### 3. 配置客户端和服务端字符 确保客户端和服务端的字符一致。可以通过以下方式检查和修改字符配置: - **服务端字符**:通过以下查询检查数据库的字符设置: ```sql SELECT parameter, value FROM nls_database_parameters WHERE parameter = 'NLS_CHARACTERSET'; ``` - **客户端字符**:检查客户端的 `NLS_LANG` 环境变量是否与服务端一致。如果需要修改,可以在注册表中调整 `HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\KEY_OraClient11g_home2\NLS_LANG` 的值[^2]。 #### 4. 修改 SQL 逻辑以避免字符冲突 在某些情况下,SQL 逻辑可能导致隐式字符转换。例如,当使用字符串常量时,确保其字符与目标列一致。以下是一个示例: ```sql -- 原始 SQL 可能导致字符不匹配 SELECT CASE WHEN app.ORDER_NO IS NOT NULL THEN app.ORDER_NO WHEN app.IS_RETURN = '1' THEN '退回' ELSE '未安排' END FROM a app; -- 修改后的 SQL 使用显式字符转换 SELECT CASE WHEN app.ORDER_NO IS NOT NULL THEN app.ORDER_NO WHEN app.IS_RETURN = '1' THEN CAST('退回' AS NVARCHAR2(10)) ELSE CAST('未安排' AS NVARCHAR2(10)) END FROM a app; ``` #### 5. 检查并修复表结构 如果问题频繁发生,建议检查相关表的定义,确保所有涉及的列使用统一的字符。例如,将所有字符串类型的列更改为 `NVARCHAR2` 或其他适合的类型。 --- ### 总结 ORA-12704 错误的核心在于字符不一致。通过确保数据类型一致性、使用 `CAST` 或 `TO_CHAR` 转换、配置客户端和服务端字符以及优化 SQL 逻辑,可以有效解决该问题。 ```sql -- 综合示例 SELECT CAST(colA AS NVARCHAR2(50)) FROM TableA UNION ALL SELECT CAST(colB AS NVARCHAR2(50)) FROM TableB; ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值