Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Ошибка при разборе getStringVal / 14 сообщений из 14, страница 1 из 1
23.09.2017, 20:32
    #39525325
Sheriffua
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при разборе getStringVal
Всем привет. Может кто-то наведет на правильную мысль. Есть такая конструкция:

Код: plsql
1.
2.
3.
4.
5.
6.
SELECT TRANSLATE (
                        XMLAGG (XMLELEMENT ("node", d1.name)).getStringVal (),
                        '<node>/',
                        ' ')
                FROM ICC_RSR.DICT_REGIONS d1
               WHERE opv.text_value LIKE '%' || TO_CHAR (d1.reg_id) || '%'



В которую передается строка вида:
Код: sql
1.
1,2,6


то названия из справочника региона подтягиваются правильно, согласно классификации reg_id
Но, если передать строку вида:
Код: sql
1.
24


то отработка происходит, по 2, 4 и 24 ! Почему так происходит, может есть вариант как можно четко организовать правильную передачу ,в чем загвоздка?
Код: plsql
1.
2.
3.
4.
5.
Oracle Database 10g Enterprise Edition Release 10.2.0.5.0 - 64bi
PL/SQL Release 10.2.0.5.0 - Production
CORE	10.2.0.5.0	Production
TNS for Linux: Version 10.2.0.5.0 - Production
NLSRTL Version 10.2.0.5.0 - Production
...
Рейтинг: 0 / 0
23.09.2017, 20:57
    #39525328
SY
SY
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при разборе getStringVal
А мозг включить?

Код: plsql
1.
opv.text_value LIKE '%' || TO_CHAR (d1.reg_id) || '%'



превращаетcя для d1.reg_id = 2 в

Код: plsql
1.
'24' LIKE '%2%'



и результат = TRUE. Для d1.reg_id = 4 в

Код: plsql
1.
'24' LIKE '%4%'



и результат = TRUE. Для d1.reg_id = 24 в

Код: plsql
1.
'24' LIKE '%24%'



и результат тоже TRUE. Проверять надо:

Код: plsql
1.
',' || opv.text_value || ',' LIKE '%,' || TO_CHAR (d1.reg_id) || ',%' and d1.reg_id IS NOT NULL



А лучше:

Код: plsql
1.
d1.reg_id in (select regexp_substr(opv.text_value,'[^,]+',1,level) from dual connect by level <= regexp_count(opv.text_value,',') + 1)



SY.
...
Рейтинг: 0 / 0
23.09.2017, 21:43
    #39525339
SY
SY
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при разборе getStringVal
Не заметил версию 10.2, так-что замени REGEXP_COUNT на REGEXP_REPLACE + LENGTH. Надеюсь сообразишь. А если гоняешься за миллисекундами, то замени REGEXPы на SUBSTR + INSTR.

SY.
...
Рейтинг: 0 / 0
23.09.2017, 21:46
    #39525341
Sheriffua
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при разборе getStringVal
SY,

Спасибо.

Но я не понял почему для
Код: plsql
1.
opv.text_value LIKE '%' || TO_CHAR (d1.reg_id) || '%'


когда поступает строка именно 24 , а она режется на 2, затем 4 и 24.

И почему лучше использовать:

Код: plsql
1.
d1.reg_id in (select regexp_substr(opv.text_value,'[^,]+',1,level) from dual connect by level <= regexp_count(opv.text_value,',') + 1)
...
Рейтинг: 0 / 0
23.09.2017, 21:55
    #39525343
SY
SY
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при разборе getStringVal
Sheriffua,

Для тех кто в т-34, LIKE '%2%' означает поверку на наличие двойки в любой позиции, так что резльтат будет "да" для любого значения opv.text_value в котором присутствует двойкa.

SY.
P.S. Забыл что у тебя разделитeль дробной части зпт а не тчк как у мeня. И вообще, чтобы избежать NLS проблем используй другoй разделитeль в opv.text_value, например, pipe вкупе с:

Код: plsql
1.
'|' || opv.text_value || '|' LIKE '%|' || TO_CHAR (d1.reg_id) || '|%' and d1.reg_id IS NOT NULL
...
Рейтинг: 0 / 0
23.09.2017, 22:00
    #39525344
SY
SY
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при разборе getStringVal
SheriffuaИ почему лучше использовать:


d1.reg_id может быть проиндексирован.

SY.
...
Рейтинг: 0 / 0
24.09.2017, 08:15
    #39525385
Sheriffua
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при разборе getStringVal
SYSheriffua,

Для тех кто в т-34, LIKE '%2%' означает поверку на наличие двойки в любой позиции , так что резльтат будет "да" для любого значения opv.text_value в котором присутствует двойкa.

SY.
P.S. Забыл что у тебя разделитeль дробной части зпт а не тчк как у мeня. И вообще, чтобы избежать NLS проблем используй другoй разделитeль в opv.text_value, например, pipe вкупе с:

Код: plsql
1.
'|' || opv.text_value || '|' LIKE '%|' || TO_CHAR (d1.reg_id) || '|%' and d1.reg_id IS NOT NULL



)))

Еще раз - строка opv.text_value = 24 , но разбор происходит как 2 и 4 и 24... этим выражением:
Код: plsql
1.
2.
3.
4.
5.
6.
SELECT TRANSLATE (
                        XMLAGG (XMLELEMENT ("node", d1.name)).getStringVal (),
                        '<node>/',
                        ' ')
                FROM ICC_RSR.DICT_REGIONS d1
               WHERE opv.text_value LIKE '%' || TO_CHAR (d1.reg_id) || '%'


Т.е. в строку
Код: sql
1.
WHERE opv.text_value LIKE '%' || TO_CHAR (d1.reg_id) || '%'


почему происходит преобразование в 2, затем в 4, и затем в 24? Это getStringVal так преобразует или что смотреть чтобы понять отчего происходит такой разбор?
...
Рейтинг: 0 / 0
24.09.2017, 09:09
    #39525388
Elic
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при разборе getStringVal
Sheriffuaчто смотреть чтобы понять отчего происходит такой разбор? 20818315 - просто снимись с ручника, там Соломон всё подробнейше разжевал.
...
Рейтинг: 0 / 0
24.09.2017, 14:48
    #39525430
SY
SY
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при разборе getStringVal
Sheriffuaпочему происходит преобразование в 2, затем в 4, и затем в 24? Это getStringVal так преобразует или что смотреть чтобы понять отчего происходит такой разбор?

Да причем тут getStringVal??? Я кажется ясно обьяснил что без обрамления разделитeлями LIKE '%' || TO_CHAR (d1.reg_id) || '%' выдаст "да" если d1.reg_id является частью одного из чисел в opv.text_value:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
with d1 as (
            select 2  reg_id from dual union all
            select 4  reg_id from dual union all
            select 24 reg_id from dual
           )
select  reg_id
  from  d1
  where '24' like '%' || to_char(d1.reg_id) || '%'
/

    REG_ID
----------
         2 -- символ двойка присутствует в строке '24' (мы сраниваем строки, не числа) посему '24' like '%2%' дает "да"
         4 -- символ четверка присутствует в строке '24' (мы сраниваем строки, не числа) посему '24' like '%4%' дает "да"
        24 -- символ двойка за которой слeдует символчетверка (мы сраниваем строки, не числа) присутствует в строке '24' посему '24' like '%24%' дает "да" 

SQL>



SY.
...
Рейтинг: 0 / 0
24.09.2017, 16:02
    #39525445
Sheriffua
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при разборе getStringVal
SY,

спасибо за подробное разъяснение.
...
Рейтинг: 0 / 0
24.09.2017, 16:27
    #39525455
SY
SY
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при разборе getStringVal
Sheriffuaспасибо за подробное разъяснение.

Но я советую:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
d1.reg_id in (
              select  regexp_substr(opv.text_value,'[^,]+',1,level)
                from  dual
                connect by level <= length(
                                           regexp_replace(
                                                          opv.text_value || ',',
                                                          '[^,]'
                                                         )
                                          )
             )



SY.
...
Рейтинг: 0 / 0
25.09.2017, 08:17
    #39525558
Sheriffua
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при разборе getStringVal
SYSheriffuaспасибо за подробное разъяснение.

Но я советую:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
d1.reg_id in (
              select  regexp_substr(opv.text_value,'[^,]+',1,level)
                from  dual
                connect by level <= length(
                                           regexp_replace(
                                                          opv.text_value || ',',
                                                          '[^,]'
                                                         )
                                          )
             )



SY.

Спасибо за совет с применением регулярных выражений.
Если несложно, то в двух словах, чем он лучше LIKE? , который ты привел в своем первом сообщении?
...
Рейтинг: 0 / 0
25.09.2017, 13:28
    #39525768
SY
SY
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при разборе getStringVal
SheriffuaЕсли несложно, то в двух словах, чем он лучше LIKE? , который ты привел в своем первом сообщении?

Я уже обьяснял: d1.reg_id может быть проиндексирован.


Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
SQL> explain plan for
  2  select  *
  3    from  emp
  4    where ',' || '7566,7654,7698' || ',' like '%,' || empno || ',%'
  5  /

Explained.

SQL> select  *
  2    from  table(dbms_xplan.display)
  3  /

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------

Plan hash value: 3956160932

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |     1 |    38 |     3   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| EMP  |     1 |    38 |     3   (0)| 00:00:01 |
--------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter(',7566,7654,7698,' LIKE '%,'||TO_CHAR("EMPNO")||',%')

13 rows selected.

SQL> explain plan for
  2  select  *
  3    from  emp
  4    where empno in (
  5                    select  regexp_substr('7566,7654,7698','[^,]+',1,level)
  6                      from  dual
  7                      connect by level <= length(regexp_replace('7566,7654,7698'  || ',','[^,]'))
  8                   )
  9  /

Explained.

SQL> select  *
  2    from  table(dbms_xplan.display)
  3  /

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------

Plan hash value: 1513497066

------------------------------------------------------------------------------------------------------
| Id  | Operation                                 | Name     | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                          |          |     1 |    68 |     4  (25)| 00:00:01 |
|   1 |  NESTED LOOPS                             |          |     1 |    68 |     4  (25)| 00:00:01 |
|   2 |   NESTED LOOPS                            |          |     1 |    68 |     4  (25)| 00:00:01 |
|   3 |    VIEW                                   | VW_NSO_1 |     1 |    30 |     3  (34)| 00:00:01 |
|   4 |     HASH UNIQUE                           |          |     1 |       |     3  (34)| 00:00:01 |
|*  5 |      CONNECT BY WITHOUT FILTERING (UNIQUE)|          |       |       |            |          |
|   6 |       FAST DUAL                           |          |     1 |       |     2   (0)| 00:00:01 |
|*  7 |    INDEX UNIQUE SCAN                      | PK_EMP   |     1 |       |     0   (0)| 00:00:01 |
|   8 |   TABLE ACCESS BY INDEX ROWID             | EMP      |     1 |    38 |     1   (0)| 00:00:01 |
------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   5 - filter(LEVEL<=3)
   7 - access("EMPNO"=TO_NUMBER("REGEXP_SUBSTR('7566,7654,7698','[^,]+',1,LEVEL)"))

Note
-----
   - this is an adaptive plan

25 rows selected.

SQL>



И если даже если индекса нет, то он может понадобиться позже когда, например, обьем данных возрастет и TABLE ACCESS FULL станет слишком медленным. В случае с LIKE придется переписывать код а с IN все прозрачно и он подхватит созданный индекс.

SY.
...
Рейтинг: 0 / 0
25.09.2017, 15:07
    #39525845
Sheriffua
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при разборе getStringVal
SY,

Теперь все понятно. Спасибо еще раз за подробное объясение, тему можно закрывать.
...
Рейтинг: 0 / 0
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Ошибка при разборе getStringVal / 14 сообщений из 14, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]