2012-02-21 79 views
2

我们最近修复了一个问题,通过确保文件是UTF-8并且Java代码打开这些文件,从文本文件错误地将字符编码读入到我们的系统中文件编号为UTF-8在整个数据库中搜索一个乱码字符“Oracle”

但是,我们最终在整个数据库表中添加了大量记录,插入了不正确的字符,即°F被读为�F。所以即使我们现在已经解决了这个问题,我们现在需要清理数据库表来纠正这个异常。

任何人都可以请建议我的方式来实现这一目标?

+2

如果你'选择转储(<>,1016)FROM <

> WHERE <<一些条件,显示了问题的数据>>)'你知道有一个表有一个表有问题,什么二进制值是存储的问题字符?如果你在几个你知道的不同情况下重复这个测试,那么这个字符是否与一个特定的二进制值一致? – 2012-02-21 04:49:44

+0

这并不一定意味着它是乱码 - 你可能会错过显示该字符的字体。 – Arafangion 2012-02-21 04:59:58

+0

@Arafangion:绝对不是这样。正如我所说,修复已完成,我们可以完美地查看新的传入记录的特殊字符。 – 2012-02-21 05:05:35

回答

1

我以前有过类似的问题。幸运的是,它影响的列数限制在一个很小的数字上,并且这些列在整个数据库中都有相同的名称。

我写一个脚本,执行以下操作解决了这个:

  1. 禁用的外键约束
  2. 建立包含的 目标列
  3. 更新所有的表在表的列表中选择使用 REGEXP_REPLACE
  4. 列表提交数据重新启用约束

这使用了一个健康剂量的动态SQL,从user_constraintsuser_tab_columns中提取数据,对我所针对的特定列名进行过滤。

这是一个粗略的框架,让你开始,我刚刚把它扔在一起很快,所以它没有测试。另外,如果您有触发器担心,你需要禁用那些过于:

-- disable constraints 
BEGIN 
    FOR c IN (
     SELECT c.owner, c.table_name, c.constraint_name, c.constraint_type 
     FROM user_constraints c 
     INNER JOIN user_tables t ON (t.table_name = c.table_name) 
     AND c.status = 'ENABLED' 
     AND c.constraint_type NOT IN ('C', 'P') 
     ORDER BY c.constraint_type DESC 
    ) 
    LOOP 
     dbms_utility.exec_ddl_statement('alter table '||c.table_name||' disable constraint ' || c.constraint_name); 
    END LOOP; 
END; 

-- do the updates 
BEGIN 
    FOR t IN (
     SELECT table_name, column_name 
     FROM user_tab_columns 
     WHERE column_name = 'TEMPERATURE' 
     AND data_type = 'VARCHAR2'; 
    ) 
    LOOP 
     dbms_utility.exec_ddl_statement('UPDATE '||t.table_name||' SET ' ||t.column_name||' = '||''GOOD VALUE''||' WHERE '||t.column_name||' = '||''BAD VALUE''); 
    END LOOP; 
END; 

-- re-enable constraints 
BEGIN 
    FOR c IN (
     SELECT c.owner, c.table_name, c.constraint_name, c.constraint_type 
     FROM user_constraints c 
     INNER JOIN user_tables t ON (t.table_name = c.table_name) 
     AND c.status = 'DISABLED' 
     AND c.constraint_type NOT IN ('C', 'P') 
     ORDER BY c.constraint_type ASC 
    ) 
    LOOP 
     dbms_utility.exec_ddl_statement('alter table '||c.table_name||' enable constraint ' || c.constraint_name); 
    END LOOP; 
END; 
/
+1

'使用REGEXP_REPLACE'更新列表中的所有表这将是一个有点难以找到所有这些符号,因为''char是不是一个特定的字符,但是代码的介绍是无效 – zerkms 2012-02-21 04:42:18

+0

@zerkms这取决于数据如何被摆在首位。 * *是一个字符,U + FFFD,“替换字符”,它应该被Unicode处理器替换为无效字节序列。因此,如果Java的搞砸了进口,很可能是在数据库因为Java把它放在那里保存为一个字符。如果数据作为二进制数据插入到数据库中,并且只有输出端拧紧,那就不一样了。 – deceze 2012-02-21 04:59:48

+0

找到一条您知道已损坏的行,并在目标列上使用DUMP功能。这会给你你正在寻找的'CHAR'代码。 – ninesided 2012-02-21 05:11:02

相关问题