2017-01-11 8 views
1

Я использую Oracle SQL и хочу знать, как два запроса ниже возвращают то же самое, что и иногда, а иногда и другой результат.SQL: using substr вместе с 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; 

1-запрос имеет длину зиЬзЬг значения 3, в то время как второй запрос имеет длину SubStr значения 2. Тем не менее, когда min_code равно 151 оба запроса вернется 16. Как это возможно?

Я понимаю, что это должно быть связано с тем, как substr вычисляет длину при использовании to_char, но я понимаю, что второй аргумент (1 в этих случаях) - это то, где должна начинаться подстрока, а третий аргумент - длина подстроки. Тем не менее, первый запрос по-прежнему возвращает 16 вместо 161, как я мог себе представить.

Затем, когда я тестирую его с записью, где min_code будет равен 051, первый запрос вернет 06, тогда как второй запрос вернет 61. Я понимаю, как второй запрос получает 61, поскольку он должен отбрасывать ведущее 0 при выполнении арифметическая операция НО, как на самом деле 1-й запрос (с функцией to_char) возвращает 06. Я ожидал бы, что 061 будет равно 3.

+1

Try 'select '|' || to_char (151, '099') || '|' от double', затем отредактируйте маску формата в ''FM099''; это должно помочь вам найти проблему – Aleksej

ответ

1

Просто поместите ваши тесты в один запрос и удалите +10 (проблема там не существует), это то, что у вас есть:

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 

Я верю, что заставляет вас ожидать другого результата что должно быть to_char; уточнить, посмотрим на результат следующих действий:

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| 

Здесь вы видите, что to_char добавили ведущее место в результирующих строк; это приводит к сбою логики подстроки, что дает вам неожиданный результат, который у вас есть. Такое поведение четко разъяснены here:

Дополнительное ведущее пространство для потенциального минус. Чтобы удалить пространство можно использовать FM в формате

В самом деле, если вы измените маску формата, то есть

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| 

и ваши Тестовые стали:

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