2009-10-07 12 views
0

J'ai une comparaison dans Oracle pour deux nombres. 010 et 10. Ils sont égaux tant que l'égalité numérique est concernée; Cependant, j'ai besoin de les comparer en tant que chaîne. J'ai essayé to_char mais ça ne marche pas.Comparaison de nombres sous forme de chaîne dans Oracle

Y at-il d'autres fonctions qui me permettraient de faire une comparaison exacte de la valeur numérique sous forme de chaîne?

------------ Pour clarifier le doute de tout le monde ---------------------

J'ai trois colonnes address1 adresse2 et adresse3 Je veux comparer UNIQUEMENT les chiffres de la concaténation des trois. Ainsi, par exemple, si les valeurs sont les suivantes:
address1 = 01 park avenue
adresse2 = 20 golden gate
Address3 = null

je voudrais comparer les données dans le tableau pour voir si l'une des adresses concaténés la valeur sort pour être 0120

Cependant en ce moment égalise 120 également avec 0120 que je ne désire pas.

Les données sont extraites et concaténées, elles ne sont donc pas stockées dans un type de colonne. Tout ce dont j'ai besoin, c'est de faire en sorte que ces chiffres soient comparés "EXACTEMENT" et non pas en chiffres.

Veuillez nous suggérer.

Vive

+2

Dans quel type de données de colonne sont stockés ces nombres? Pouvez-vous écrire un petit script qui montre le problème? –

Répondre

0

sont les numéros stockés sous forme Varchars dans le db? Si les chiffres sont stockés dans des variables entières alors 010 sera le même que 10.

SELECT 010 FROM DUAL 

retournera 10. Cela signifie qu'une fois que vous avez enregistré un nombre avec des zéros, un entier vous perdez les zéros. Vous ne pouvez pas récupérer ce que vous avez perdu.

Peut-être que je vous ai mal compris, pouvez-vous reformuler votre question?

1

Vous n'avez pas vraiment d'option ici - vous comparez des chaînes ou des nombres.

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

quand converti en nombre entier all = 10.

Si vous commencez avec un entier 10, vous avez aucun moyen de savoir combien de zéros la version « chaîne » de celui-ci devrait avoir. Donc, les stocker sous forme de chaînes ou de les comparer sous forme de nombres - ce qui signifie "10" = "010" = "0010" = 10.

0

Vous avez un champ de chaîne:

select '010' str from dual 

Les éléments suivants select retournera 1 rang:

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

la sélection suivante retourne aucune ligne:

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

Ainsi, même si le champ est une chaîne si yo Il suffit d'écrire =10 dans la clause where Oracle les comparera en tant que nombres. Si vous écrivez ='10' Oracle les comparera en tant que chaînes.

1

Est-ce ce que vous cherchez?

Mettre en place quelques exemples de données:

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; 

Voici une requête qui va trouver doublon par la commande par la chaîne de numéro concaténer. Nous extrayons les nombres de l'adresse en utilisant regexp_replace sur la concaténation d'adresse.

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

Si vous cherchez des correspondances à une adresse spécifique - essayer quelque chose comme ceci:

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

Par exemple:

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 
+0

Je pense que cela donne ce que vous demandiez, mais l'approche d'APC d'inclure un délimiteur dans la concaténation avant de comparer est la voie à suivre. –

1

La seule et unique façon correcte pour vérifier les correspondances exactes seraient

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

(Substitution de variables de liaison ou d'autres colonnes pour les valeurs codées en dur à goûter). Le fait que vous ignoriez cette solution évidente suggère que vous avez un motif pour comparer les chaînes concaténées, que vous n'avez pas encore expliquées.

L'appariement par concaténation est gênant, comme vous le découvrez. Cela fonctionne pourvu que tous les éléments soient peuplés et d'une longueur fixe. Une fois que nous autorisons les valeurs nulles ou de longueur variable, nous sommes condamnés. Aucun des éléments suivants ne doit correspondre sur la base de l'égalité des éléments, mais lo! par la magie de concaténation ils le font:

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> 

La solution à ce problème est de délimiter explicitement les éléments de la chaîne concaténée. Par exemple, si nous séparons les éléments de ce dernier exemple avec des tildes, nous n'obtiendrons plus de correspondance ...

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

no rows selected 

SQL> 
Questions connexes