将Firebird字段/域从ISO8859_1转换为UTF8

时间:2014-03-25 11:09:55

标签: utf-8 firebird firebird2.5

我已经通过谷歌进行了一些研究,但无法找到合适的答案。

我有一个Firebird数据库,我总是在我的表字段中使用自己的域名。所有这些域都使用Charset ISO8859_1定义。现在我想将其更改为UTF8。 如果我在IBExpert中尝试这个,它会给我带来这段代码:

ALTER DOMAIN D_CHAR100 TYPE VARCHAR(100) CHARACTER SET UTF8;

此更新有效。但它真的有效吗?是否正确转换了所有字符,现在我将字段更改为" real" UTF8 ??还是内部仍然是ISO08859_1?

如果我在互联网上搜索,有人会说:

  • 通过临时字段解决问题并处理所有数据(大量数据库的大量工作)

和其他人说:

  • 更改域或字段数据类型就足够了。

什么是对的?怎么可能出错?我们有很多客户,我想通过脚本转换数据库。

1 个答案:

答案 0 :(得分:1)

更改字段不会更改该字段内的任何数据。它将为您揭露许多问题。执行此操作的最佳方法是复制数据,但是您还需要做更多的工作。

以下是您将遇到的一些问题:

  1. 必须更新使用此字段的任何存储过程/触发器以使用更新的变量。
  2. varchar(100)字段在ASCII中最多可占用100个字节,但在UTF中最多需要400个字节。因此,您的新UTF字段最大可以是8191。因此,无法转换此大小以上的任何varchar或char字段。
  3. 即使你已经将varchar(100)字段从ASCII转换为UTF,你仍然可以破坏选择语句,因为Firebird对行有64KB的限制。而且你在这些领域的数据大小翻了两番。
  4. 如果您有任何高于127 ASCII值的字符,则无法选择生成的列。像这样的字符将包括半个字符:½。它的值为171,当被告知为UTF8时会中断。
  5. 试试这两个陈述:

    select cast('½' as varchar(10) character set ISO8859_1)
    from rdb$database
    
    select cast('½' as varchar(10) character set UTF8)
    from rdb$database
    

    第一个起作用,第二个起作用。

    最后,简单地改变字段会暴露上面的四个问题,但是在遇到它们之前你不会知道它们是存在的,在一个复杂的数据库中可能直到生产级用户遇到它们。同时复制数据将为您自己带来更多工作,但可以让您正确处理上述所有项目。

    还有两点需要注意:

    1. 如果您复制数据,您将收到#4的错误。相反,您应该根据需要清理此数据,并使用可以正确转换这些值的外部应用程序执行此操作。 ASCII 171 = UTF 189 = 1/2字符。

    2. 执行针对这些字段的语句的任何应用程序代码仍然违反问题#3的64KB规则。您需要至少搜索所有较大的字段或语句,以确保您没有达到此目的。