Як перемістити збережені процедури SQL Server за допомогою тимчасових таблиць або змінних таблиць до Oracle?


9

Розробник C #, який заохочується керівництвом писати збережені SQL Server процедури, часто виробляє такі процедури

create table #t1 (...);
insert into #t1 Select ... from table_a where ...;
insert into #t1 Select ... from table_b where ...;
update #t1 Set ... = ... where ...
Select * from #t1;

Одне твердження досить просте, і цей метод змушує їх давати правильні результати.

Часто моє завдання - перенести такі процедури в Oracle.

Давайте розберемося з такими фактами.

  • Різні тимчасові таблиці в SQL Server повністю незалежні і можуть мати будь-яку спеціальну структуру.
  • Загальні загальні таблиці Oracle - це глобальні об'єкти, і всі користуються значною мірою однаковою структурою таблиць. Змінити цю структуру неможливо, хоча вона використовується де завгодно.

Одне з речей, які я дізнався від dba Oracle, - це уникати використання тимчасових таблиць, коли це можливо. Навіть продуктивність на SQL сервері виграє від таких модифікацій.

Замініть окремі вставки союзами

У найпростішому випадку вищесказане може бути перетворене на щось подібне

select case when ... then ... end, ... from table_a where ...
union
select case when ... then ... end, ... from table_b where ...
Order by ...;

Використання функцій

Як скалярні, так і функції, що оцінюються за таблицею, можуть допомогти перетворити вашу процедуру в один запит вищевказаної форми.

Загальні вирази таблиць, також факторинг підзапросів

Факторинг підзапросів - це майже найкраще, що пропонує Oracle, щоб уникнути тимчасових таблиць. За його допомогою міграція SQL Server до Oracle знову досить проста. Для цього потрібен SQL Server 2005 і вище.


Ці зміни покращують версію SQL Server і в багатьох випадках роблять міграцію прямо вперед. В інших випадках вдача до глобальних тимчасових таблиць дає можливість здійснювати міграцію в обмежений час, але це менш задовольняє.


Чи є інші способи уникнути використання глобальних тимчасових таблиць в Oracle?


3
Я скажу, що такий код вказує на процедурне невстановлене мислення. І це локальні тимчасові таблиці з єдиним #. Я керую, і я зламав би ноги, якби побачив, що йде у виробництво :-)
gbn

Я повністю згоден
bernd_k

@gbn - Ідіоматичний PL / SQL має тенденцію бути трохи більш процедурним, ніж ідіоматичний T-SQL. Тимчасові таблиці дозволяють робити майже все, що знаходиться в наборі операцій у T-SQL. PL / SQL має паралельні опції курсору та набагато більше функціональних можливостей для оптимізації процесуального коду.
ConcernedOfTunbridgeWells

Відповіді:


3

Одним із способів зробити це будуть типи об'єктів , у цьому випадку тип буде аналогічним вашому #t1. Отже, його потрібно десь визначити, але не потрібно бути глобальним, це може бути навіть схема або процедура. По-перше, ми можемо створити тип:

SQL> create or replace type t1_type as object (x int, y int, z int)
  2  /

Type created.

SQL> create or replace type t1 as table of t1_type
  2  /

Type created.

Тепер встановіть кілька прикладних даних:

SQL> create table xy (x int, y int)
  2  /

Table created.

SQL> insert into xy values (1, 2)
  2  /

1 row created.

SQL> insert into xy values (3, 4)
  2  /

1 row created.

SQL> commit
  2  /

Commit complete.

І створити функцію над цими даними, повертаючи наш "тимчасовий" тип:

SQL> create or replace function fn_t1 return t1 as
  2  v_t1 t1 := t1();       -- empty temporary table (really an array)
  3  v_ix number default 0; -- array index
  4  begin
  5  for r in (select * from xy) loop
  6  v_ix := v_ix + 1;
  7  v_t1.extend;
  8  v_t1(v_ix) := t1_type(r.x, r.y, (r.x + r.y));
  9  end loop;
 10  return v_t1;
 11  end;
 12  /

Function created.

І, нарешті:

SQL> select * from the (select cast (fn_t1 as t1) from dual)
  2  /

         X          Y          Z
---------- ---------- ----------
         1          2          3
         3          4          7

Як ви бачите, це досить незграбно (і використовує псевдофункції колекції , що є незрозумілою особливістю в найкращі часи!), Як я завжди кажу, перенесення з БД до БД - це не просто синтаксис та ключові слова в їх діалектах SQL реальна складність полягає в різних основоположних припущеннях (у випадку з SQL Server, що курсори дорогі і їх використання уникають / обробляють за будь-яку ціну).


3

Якщо варіант регістру недостатньо гнучкий, ви можете масово збирати дані у вашій процедурі та маніпулювати масивом.

--Setup
CREATE TABLE table_a (c1 Number(2));
CREATE TABLE table_b (c1 Number(2));
INSERT INTO table_a (SELECT rownum FROM dual CONNECT BY rownum<=4);
INSERT INTO table_b (SELECT rownum+5 FROM dual CONNECT BY rownum<=4);

--Example
DECLARE
   Type tNumberArray Is Table Of Number;
   v1 tNumberArray;
BEGIN
   SELECT c1 BULK COLLECT INTO v1 FROM (
      SELECT c1 FROM table_a
      UNION ALL
      SELECT c1 FROM table_b
      );

   For x IN v1.First..v1.Last Loop
      /* Complex manipulation goes here. */
      If (v1(x) <= 3) Then
         v1(x) := v1(x)*10;
      End If;
      DBMS_OUTPUT.PUT_LINE(v1(x));
   End Loop;
END;
/

+1, але це не повертає набір результатів (якщо a SELECT- це останнє, що зберігається в T-SQL Pro, це те, що він повертає)
Gaius

Якщо цей блок коду був перетворений на процедуру, ви можете повернути масив або відкрити масиви як курсор і передати курсор назад, або навіть зробити його функцією і повернути назад рядки. Кожне з них було б схожим, але те, що вам слід використовувати, залежатиме від ситуації.
Лей Ріффер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.