Одна единственная функция PLSQL с входными данными CLOB или VARCHAR2 и возвращаемым значением CLOB или VARCHAR2

Мне нужно написать функцию PLSQL, которая должна работать как с входными данными CLOB, так и с VARCHAR2 и возвращать CLOB или VARCHAR2 соответственно. Но функциональность, реализованная функцией, одинакова (она выполняет ряд вызовов REGEXP_REPLACE) независимо от типа ввода. Можно ли написать функцию, которая может одновременно принимать и CLOB, и VARCHAR2 и возвращать полученный тип? Я хочу избежать написания двух очень похожих функций, дублирующих код.

Моя первая функция выглядит примерно так:

FUNCTION Test(i_text CLOB) RETURN CLOB IS
v_text CLOB;
BEGIN
  v_text := i_text;  
  ... a series of REGEXP_REPLACE calls like v_text := REGEXP_REPLACE(v_text,...)
  RETURN v_text
END;

И моя другая функция:

FUNCTION Test(i_text VARCHAR2) RETURN VARCHAR2 IS
v_text VARCHAR2;
BEGIN
  v_text := i_text;  
  ... a series of REGEXP_REPLACE calls like v_text := REGEXP_REPLACE(v_text,...)
  RETURN v_text
END;

Поскольку внутри функций есть большое количество вызовов REGEXP_REPLACE, я бы предпочел иметь только одну функцию - если это возможно.

Входные данные CLOB могут иметь значительный размер, поэтому преобразование CLOB в VARCHAR2 перед вызовом функции невозможно.

Даже REGEXP_REPLACE работает с различными входными данными, такими как CHAR, VARCHAR2, NCHAR, NVARCHAR2, CLOB или NCLOB. Вот почему я надеюсь, что есть решение для этой потребности.

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

APC 12.12.2020 19:58
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
1
823
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы можете создать пакет с двумя функциями Test(Перегрузка в пакетах), такими как

CREATE OR REPLACE PACKAGE Pkg_Test IS
  FUNCTION Test (i_text VARCHAR2) RETURN VARCHAR2
  FUNCTION Test (i_text CLOB) RETURN CLOB;
END;
/

CREATE OR REPLACE PACKAGE BODY Pkg_Test IS
  FUNCTION Test (i_text VARCHAR2) RETURN VARCHAR2 IS
   val VARCHAR2;
  BEGIN
   SELECT ...
     INTO val
     FROM tab t
    WHERE t.col1 = i_text;
    
   RETURN val; 
  END;

  FUNCTION Test (i_text CLOB) RETURN CLOB IS
   val CLOB;
  BEGIN
   SELECT ....
     INTO val
     FROM tab t
    WHERE t.col2 = i_text;
    
   RETURN val; 
  END;
END;
/

и вызовите с тем же именем, что и ниже, независимо от типа данных параметра

BEGIN
  :result := Pkg_Test.test(:prm);
END;
/

Да, я знаю о перегрузке процедур, этим сейчас и занимаюсь. Но даже в этом случае мне придется дублировать длинную серию вызовов (REGEXP_REPLACE или что-то еще). Потому что даже в этом случае у вас есть две отдельные функции с двумя отдельными телами. И оба будут иметь одинаковый большой набор вызовов внутри тела. Это то, чего я пытаюсь как-то избежать.

Szilárd Kotta 12.12.2020 20:18
Ответ принят как подходящий

@BarbarosOzhan прав, что вам нужен пакет, чтобы получить возможность перегрузки. Но дублировать код не нужно. Хотя вы правы в том, что преобразование CLOB в VARCHAR2 невозможно, ничто не мешает вам преобразовать VARCHAR2 в CLOB. Затем, если вы не увеличиваете длину регулярных выражений, преобразуйте результат обратно в VARCHAR2. Затем функция, обрабатывающая varchar2, становится просто оболочкой, которая просто обрабатывает преобразования.

create or replace package test_pkg is
    function test(i_text clob) return clob;
    function test(i_text varchar2) return varchar2;
end test_pkg;   
/

create or replace package body test_pkg is
    function test(i_text clob) return clob is
      v_text clob;
    begin
      v_text := i_text;  
      --...
      return v_text;
    end test;
    
    function test(i_text varchar2) return varchar2 is
      v_text clob;
      v_res  varchar2(32767);   -- 4000 is actually used in SQL statement
    begin
       v_text := cast(i_text as clob); 
       v_res := cast (test(v_text) as varchar2);
       return v_res;
    end test;
end test_pkg; 

Ваша подпрограмма вызова должна ожидать и обрабатывать исключение «ORA-06502: PL/SQL: числовая ошибка или ошибка значения: буфер символьной строки слишком мал»

Спасибо @Belayer. Это здорово, я не знал, что кастинг из VARCHAR2 в CLOB так прост. Это решило мою проблему.

Szilárd Kotta 13.12.2020 20:06

Рад, что смог помочь. Я тоже этого не знал - никогда этого не делал. Но это казалось логичным, в конце концов, CLOB — это очень длинный VARCHAR2. Много лет назад я изучил очень полезную технику, она называется «выдача желаемого за действительное». Это происходит из психологии, но для разработки это в основном переводится как «Хотел бы я сделать X», поэтому напишите фрагмент кода, который делает X. Если он работает, вы можете это сделать; если не двигаться дальше.

Belayer 13.12.2020 20:26

Мне нравится такое позитивное мышление :)

Szilárd Kotta 14.12.2020 22:13

Другие вопросы по теме