如何用C#或SQL查询读取Oracle、SQL Server中存为问号的荷兰字符ë
我来帮你梳理下这个问题的解决思路——首先得明确:如果字符已经因为插入时的编码问题被存成了问号,那有些情况可能没法完全恢复,但我们可以先排查存储的实际内容,再针对性解决读取和显示的问题。
第一步:先确认数据库里存的到底是啥
不管是SQL Server还是Oracle,先别着急调读取逻辑,先搞清楚数据是真的变成问号了,还是只是显示的时候出问题:
SQL Server 端排查
跑个SQL查一下字符的编码值,看看是不是真的存成了问号:
-- 替换成你的表名和字段名 SELECT YourColumn, ASCII(YourColumn) AS 字符ASCII值, -- 问号的ASCII是63 UNICODE(YourColumn) AS 字符Unicode值 FROM YourTable WHERE YourColumn LIKE '%?%';
如果字符Unicode值是63,那说明插入的时候编码就错了,数据已经丢了;如果是235(ë的Unicode值),那只是显示或读取时的编码没配对,好办。
Oracle 端排查
同样用SQL查存储的实际编码:
-- 替换成你的表名和字段名 SELECT YourColumn, ASCII(YourColumn) AS 字符ASCII值, UNISTR(YourColumn) AS Unicode编码显示, DUMP(YourColumn, 1016) AS 十六进制存储值 -- ë的UTF-8是0xC3AB,UTF-16是0x00EB FROM YourTable WHERE YourColumn LIKE '%?%';
如果十六进制值是0x3F(问号的十六进制),那数据已经没救了;如果是对应ë的编码,那就是显示或读取的问题。
第二步:针对现有数据的读取方案
SQL Server 读取(C# + SQL)
SQL 查询方式
如果数据实际是Unicode值(只是显示成问号),如果字段是nvarchar类型,直接查就行;如果是varchar,试试转成Unicode:
SELECT CONVERT(NVARCHAR(MAX), YourColumn) AS 修正后字段 FROM YourTable
C# 读取方式
连接SQL Server的时候,确保连接字符串没毛病,读取的时候直接用GetString就行,另外项目编码设成UTF-8:
using (SqlConnection conn = new SqlConnection("Server=你的服务器;Database=你的库;User Id=账号;Password=密码;")) { conn.Open(); string query = "SELECT YourColumn FROM YourTable"; using (SqlCommand cmd = new SqlCommand(query, conn)) { using (SqlDataReader reader = cmd.ExecuteReader()) { while (reader.Read()) { // 直接读取,前提是字段是nvarchar类型 string value = reader.GetString(0); Console.WriteLine(value); // 应该能显示出ë } } } }
要是字段是varchar,而且数据库排序规则支持西欧字符(比如SQL_Latin1_General_CP1_CI_AS),可以试试读字节再转编码:
byte[] bytes = reader.GetSqlBytes(0).Buffer; string value = Encoding.GetEncoding("ISO-8859-1").GetString(bytes);
Oracle 读取(C# + SQL)
SQL 查询方式
如果字段是NVARCHAR2,直接查就行;如果是VARCHAR2,数据库字符集支持西欧字符的话,试试转换:
SELECT CONVERT(YourColumn, 'AL32UTF8') AS 修正后字段 FROM YourTable
C# 读取方式
用Oracle的驱动连接时,记得在连接字符串里加Unicode=True:
using (OracleConnection conn = new OracleConnection("Data Source=你的Oracle库;User Id=账号;Password=密码;Unicode=True;")) { conn.Open(); string query = "SELECT YourColumn FROM YourTable"; using (OracleCommand cmd = new OracleCommand(query, conn)) { using (OracleDataReader reader = cmd.ExecuteReader()) { while (reader.Read()) { string value = reader.GetString(0); Console.WriteLine(value); } } } }
要是字段是VARCHAR2,数据库字符集是西欧编码(比如WE8ISO8859P1),可以转编码读取:
byte[] bytes = reader.GetOracleString(0).Value; string value = Encoding.GetEncoding("ISO-8859-1").GetString(bytes);
第三步:解决SQL Developer显示问号的问题
你已经调过NLS和字体还没用?试试这些方向:
- 查Oracle数据库的字符集:跑
SELECT value FROM nls_database_parameters WHERE parameter='NLS_CHARACTERSET';,如果是US7ASCII,那VARCHAR2字段根本存不下ë,只能改字符集(还得重新导数据)。 - 检查SQL Developer的连接设置:编辑连接的时候,去“Advanced”标签页,勾选“Use Unicode”选项。
- 换字段类型:如果是
VARCHAR2,改成NVARCHAR2试试(但原数据已经是问号的话,改了也没用,得重新插)。 - 换个工具试试:比如用PL/SQL Developer连一下,看能不能显示,排除SQL Developer本身的问题。
重要提醒
如果是插入的时候没加N前缀(SQL Server)或者没用Unicode字段类型(SQL Server的nvarchar、Oracle的NVARCHAR2),导致字符直接被转成了问号,那现有数据已经不可逆丢失了,只能找原始备份重新插入——插入的时候记得加N前缀(比如INSERT INTO YourTable (YourColumn) VALUES (N'ë')),或者用Unicode类型的字段。
内容的提问来源于stack exchange,提问作者Ritu

