【问题标题】:Comparing numbers as string in oracle在oracle中将数字与字符串进行比较
【发布时间】:2010-12-04 12:35:07
【问题描述】:

我在 Oracle 中有两个数字的比较。 010 和 10。 只要涉及数字相等,它们就相等;但是,我需要将它们作为字符串进行比较。我尝试了 to_char 但它不起作用。

是否有任何其他函数可以让我将数值作为字符串进行精确比较?

------------澄清大家的疑惑------------

我有三列地址1地址2和地址3 我只想比较所有三个连接中的数字。例如,如果值如下:
地址 1 = 01 公园大道
address2 = 20 金门
地址3 = null

然后我想比较表中的数据,看看是否有任何地址的连接值是 0120

但是现在它使 120 也与 0120 相等,这是我不希望的。

数据被提取和连接,因此不存储在某种列中。我只需要确保这些数字是“完全”比较的,而不是数字。

请提出建议。

干杯

【问题讨论】:

  • 这些数字存储在什么列数据类型中?你能写一个说明问题的小脚本吗?

标签: oracle plsql


【解决方案1】:

检查完全匹配的唯一正确方法是

select whatever
from addresses
where address1 = '01'
and   address2 = '20'
and   address3 is null;

(用绑定变量或其他列替换硬编码值)。

您忽略这个明显的解决方案的事实表明您有一些动机来比较串联的字符串,但您尚未解释。

正如您所发现的那样,通过连接进行匹配很麻烦。只要所有元素都已填充且长度固定,它就可以工作。一旦我们允许空值或可变长度值,我们就注定要失败。在元素相等的基础上,以下任何一项都不应该匹配,但是 lo! 通过连接的魔力它们可以做到:

SQL> select * from dual
  2  where 1||23 = 12||3
  3  /

D
-
X

SQL> select * from dual
  2  where 1||null||2 = 1||2||null
  3  /

D
-
X

SQL>
SQL> select * from dual
  2  where 123||null||null = 1||2||3
  3  /

D
-
X

SQL>

解决此问题的方法是明确划分连接字符串中的元素。例如,如果我们用波浪号分隔最后一个示例中的元素,我们将不再得到匹配...

SQL> select * from dual
  2  where 123||'~'||null||'~'||null = 1||'~'||2||'~'||3
  3  /

no rows selected

SQL>

【讨论】:

    【解决方案2】:

    你在这里真的没有选择 - 你要么比较字符串 - 要么比较数字。

    The "strings":
    "10"
    "010"
    "0010"
    "00010"
    

    当转换为整数时 all = 10。

    如果你从整数 10 开始,你无法知道它的“字符串”版本应该有多少个前导零。所以将它们全部存储为字符串,或者将它们作为数字进行比较 - 意思是“10”=“010”=“0010”=10。

    【讨论】:

      【解决方案3】:

      这就是你所追求的吗?

      设置一些示例数据:

      create table address as
      select
          '01 park avenue' address1,
          '20 golden gate' address2,
          '30 test' address3
      from
          dual;
      
      insert into address
      select
          '01 park avenue' address1,
          '20 golden gate' address2,
          null address3
      from
          dual;
      
      insert into address
      select
          '01 park avenue' address1,
          '20 golden gate' address2,
          null address3
      from
          dual;
      
      commit;
      

      这是一个查询,它将通过连接的数字字符串排序来查找“重复项”。我们在地址连接上使用 regexp_replace 从地址中提取数字。

      select
          address1 || address2 || address3 address_concat,
          regexp_replace(address1 || address2 || address3, '[^[:digit:]]')
                  address_numbers_only
      from
          address
      order by
          address_numbers_only;
      

      如果您要查找特定地址的匹配项 - 请尝试以下操作:

      select
          *
      from
          address
      where
          regexp_replace(address1 || address2 || address3, '[^[:digit:]]') = 
                  regexp_replace(:v_address1 ||
                          :v_address2 || 
                          :v_address3, '[^[:digit:]]');
      

      例如:

      select
          *
      from
          address
      where
          regexp_replace(address1 || address2 || address3, '[^[:digit:]]') = 
                  regexp_replace('01 park avenue' ||
                          '20 golden gate' || 
                          null, '[^[:digit:]]');
      
      -- returns...
      
      ADDRESS1        ADDRESS2        ADDRESS3
      01 park avenue  20 golden gate  
      01 park avenue  20 golden gate  
      

      【讨论】:

      • 我认为这可以满足您的要求,但是 APC 在比较之前在连接中包含分隔符的方法是可行的方法。
      【解决方案4】:

      你有一个字符串字段:

      select '010' str from dual
      

      以下选择将返回 1 行:

      select * from (select '010' str from dual) where str=10
      

      以下选择将不返回任何行:

      select * from (select '010' str from dual) where str='10'
      

      因此,即使字段是字符串,如果您在 where 子句中只写 =10,Oracle 也会将它们作为数字进行比较。如果您写='10',Oracle 会将它们作为字符串进行比较。

      【讨论】:

        【解决方案5】:

        这些数字是否以 varchars 形式存储在数据库中?如果数字存储在整数变量中,则 010 将与 10 相同。

        SELECT 010 FROM DUAL 
        

        将返回 10。这意味着一旦您将任何带有前导零的数字存储为整数,您就会丢失前导零。你无法找回你失去的东西。

        也许我理解错了,你能改一下你的问题吗?

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2023-03-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-10-17
          • 1970-01-01
          相关资源
          最近更新 更多