2014-11-12 2 views
0

먼저 내 배경은 SQL Server에 있습니다. CTE (Common Table Expressions) 사용은 매우 간편하며 변수가있는 저장 프로 시저로 변환하는 경우 입력 된 값을 변수 이름으로 바꾸는 것 외에는 SQL의 구조를 변경할 필요가 없습니다.ORACLE : PL/SQL에서 CTE (Common Table Expressions) 사용

그러나 Oracle PL/SQL에서는 완전히 다른 문제입니다. 내 CTE는 일직선 SQL처럼 잘 작동하지만 일단 PL/SQL로 랩핑을 시도하면 여러 가지 문제가 발생합니다. 내 이해에서 SELECT는 이제 단일 레코드의 결과 만 보유 할 INTO가 필요합니다. 그러나 여러 값의 전체 레코드 집합을 원합니다.

여기에 분명한 부분이 누락되면 사과드립니다. 나는 나의 문제의 99 %가 내가해야 할 패러다임 변화라고 생각하고있다.

다음 예제를 감안할 때 :

참고 : 나는 여기에 SQL을 단순화를 통해 크게입니다. 아래 예제는 단일 SQL 문에서 수행 할 수 있다는 것을 알고 있습니다. 실제 SQL은 훨씬 더 복잡합니다. 그것은 내가 여기서 찾고있는 기본 사항입니다.

WITH A as (SELECT * FROM EMPLOYEES WHERE DEPARTMENT = 200), 

B as (SELECT * FROM A WHERE EMPLOYEE_START_DATE > date '2014-02-01'), 

C as (SELECT * FROM B WHERE EMPLOYEE_TYPE = 'SALARY') 

SELECT 'COUNTS' as Total, 
(SELECT COUNT(*) FROM A) as 'DEPT_TOTAL', 
(SELECT COUNT(*) FROM B) as 'NEW_EMPLOYEES', 
(SELECT COUNT(*) FROM C) as 'NEW_SALARIED' 
FROM A 
WHERE rowcount = 1; 

지금 내가 전달 또는 상단에 미리 정의 된 변수를 PL/SQL로이를 만들고 싶어, 그것은 변수를 선언 그들에 값을 보여주고, 내 하드를 변경하는 간단한 문제가 아니다 코드화 된 값을 변수에 저장하고 실행합니다. 참고 : 하드 코딩 된 값을 Department, : StartDate 및 : Type과 같은 변수로 간단히 변경할 수 있음을 알고 있습니다. 그러나 다시 예제를 간소화하고 있습니다.

나는 주위에 내 머리를 정리하려고 내가 여기에 직면하고 세 가지 문제가 있습니다 :

1) 무엇 선언 된 변수이 사용하는 PL/SQL을 재 작성하는 가장 좋은 방법이 있을까요? CTE는 이제 뭔가 들어가야 만합니다. 그러나 그때 나는 전체 표와 반대로 한 번에 한 행을 다루고 있습니다. 따라서 CTE 'A'는 한 번에 하나의 행이며, CTE B는 A 등의 모든 데이터 결과와 반대되는 단일 행만을 볼 것입니다. CURSORS를 통과해야 할 가능성이 가장 높습니다. 어떤 식 으로든 이것을 지나치게 복잡하게 만드는 것처럼 보이는 기록.

2) 이제 출력에 DBMS_OUTPUT을 사용해야합니다. 여러 레코드의 경우 FETCH (또는 FOR ... LOOP)와 함께 CURSOR를 사용해야합니다. 예?

3) 사용 된 속도와 리소스와 관련하여 스트레이트 SQL과 비교하여 큰 성능 문제가 있습니까?

사전에 감사 드리며 다시 사과드립니다. 여기에 정말 분명한 것을 놓치면 사과드립니다!

+0

부디 예 : http://stackoverflow.com/tags/plsql/info에서 Steven Feuerstein의 PL/SQL 101 시리즈 (태그 위키에서 링크를 찾을 수 있습니다)를 읽기 시작하십시오. – user272735

답변

1

먼저 CTE와 관련이 없습니다. 이 동작은 간단한 select * from table 쿼리와 동일합니다. 차이점은 T-SQL의 경우 쿼리가 호출자에게 반환되는 암시 적 커서로 이동한다는 것입니다. Management Studio에서 SP를 실행할 때 편리합니다. 우리가 직접 쿼리를 실행 한 것처럼 결과 집합이 데이터 창에 나타납니다. 그러나 이것은 실제로 비표준 동작입니다. 오라클은 "커서로 전달되지 않는 쿼리의 결과 집합을 변수로 전달해야합니다"라고 표현 될 수있는보다 표준적인 동작을 제공합니다."변수로 지정되면 쿼리는 한 행만 반환해야합니다.

T-SQL의 동작을 복제하려면 커서를 명시 적으로 선언하고 반환하면됩니다. 그런 다음 호출 코드가 전체 결과를 커서에서 가져옵니다 한 번에 하나의 행으로 설정하십시오 .Sql Developer 나 PL/SQL Developer가 데이터 표시 창으로 결과 집합을 전환하는 편리함을 얻지는 못하지만, 모든 것을 가질 수는 없습니다.

그러나 우리는 일반적으로 IDE에서 호출 할 SP를 작성하면 SQL Server의 암시 적 커서보다 오라클의 명시 적 커서를 사용하는 것이 더 쉽습니다. 좋은 재료를 많이 얻으려면 google "oracle return cursor"를 호출하십시오.

1

가장 간단한 방법은 변수를 미리 정의 할 필요없이 루프

begin 
    for i in (select object_id, object_name 
       from user_objects 
       where rownum = 1) loop 
     -- Do something with the resultset 
     dbms_output.put_line (i.object_id || ' ' || i.object_name); 
    end loop; 
end; 

단일 행 쿼리에 대한 암시로 포장하는 것입니다.

+1

@OlafurTryggvason과 같이 Oracle 10 암시 적 FOR 루프로 시작하는 부수적 인 주석은 내부적으로 BULK COLLECT 의미를 자동으로 사용합니다. 따라서 필자의 경험에 따르면 CURSOR 선언을 사용하여 커서를 더 이상 선언 할 필요가 거의 없습니다. 문제의 SELECT가 한 행만 반환한다는 것이 확실하다면 SELECT ... INTO를 사용해야합니다. TSQL과 PL/SQL은 서로 다른 프로그래밍 모델을 사용하는 서로 다른 짐승들입니다. 그러나 그것을 고수하고 사소한 양의 정신적 통증을 느끼면 익숙해집니다 (PL/SQL, 나는 고통을 느끼지 않습니다 :-). 행운을 빌어 요. –

+0

그런 다음 BULK COLLECT 및 FORALL 문을 명시 적으로 사용하지 않는 이유는 무엇입니까? - 혼란을 피하기 위해 게시자가 오라클 버전을 네 자리까지 명시 해 주시기 바랍니다. –

+0

제한적 하위 절과 함께 명시 적 대량 수집 만 사용합니다. –