Сравните значения в каждом столбце двух типов Oracle - PullRequest
3 голосов
/ 09 апреля 2010

Сегодня я поигрался с pluto-test-framework , и я хотел бы добавить некоторые существующие функции в тестовый комплект.

У меня много функций с этим типом спецификации.

   FUNCTION DO_SOME_STUFF   (pOldSchedule       IN      SCHEDULE_OBJ,
                             pNewSchedule          OUT  SCHEDULE_OBJ,
                             pLoggerContext     IN OUT  LOGGER_CONTEXT_OBJ)
   RETURN NUMBER;

Он принимает pOldSchedule, что-то с ним делает, а затем возвращает pNewSchedule. Logger_context только делает регистрацию.

В рамках теста я хотел бы иметь возможность сравнивать значения в каждом из столбцов типа без необходимости писать отдельные операторы IF.

Потребуется вернуть логическое значение, чтобы указать, совпадают или нет pOldSchedule и pNewSchedule.

Есть идеи?

1 Ответ

6 голосов
/ 10 апреля 2010

Простые тесты на равенство работают с вложенными таблицами:

SQL> declare
  2      type nt is table of number;
  3      nt1 nt;
  4      nt2 nt;
  5      nt3 nt;
  6  begin
  7      nt1 := nt(1,2,3);
  8      nt2 := nt(1,2,3);
  9      if nt1 = nt2 then
 10          dbms_output.put_line('NT2 is the same nested table as NT1');
 11      else
 12          dbms_output.put_line('NT2 is a different nested table from NT1');
 13      end if;
 14      nt2 := nt(1,2,3,4);
 15      if nt1 = nt3 then
 16          dbms_output.put_line('NT3 is the same nested table as NT1');
 17      else
 18          dbms_output.put_line('E3 is a different nested table from NT1');
 19      end if;
 20  end;
 21  /
NT2 is the same nested table as NT1
E3 is a different nested table from NT1

PL/SQL procedure successfully completed.

SQL>

Однако то же самое не относится к полнофункциональным объектам:

SQL> create or replace type new_emp as object (
  2      ename varchar2(10)
  3      , sal number
  4      , deptno number
  5      , job varchar2(10))
  6  /

Type created.

SQL> declare
  2      e1 new_emp;
  3      e2 new_emp;
  4  begin
  5      e1 := new_emp('KESTELYN', 3700, 30, 'MARKETING');
  6      e2 := new_emp('KESTELYN', 3700, 30, 'MARKETING');
  7      if e1 = e2 then
  8          dbms_output.put_line('E2 is the same as E1');
  9      else
 10          dbms_output.put_line('E2 is different from E1');
 11      end if;
 12  end;
 13  /
    if e1 = e2 then
          *
ERROR at line 7:
ORA-06550: line 7, column 11:
PLS-00526: A MAP or ORDER function is required for comparing objects in PL/SQL.


SQL>

Нам нужно явно определить функцию-член для выполнения сравнений. Так что здесь тот же объект с функцией MAP. Пример реализации генерирует хешированную строку, которая полезна, если мы хотим сохранить значение для последующего сравнения, но она может просто вернуть объединенную строку (особенно, если EXECUTE для DBMS_CRYPTO не предоставляется по умолчанию). Функции NVL () необходимы, чтобы избежать (равных нулю, значению) и (значению, нулю) оценки как равных. При использовании магических ценностей всегда существует риск, поэтому мы должны тщательно выбирать их.

SQL> create or replace type new_emp as object (
  2      ename varchar2(10)
  3      , sal number
  4      , deptno number
  5      , job varchar2(10)
  6      , map member function equals return raw)
  7  /

Type created.

SQL> create or replace type body new_emp as
  2      map member function equals return raw
  3      is
  4      begin
  5          return dbms_crypto.hash(
  6                     utl_raw.cast_to_raw(nvl(self.ename,'***')||
  7                                          nvl(self.sal,-99)||
  8                                          nvl(self.deptno,-99)||
  9                                          nvl(self.job,'***')
 10                                        )
 11                                   , 1);
 12      end equals;
 13  end;
 14  /

Type body created.

SQL>

Теперь у нас есть база для сравнения экземпляров наших объектов:

SQL> declare
  2      e1 new_emp;
  3      e2 new_emp;
  4  begin
  5      e1 := new_emp('KESTELYN', 3700, 30, 'MARKETING');
  6      e2 := new_emp('KESTELYN', 3700, 30, 'MARKETING');
  7      if e1 = e2 then
  8          dbms_output.put_line('E2 is the same as E1');
  9      else
 10          dbms_output.put_line('E2 is different from E1');
 11      end if;
 12  end;
 13  /
E2 is the same as E1

PL/SQL procedure successfully completed.

SQL>    

Вам может быть интересно, почему Oracle не делает этого по умолчанию. Что ж, реализация TYPE допускает только один метод сравнения (если у нас есть функция MAP, у нас не может быть функции ORDER), поэтому нам нужно иметь возможность выбрать собственное определение равенства. Например, тип с именем rectangle может иметь функцию MAP с именем area(), которая возвращает self.width * self.length.

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