ORACLE SQL динамически заменяет подстроку в большой строке на основе другой подстроки - PullRequest
0 голосов
/ 05 марта 2019

У меня есть таблица, в которой SQL-запросы хранятся в строковом столбце, как показано ниже.(Я дал 3 примера строки ниже)

select sql_query_part_1_tx  from Table1;

sql_query_part_1_tx
--------------------------------------------------------
SELECT SUM(BAL_AM) FROM SCH.DERHCE03 WHERE 1=1  AND HIRHCC04<>'US' AND HIRHCE01 IN ('TDCD','TDOA','IRATD') AND HIREG039 IN ((660),(661),(604)) AND HIREG234 <> 345 ;
SELECT SUM(BAL_AM) FROM SCH.DEFD1520 WHERE 1=1  AND HIRHCV04='Y' AND HIRHCC04<>'US' AND HIRHCN17='FDIC' AND HIFD1516<>'Y' AND HIFD1527='FDIC';
SELECT SUM(OUTSTANDING_AM) FROM SCH.DEFD1520 WHERE 1=1  AND HIRHCV04='Y' AND HIRHCC04<>'US' AND HIRHCN17='FDIC' AND HIFD1516='Y';

Таким образом, столбец sql_query_part_1_tx хранит SQL-запросы в строковом формате.мое требование состоит в том, чтобы прочитать эти запросы и выполнить их динамически и сохранить результаты в другой таблице.

Здесь проблема в вышеупомянутых хранимых запросах заключается в том, что там, где есть условие <> (не равно), оно не выбирает строки со значениями NULL (что ожидается).Но мне также нужны строки со значениями NULL.

Например:

SELECT SUM(BAL_AM) FROM SCH.DERHCE03 WHERE 1=1  AND HIRHCC04<>'US' AND HIRHCE01 IN ('TDCD','TDOA','IRATD') AND HIREG039 IN ((660),(661),(604)) AND HIREG234 <> 345 ;

В приведенной выше строке запроса есть условие HIRHCC04<>'US'.Поэтому он не будет получать записи с HIRHCC04 IS NULL.

Я хочу изменить приведенную выше строку запроса, как показано ниже, применить функцию NVL везде, где я нахожу <> в условии.

SELECT SUM(BAL_AM) FROM SCH.DERHCE03 WHERE 1=1  AND NVL(HIRHCC04,'###')<>'US' AND HIRHCE01 IN ('TDCD','TDOA','IRATD') AND HIREG039 IN ((660),(661),(604)) AND NVL(HIREG234,999999) <> 345 ;

Так что я могу также получить строки со значениями NULL для 'HIRHCC04' и 'HIREG234'.

Поэтому я хочу обновить мою таблицу, в которой хранятся эти строки запроса, с опцией NVL или COALESCE.Я надеюсь, что я ясно.

ПРИМЕЧАНИЕ. Обратите внимание, что нам необходимо учитывать тип данных и условие «НЕ В».

Ответы [ 2 ]

0 голосов
/ 05 марта 2019

Следующий запрос должен помочь:

SELECT REGEXP_REPLACE(sql_query_part_1_tx, '(\w+)\s*<>', 'COALESCE(\1, 9999) <>') 
FROM mytable;

Объяснение регулярного выражения:

  • '(\w+)\s*<>' захватывает слова (то есть последовательные буквенно-цифровые символы и символы подчеркивания) слева от<> знак с необязательной последовательностью пробелов между
  • 'COALESCE(\1, 9999) <>': заменяет совпавшую строку записанным словом (именем столбца), именуемым '\ 1'

Эта демонстрация на скрипте БД с вашими примерами возвращаемых данных:

| REGEXP_REPLACE(SQL_QUERY_PART_1_TX,'(\W+)\S*<>','COALESCE(\1,9999)<>')                                                                                                                              |
| :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| SELECT SUM(BAL_AM) FROM SCH.DERHCE03 WHERE 1=1  AND COALESCE(HIRHCC04, 9999)<>'US' AND HIRHCE01 IN ('TDCD','TDOA','IRATD') AND HIREG039 IN ((660),(661),(604)) AND COALESCE(HIREG234, 9999)<> 345 ; |
| SELECT SUM(BAL_AM) FROM SCH.DEFD1520 WHERE 1=1  AND HIRHCV04='Y' AND COALESCE(HIRHCC04, 9999)<>'US' AND HIRHCN17='FDIC' AND COALESCE(HIFD1516, 9999)<>'Y' AND HIFD1527='FDIC';                      |
| SELECT SUM(OUTSTANDING_AM) FROM SCH.DEFD1520 WHERE 1=1  AND HIRHCV04='Y' AND COALESCE(HIRHCC04, 9999)<>'US' AND HIRHCN17='FDIC' AND HIFD1516='Y';                                                   |

Кстати, позвольте мне предложить оптимизацию вашей логики замены.

Это:

COALESCE(HIRHCC04, 9999)<>'US'

Обычно пишется лучше:

(HIRHCC04 IS NULL OR HIRHCC04 <> 'US')

Второе выражение является более явным и более эффективным, поскольку оно с радостью использует существующий индекс для столбца.фильтруется (пока первое выражение не будет).Это также позволяет избежать потенциальных проблем преобразования, когда проверяемый столбец не является числом.

Эти выражения могут быть сгенерированы с помощью следующего регулярного выражения:

SELECT REGEXP_REPLACE(
    sql_query_part_1_tx, 
    '(\w+)\s*<>\s*''(\w+)''', 
    '(\1 IS NULL OR \1 <> ''\2'')'
) 
FROM mytable;

Демонстрация в БДСкрипка :

| REGEXP_REPLACE(SQL_QUERY_PART_1_TX,'(\W+)\S*<>\S*''(\W+)''','(\1ISNULLOR\1<>''\2'')')                                                                                                          |
| :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| SELECT SUM(BAL_AM) FROM SCH.DERHCE03 WHERE 1=1  AND (HIRHCC04 IS NULL OR HIRHCC04 <> 'US') AND HIRHCE01 IN ('TDCD','TDOA','IRATD') AND HIREG039 IN ((660),(661),(604)) AND HIREG234 <> 345 ;   |
| SELECT SUM(BAL_AM) FROM SCH.DEFD1520 WHERE 1=1  AND HIRHCV04='Y' AND (HIRHCC04 IS NULL OR HIRHCC04 <> 'US') AND HIRHCN17='FDIC' AND (HIFD1516 IS NULL OR HIFD1516 <> 'Y') AND HIFD1527='FDIC'; |
| SELECT SUM(OUTSTANDING_AM) FROM SCH.DEFD1520 WHERE 1=1  AND HIRHCV04='Y' AND (HIRHCC04 IS NULL OR HIRHCC04 <> 'US') AND HIRHCN17='FDIC' AND HIFD1516='Y';                                      |

ОБНОВЛЕНИЕ

Вот обновленный запрос, который также обрабатывает предложения NOT IN и разрешает обацифры и строки в левой части оператора <> (и в списках NOT IN):

SELECT REGEXP_REPLACE(
    REGEXP_REPLACE(sql_query_part_1_tx, '(\w+)\s*<>\s*(''*\w+''*)', '(\1 IS NULL OR \1 <> \2)'), 
    '(\w+)\s*NOT IN\s*(\([^)]+\))', 
    '(\1 IS NULL OR \1 NOT IN \2)'
) FROM mytable;

Демонстрация на DB Fiddle ;

| REGEXP_REPLACE(REGEXP_REPLACE(SQL_QUERY_PART_1_TX,'(\W+)\S*<>\S*(''*\W+''*)','(\1ISNULLOR\1<>\2)'),'(\W+)\S*NOTIN\S*(\([^)]+\))','(\1ISNULLOR\1NOTIN\2)')                                                                                    |
| :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| SELECT SUM(BAL_AM) FROM SCH.DERHCE03 WHERE 1=1  AND (HIRHCC04 IS NULL OR HIRHCC04 <> 'US') AND (HIRHCE01 IS NULL OR HIRHCE01 NOT IN ('TDCD','TDOA','IRATD')) AND HIREG039 IN ((660),(661),(604)) AND (HIREG234 IS NULL OR HIREG234 <> 345) ; |
| SELECT SUM(BAL_AM) FROM SCH.DEFD1520 WHERE 1=1  AND HIRHCV04='Y' AND (HIRHCC04 IS NULL OR HIRHCC04 <> 'US') AND HIRHCN17='FDIC' AND (HIFD1516 IS NULL OR HIFD1516 <> 'Y') AND HIFD1527='FDIC';                                               |
| SELECT SUM(OUTSTANDING_AM) FROM SCH.DEFD1520 WHERE 1=1  AND HIRHCV04='Y' AND (HIRHCC04 IS NULL OR HIRHCC04 <> 'US') AND HIRHCN17='FDIC' AND HIFD1516='Y';                                                                                    |
0 голосов
/ 05 марта 2019

ЭТО ОТВЕТЫ НА ОРИГИНАЛЬНУЮ ВЕРСИЮ ВОПРОСА:

Здесь проблема в вышеупомянутых хранимых запросах, где бы ни было условие <> (не равно), она не выбирает строки со значениями NULL(что ожидается).Но мне также нужны строки со значениями NULL.

Это действительно неприятно.Я не могу сказать, что я действительно оправдываю это.Ваши запросы не написаны последовательно (в одном месте есть пробелы около <>, а в другом нет пробелов).Я подозреваю, что может быть лучшее решение вашей общей проблемы, чем хранение такого необработанного SQL.

Тем не менее, я могу оценить, что у вас есть проблема.Это сложно, потому что у вас есть как строки, так и числа, что усложняет задачу.Вы могли бы иметь даты.Следующее не будет работать на даты.Но regexp_replace() может что-то сделать:

select regexp_replace(regexp_replace(q, ' ([^ <]+) ?<> ?''', ' NVL(\1, ''XXX'') <> '''), ' ([^ <)]+) ?<> ?[^'']', ' NVL(\1, -1) <> ')
from (select 'SELECT SUM(BAL_AM) FROM SCH.DERHCE03 WHERE 1=1 AND HIRHCC04<>''US'' AND HIRHCE01 IN (''TDCD'',''TDOA'',''IRATD'') AND HIREG039 IN ((660),(661),(604)) AND HIREG234 <> 345 ;' as q
     from dual) x

Примечание. Это предполагает, что ссылка перед <> является ссылкой на один столбец, а не более сложным выражением.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...