2017-01-11 1 views
1

J'utilise Oracle SQL et je veux savoir comment les 2 requêtes ci-dessous retournent exactement la même chose parfois et d'autres fois un résultat différent.SQL: using substr avec to_char

select substr(to_char(min_code + 10, '099'),1,3) 
from x 
where a = b; 


select substr(min_code + 10,1,2) 
from x 
where a = b; 

La 1ère requête a la longueur de substr fixé à 3, alors que la 2ème requête a la longueur de substr mis à 2. Toutefois, lorsque min_code est égal à 151 deux requêtes renverront 16. Comment est-ce possible? Je réalise qu'il doit s'agir de la façon dont substr calcule la longueur lors de l'utilisation de to_char mais je crois comprendre que le 2ème argument (1 dans ces cas) est où la sous-chaîne doit commencer et le 3ème argument est le longueur de la sous-chaîne. Pourtant, la première requête renvoie toujours 16 au lieu de 161 comme je l'aurais imaginé. Ensuite, quand je le testerai avec un enregistrement où min_code sera égal à 051, la 1ère requête retournera 06, alors que la 2ème requête retournera 61. Je comprends comment la 2ème requête obtient 61 car elle doit laisser tomber le 0 initial lors de l'exécution l'opération arithmétique MAIS comment diable la première requête (avec la fonction to_char) renvoie 06. Je m'attendrais à 061 comme longueur est 3.

+1

Essayez 'select '|' || to_char (151, '099') || '|' de dual', puis éditez le masque de format dans ''FM099''; cela devrait vous aider à trouver le problème – Aleksej

Répondre

1

Il suffit de mettre vos tests dans une seule requête et en supprimant le +10 (le problème n'est pas là), voici ce que vous avez:

SQL> with testCases(n) as (select 151 from dual union select 51 from dual) 
    2 select n, 
    3   substr(to_char(n, '099'),1,3) as substr_3, 
    4   substr(n,1,2) as substr_3 
    5 from testCases; 

     N SUBSTR_3  SUBSTR_3 
---------- ------------ -------- 
     51 05   51 
     151 15   15 

Je crois que ce qui vous fait espérer un résultat différent est qu'est-ce que to_char est censé faire? de clarifier, consultez le résultat des éléments suivants:

SQL> with testCases(n) as (select 151 from dual union select 51 from dual) 
    2 select n, 
    3   '|' || to_char(n, '099') || '|' as to_char 
    4 from testCases; 

     N TO_CHA 
---------- ------ 
     51 | 051| 
     151 | 151| 

Ici, vous voyez que to_char ajouté un espace menant aux chaînes résultantes; cela fait échouer votre logique de sous-chaîne, vous donnant le résultat inattendu que vous avez. Ce comportement est clairement expliqué here:

L'espace supplémentaire est leader pour le potentiel signe moins. Pour supprimer l'espace vous pouvez utiliser FM au format

En fait, si vous modifiez le masque de format, vous avez

SQL> with testCases(n) as (select 151 from dual union select 51 from dual) 
    2 select n, 
    3   '|' || to_char(n, 'FM099') || '|' as to_char 
    4 from testCases; 

     N TO_CHA 
---------- ------ 
     51 |051| 
     151 |151| 

et vos cas de test deviennent:

SQL> with testCases(n) as (select 151 from dual union select 51 from dual) 
    2 select n, 
    3   substr(to_char(n, 'FM099'),1,3) as substr_3, 
    4   substr(n,1,2) as substr_2 
    5 from testCases ; 

     N SUBSTR_3  SUBSTR_2 
---------- ------------ -------- 
     51 051   51 
     151 151   15