【问题标题】:Replace character in SQL results替换 SQL 结果中的字符
【发布时间】:2010-11-11 13:05:03
【问题描述】:

这是来自 Oracle SQL 查询。它在数据库中应该有撇号的地方有这些奇怪的细长矩形。 (我希望我们可以在这里粘贴屏幕截图)

当我复制并粘贴结果时,它看起来像这样。

spouse�s

有没有办法编写一个 SQL SELECT 语句,在字段中搜索该字符并在结果中用撇号替换它?

编辑:出于报告目的,我只需要更改 SELECT 语句中的结果,我无法更改数据库。


我跑了这个

select dump('�') from dual;

返回的

Typ=96 Len=3: 239,191,189

到目前为止,这似乎有效

select translate('What is your partner's first name?', '�', '''') from dual;

但这不起作用

select translate(Fieldname, '�', '''') from TableName


从 TN 中选择 FN

你配偶的名字是什么?

从 TN 中选择 DUMP(FN, 1016)

Typ=1 Len=33 CharacterSet=US7ASCII: 57,68,61,74,20,69,73,20,79,6f,75,72,20,73,70,6f,75,73,65 ,92,73,20,66,69,72,73,74,20,6e,61,6d,65,3f


编辑: 所以我已经确定这是反引号字符。我无法更新数据库,所以我正在尝试这段代码

从 TN 中选择 REGEX_REPLACE(FN,"\0092","\0027")

我得到 ORA-00904:"Regex_Replace":invalid identifier

【问题讨论】:

  • 我会为您的问题添加更多信息。 1) 通过阅读下面的 cmets,您似乎无法通过查询工具在数据库上运行 UPDATE 语句。如果您不能这样做,那么您实际上无法按书面形式解决您的问题。您可以从您的应用程序中访问数据库/创建 SQL 语句吗?
  • 您是否在您的应用中看到了这个角色?您是否在查询工具中看到了这一点?
  • 我在 SQL Navigator、SQL Developer 和 ASP.net 中看到了这一点
  • CP-1252(默认 Windows 代码页)中的 0x92 是一个反引号字符,看起来有点像撇号。此代码不是有效的 ASCII 字符,在 IS0-8859-1 中也无效。因此,可能数据库是 CP-1252 编码(不太可能),或者是通过 CP-1252 插入的数据库连接,或者撇号以某种方式转换为 0x92。数据库返回在 CP-1252 中有效的值(或其他 0x92 有效的字符集),但您的 db 客户端连接不期望 CP-1252。因此,奇怪的问号。
  • 人们使用反引号是因为撇号会破坏应用程序

标签: sql oracle replace character-encoding character


【解决方案1】:

这似乎是您的字符集配置的问题。检查您的 NLS_LANG 和其他 NLS_xxx 环境/注册表值。您必须检查 oracle 服务器、您的客户端和该数据插入器的客户端。

尝试DUMP 的值。你可以用一个简单的选择来做到这一点:

SELECT DUMP(the_column)
  FROM xxx
 WHERE xxx

UPDATE:我认为在尝试替换之前,先寻找问题的根源。如果发生这种情况是因为字符集问题,您可能会遇到糟糕数据的大问题。

更新 2:回答 cmets。问题可能不在数据库服务器端,可能在客户端。问题(如果这是问题)可能是服务器与客户端通信的转换。它用于服务器-客户端错误的配置协调。例如,如果服务器定义了 UTF8 字符集,而您的客户端使用 US7ASCII,那么所有尖音符都将显示为 ?。

另一种方法是,如果服务器定义了 UTF8 字符集,而您的客户端也定义了 UTF8,但应用程序无法显示 UTF8 字符,那么问题出在应用程序端。

更新 3:关于您的示例:

  • select translate('What。之所以有效,是因为 � 是完全相同的字符:您已粘贴在两面。
  • select translate(Fieldname。它不起作用,因为 � 没有存储在数据库中,它是客户端收到的字符,可能是因为从数据表中发生了一些转换,直到它显示给您。

下一步:查看DUMP 语法并尝试提取神秘字符的代码(从未粘贴的表中提取...!)。

【讨论】:

  • 请注意,OP 可能无法对此进行控制。他可能不是 Oracle 管理员,并且可能无法在所有部署区域(包括来自其他系统的入站接口)中更改或强制执行这些客户端设置。从他的问题来看,我的猜测是,他是应用程序开发人员,而不是数据库管理员。从这个角度来看,他可能会更好地更换它们。这完全取决于他的 DBA 以及与他们合作的难易程度。 :)
  • 无论如何,如果存在问题,这是针对具体问题的解决方法。但如果不解决(或请求 DBA 解决)根本问题,则数据库可能状态不佳。
  • 我不是数据库管理员。不可能对数据库进行任何更改。
  • 鉴于他的字符响应,数据库和客户端之间可能存在字符集不匹配。我不会想到的;这将是我将来需要更加了解的事情。
【解决方案2】:

我会说这个角色很有可能是一个单勾“智能引用”(我讨厌这个名字)。智能引号是字符 91-94(使用 Windows 编码)或 Unicode U+2018、U+2019、U+201C 和 U+201D。

【讨论】:

    【解决方案3】:

    我将提出一种基于前端应用程序的客户端方法来解决该问题:

    我怀疑这个问题更多地与您尝试显示单词配偶的字体与字符之间的不匹配有关。当您尝试以没有字符代码字形的 Unicode 字体显示字符时,会出现该图标。

    Oracle 数据库将尽职地返回插入到其列中的任何字符。考虑到您尝试在应用程序中显示数据的字体,您和您的应用程序更多地取决于您和您的应用程序来解释它的外观,因此我建议调查一下这个神秘的字符是什么取代了您的撇号。首先使用 FerranB 推荐的 DUMP()。

    尝试运行以下查询以获取字符代码:

    SELECT DUMP(<column with weird character>, 1016) 
    FROM <your table> 
    WHERE <column with weird character> like '%spouse%';
    

    如果这不能从数据库中获取实际文本,则需要修改 WHERE 子句以实际获取有问题的列。

    一旦您找到了字符的代码,您就可以使用regex_replace() 内置函数来替换字符,方法是确定字符的原始十六进制代码,然后提供 ASCII / C0 控件和基本拉丁文字符 0x0027 ('),使用类似这样的代码:

    UPDATE <table>
        set <column with offending character> 
                = REGEX_REPLACE(<column with offending character>,
                                "<character code of �>",
                                "'")
    WHERE regex_like(<column with offending character>,"<character code of �>");
    

    如果您不熟悉 Unicode 和不同的字符编码方式,我建议您阅读 Joel 的文章 The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)。直到我读了那篇文章才知道。


    编辑:如果您看到 0x92,则此处可能存在字符集不匹配:

    CP-1252(默认 Windows 代码页)中的

    0x92 是一个反引号字符,看起来有点像撇号。此代码不是有效的 ASCII 字符,在 IS0-8859-1 中也无效。因此,可能数据库是 CP-1252 编码(不太可能),或者是通过 CP-1252 插入的数据库连接,或者撇号以某种方式转换为 0x92。数据库返回在 CP-1252 中有效的值(或其他 0x92 有效的字符集),但您的 db 客户端连接不期望 CP-1252。因此,奇怪的问号。

    FerranB 可能是对的。我会与您的 DBA 或其他管理员讨论此问题,以解决问题。如果你不能,我会尝试进行上面的更新(似乎你不能),或者这样做:

    INSERT (<normal table columns>,...,<column with offending character>) INTO <table>
    SELECT <all normal columns>, REGEX_REPLACE(<column with offending character>,
                                 "\0092",
                                 "\0027")  -- for ASCII/ISO-8859-1 apostrophe
    FROM <table>
    WHERE regex_like(<column with offending character>,"\0092");
    
    DELETE FROM <table> WHERE regex_like(<column with offending character>,"\0092");
    

    【讨论】:

    • "Oracle 数据库将尽职尽责地返回插入到其列中的任何字符" 不完全是。如果数据是字符(例如 VARCHAR2)而不是 RAW,Oracle 可以将插入数据的客户端的字符集转换为数据库的字符集,然后再转换为请求数据的客户端的字符集。通常,如果数据库设置为 UTF8 并且客户端设置相同,那么您不会遇到问题。
    • 假设您可以控制所述字符集。最后,这一切都与位有关,以及您将它们解释为什么。一个强大的应用程序也应该在内部处理此类问题。
    • 尝试运行以下查询:SELECT DUMP(, 1016) FROM WHERE like '%spouse%'。
    • 我运行它并将其添加到我的帖子顶部。
    • 我认为这是一个反引号。人们在这里使用的旧版 vb6(实际上是 sql)无法处理撇号,所以我认为 dba 告诉他们使用反引号。
    【解决方案4】:

    在您执行此操作之前,您需要了解实际发生的情况。在我看来,有人在数据库中插入了非 ascii 字符串。例如 Unicode 或 UTF-8。在修复此问题之前,请确保这实际上是一个错误。撇号有多种形式,而不仅仅是“'”。

    【讨论】:

      【解决方案5】:

      TRANSLATE() 是一个用于替换或消除已知单字符代码的有用函数。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-08-22
        • 2017-02-20
        • 1970-01-01
        • 2015-02-27
        • 1970-01-01
        • 1970-01-01
        • 2011-04-03
        • 2012-08-19
        相关资源
        最近更新 更多