임시 테이블 또는 테이블 변수를 사용하여 SQL Server 저장 프로 시저를 Oracle로 마이그레이션하는 방법


9

경영진이 SQL Server 저장 프로 시저를 작성하도록 권장하는 C # 개발자는 종종 다음과 같은 절차를 생성합니다.

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 글로벌 공통 테이블은 글로벌 오브젝트이며 모두 동일한 테이블 구조를 공유합니다. 이 구조를 수정하는 것은 불가능하지만 어디서나 사용됩니다.

Oracle dba에서 배운 것 중 하나는 가능할 때마다 임시 테이블을 사용하지 않는 것입니다. SQL Server의 성능조차도 그러한 수정의 이점을 얻습니다.

개별 인서트를 유니온으로 교체

가장 간단한 경우, 위의 내용은

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

기능 사용

스칼라 함수와 테이블 반환 함수는 프로 시저를 위의 단일 쿼리로 변환하는 데 도움이 될 수 있습니다.

공통 테이블 표현식 (일명 서브 쿼리 팩토링)

서브 쿼리 팩토링은 임시 테이블을 피하기 위해 오라클이 제공해야하는 최고의 제품입니다. 이를 사용하여 SQL Server를 Oracle로 마이그레이션하는 것이 다시 쉽습니다. 이를 위해서는 SQL Server 2005 이상이 필요합니다.


이러한 수정 사항으로 인해 SQL Server 버전이 개선되고 많은 경우 마이그레이션이 간단 해집니다. 다른 경우에는 글로벌 임시 테이블에 의지하여 제한된 시간 내에 마이그레이션을 수행 할 수 있지만 만족스럽지 않습니다.


Oracle에서 전역 임시 테이블을 사용하지 않는 다른 방법이 있습니까?


3
그런 코드는 절차 적 기반이 아닌 사고 방식을 나타냅니다. 그리고 이들은 단일 #을 가진 로컬 임시 테이블입니다. 나는 관리이고 나는 생산에 들어가는 것을 보았을 때 다리를 깰 것이다 :-)
gbn

완전히 동의합니다
bernd_k

@gbn-관용적 인 PL / SQL은 관용적 인 T-SQL보다 조금 더 절차적인 경향이 있습니다. 임시 테이블을 사용하면 T-SQL의 set op에서 거의 모든 작업을 수행 할 수 있습니다. 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

보시다시피 , 이것은 항상 매우 말끔하고 (그리고 가장 잘 모호한 기능인 수집 의사 함수를 사용합니다 !) DB에서 DB로 포팅하는 것은 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 저장 프로 시저에서 마지막 항목 인 경우 반환
Gaius

이 코드 블록이 프로 시저로 바뀌면 배열을 리턴하거나 배열을 커서로 열고 커서를 다시 전달하거나 함수로 만들고 행을 다시 파이프 할 수 있습니다. 이들 각각은 비슷하지만 상황에 따라 사용해야합니다.
레이 리펠
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.