이 문서는 지원되지 않는 PostgreSQL 버전에 대한 것입니다.
당신은 다음과 같은 페이지를 보고 싶을 수도 있습니다.PostgreSQL : 문서 : 17 : 41.13. Oracle 토토 사이트/SQL에서 포팅버전 또는 위에 나열된 다른 지원 버전 중 하나를 사용하세요.

19.11. Oracle에서 포팅 PL/SQL

저자:로베르토 멜로 ()

이 섹션에서는 오라클의 PL/SQL과 Oracle의 PL/SQL 간의 차이점을 설명합니다.포스트그레SQL's토토 핫/pgSQL도움을 희망하는 언어 개발자는 Oracle에서 다음으로 애플리케이션을 포팅합니다.PostgreSQL. 여기에 있는 대부분의 코드는ArsDigita 클릭스트림 모듈내가 포팅한 곳포스트그레SQL인턴십을 할 때오픈포스 주식회사2000년 여름.

토토 핫/pgSQLPL/SQL과 유사합니다. 여러 측면에서. 블록 구조의 명령형 언어입니다. (모든 변수는 선언되어야 함) PL/SQL에는 더 많은 기능이 있습니다 그것보다 기능은포스트그레SQL반대이지만토토 핫/pgSQL허용 많은 기능이 추가되었으며 개선되고 있습니다. 끊임없이.

19.11.1. 주요 차이점

Oracle에서 포팅할 때 명심해야 할 몇 가지 사항 에포스트그레SQL:

  • 기본 매개변수 없음포스트그레SQL.

  • 함수를 오버로드할 수 있습니다.PostgreSQL. 이것은 종종 작업에 사용됩니다. 기본 매개변수가 부족합니다.

  • 할당, 루프 및 조건은 유사합니다.

  • 커서가 필요하지 않습니다.PostgreSQL, 쿼리를 FOR 문(아래 예 참조)

  • 포스트그레SQL당신필요탈출하다 작은따옴표. 참조섹션 19.11.1.1.

19.11.1.1. 그에 대한 인용문: 싱글 탈출 인용문

PostgreSQL당신은 다음을 수행해야 합니다 함수 정의 내에서 작은따옴표를 이스케이프 처리하세요. 이 때때로 꽤 재미있는 코드가 나올 수 있습니다. 특히 다음과 같은 경우에는 더욱 그렇습니다. 다음과 같이 다른 함수를 생성하는 함수를 만들고 있습니다. 에서예 19-6. 많은 것을 피할 때 명심해야 할 한 가지 작은따옴표는 시작/끝을 제외한 것입니다. 다른 모든 제품은 짝수 수량으로 제공됩니다.

테이블 19-1특종을 제공합니다. (너는 이 작은 것을 좋아할 것이다. 차트.)

표 19-1. 작은따옴표 이스케이프 차트

아니요. 인용문 사용법 결과
1 함수 본문을 시작/종료하려면
함수 생성 foo()는 정수를 '...'로 반환합니다.
언어 '토토 핫pgsql';
그대로
2 할당에서 SELECT 문으로 구분 문자열 등
a_output := ''어쩌고'';
SELECT * FROM 사용자 WHERE f_name=''foobar'';
SELECT * 어디에서 사용자로부터 선택 f_name='foobar';
4 결과에 두 개의 작은따옴표가 필요한 경우 해당 문자열을 종료하지 않고 문자열을 삭제합니다.
a_output := a_output || '' AND 이름 
    LIKE ''''foobar'''' AND ...''
그리고 'foobar' 같은 이름 AND ...
6 결과에 큰따옴표를 원하는 경우 문자열그리고해당 문자열을 종료합니다.
a_output := a_output || '' AND 이름 
    LIKE ''''foobar''''''
및 이름 LIKE '푸바'
10 결과에 두 개의 작은따옴표를 원하는 경우 문자열(8개의 따옴표를 설명함)그리고종료하세요 문자열(2개 이상). 아마도 다음과 같은 경우에만 필요할 것입니다. 다른 함수를 생성하기 위해 함수를 사용하고 있었습니다. (처럼예 19-6).
a_output := a_output || '' v_''인 경우 || 
    Referrer_keys.kind || ''처럼 '''''''''' 
    || Referrer_keys.key_string || '''''''''' 
    그런 다음 ''''''를 반환합니다 || Referrer_keys.referrer_type 
    || ''''''; 다음 경우 종료;'';
if v_<... 좋아요 ''<...'' 그런 다음 ''<...''를 반환합니다. 끝 만약;

19.11.2. 포팅 기능

예제 19-5. 간단한 기능

다음은 Oracle 함수입니다:

함수 생성 또는 교체 cs_fmt_browser_version(v_name IN varchar, v_version IN varchar)
반환 varchar IS
시작
    v_version이 NULL인 경우
        RETURN v_name;
    종료하면;
    RETURN v_name || '/' || v_version;
끝;
/
오류 표시;

이 기능을 살펴보고 차이점을 살펴보겠습니다.토토 핫/pgSQL:

  • 포스트그레SQL하지 않습니다 명명된 매개변수가 있습니다. 명시적으로 별칭을 지정해야 합니다. 함수 내부에 있습니다.

  • 오라클은 할 수 있습니다IN, 아웃INOUT매개변수가 함수에 전달되었습니다.INOUT18599_18702PostgreSQL만 있음"IN"매개변수 및 함수 단일 값만 반환할 수 있습니다.

  • 반환키워드 함수 프로토타입(함수 본문 아님)은 다음과 같습니다.반환in포스트그레SQL.

  • 켜짐PostgreSQL함수는 작은따옴표를 구분 기호로 사용하여 생성됩니다. 따라서 함수 내에서 작은따옴표를 이스케이프 처리해야 합니다. (때때로 상당히 짜증날 수 있습니다. 참조섹션 19.11.1.1).

  • /오류 표시명령은 다음과 같습니다 에는 존재하지 않습니다.PostgreSQL.

이 함수가 다음으로 이식되었을 때 어떻게 보이는지 봅시다PostgreSQL:

함수 생성 또는 교체 cs_fmt_browser_version(VARCHAR, VARCHAR)
VARCHAR를 '로 반환합니다.
선언
    $1에 대한 v_name 별칭;
    $2에 대한 v_version 별칭;
시작
    v_version이 NULL인 경우
        v_name을 반환합니다.
    종료하면;
    RETURN v_name || ''/'' || v_version;
끝;
' 언어 'plpgsql';

예제 19-6. 또 다른 것을 생성하는 함수 기능

다음 절차는 a에서 행을 가져옵니다.선택문을 작성하고 큰 함수를 빌드합니다. 결과는 다음과 같습니다.IF문장, 효율성을 위해서. 특히 주목하세요. 커서의 차이점,for루프, 그리고 작은 따옴표를 이스케이프 처리해야 할 필요성포스트그레SQL.

프로시저 생성 또는 교체 cs_update_referrer_type_proc IS
    커서 Referrer_keys IS 
        SELECT * cs_referrer_keys에서 
        ORDER BY try_order;

    a_output VARCHAR(4000); 
시작 
    a_output := '함수 생성 또는 교체 cs_find_referrer_type(v_host IN VARCHAR, v_domain IN VARCHAR, 
v_url IN VARCHAR) RETURN VARCHAR IS BEGIN'; 

    FOR Referrer_key IN Referrer_keys LOOP 
        a_output := a_output || ' IF v_' || Referrer_key.kind || '좋아요''' || 
Referrer_key.key_string || ''' 그런 다음 '''를 반환합니다 || referrer_key.referrer_type || 
'''; 종료 IF;'; 
    엔드 루프; 

    a_output := a_output || ' NULL을 반환합니다. 끝;'; 
    즉시 실행 a_output; 
끝; 
/ 
오류 표시

이 함수는 다음과 같이 종료됩니다.PostgreSQL:

함수 생성 cs_update_referrer_type_proc()는 정수를 '로 반환합니다.
선언
    Referrer_keys 기록;  -- FOR에 사용할 일반 레코드를 선언합니다.
    a_output varchar(4000);
시작 
    a_output := ''CREATE 함수 cs_find_referrer_type(VARCHAR,VARCHAR,VARCHAR) 
                  VARCHAR를 ''''로 반환합니다. 
                     선언 
                         $1에 대한 v_host 별칭; 
                         $2에 대한 v_domain 별칭; 
                         $3에 대한 v_url 별칭;
                     시작하다 ''; 

    -- 
    -- FOR 루프에서 쿼리 결과를 검색하는 방법에 주목하세요.
    -- FOR <record 구문을 사용합니다.
    --

    FOR Referrer_keys IN SELECT * FROM cs_referrer_keys ORDER BY try_order LOOP
        a_output := a_output || '' IF v_'' || Referrer_keys.kind || ''좋아요'''''''''' 
                 || Referrer_keys.key_string || '''''''''' 그런 다음 ''''''를 반환합니다. 
                 || referrer_keys.referrer_type || ''''''; 종료 IF;''; 
    엔드 루프; 

    a_output := a_output || '' NULL을 반환합니다. 끝; '''' 언어 ''''plpgsql'''';''; 

    -- 변수를 대체하지 않기 때문에 작동합니다.
    -- 그렇지 않으면 실패할 것입니다. 함수를 실행하는 다른 방법은 PERFORM을 참조하세요.

    a_output을 실행합니다. 
끝; 
' 언어 'plpgsql';

예 19-7. 문자열이 많은 프로시저 조작 및 OUT 매개변수

다음 Oracle PL/SQL 절차는 URL을 지정하고 여러 요소(호스트, 경로 및 쿼리)를 반환합니다. 그것은 절차가 있기 때문에토토 핫/pgSQL함수에는 하나의 값만 포함될 수 있습니다. 반환됨(참조섹션 19.11.3). 에서PostgreSQL, 이 문제를 해결하는 한 가지 방법은 절차를 여러 부분으로 분할하는 것입니다. 세 가지 다른 기능: 하나는 호스트를 반환하고 다른 하나는 경로에 대한 것이고 다른 하나는 쿼리에 대한 것입니다.

프로시저 생성 또는 교체 cs_parse_url(
    v_url IN VARCHAR,
    v_host OUT VARCHAR, -- 다시 전달됩니다.
    v_path OUT VARCHAR, -- 이것도 마찬가지입니다.
    v_query OUT VARCHAR) -- 그리고 이건
이다
    a_pos1 INTEGER;
    a_pos2 INTEGER;
시작하다
    v_host := NULL;
    v_path := NULL;
    v_query := NULL;
    a_pos1 := instr(v_url, '//'); --PostgreSQLinstr 함수가 없습니다.

    만약 a_pos1 = 0이면
        반환;
    종료하면;
    a_pos2 := instr(v_url, '/', a_pos1 + 2);
    만약 a_pos2 = 0이면
        v_host := substr(v_url, a_pos1 + 2);
        v_path := '/';
        반품;
    종료하면;

    v_host := substr(v_url, a_pos1 + 2, a_pos2 - a_pos1 - 2);
    a_pos1 := instr(v_url, '?', a_pos2 + 1);

    만약 a_pos1 = 0이면
        v_path := substr(v_url, a_pos2);
        반품;
    종료하면;

    v_path := substr(v_url, a_pos2, a_pos1 - a_pos2);
    v_query := substr(v_url, a_pos1 + 1);
끝;
/
오류 표시;

이 절차를 번역하는 방법은 다음과 같습니다.포스트그레SQL:

함수 생성 또는 교체 cs_parse_url_host(VARCHAR)는 VARCHAR를 '로 반환합니다. 
선언 
    $1에 대한 v_url 별칭; 
    v_host VARCHAR; 
    v_path VARCHAR; 
    a_pos1 INTEGER; 
    a_pos2 INTEGER; 
    a_pos3 INTEGER; 
시작 
    v_host := NULL; 
    a_pos1 := instr(v_url,''//''); 

    만약 a_pos1 = 0이면 
        반환 '''';  -- 공백을 반환합니다.
    종료하면; 

    a_pos2 := instr(v_url,''/'',a_pos1 + 2); 
    만약 a_pos2 = 0이면 
        v_host := substr(v_url, a_pos1 + 2); 
        v_path := ''/''; 
        RETURN v_host; 
    종료하면; 

    v_host := substr(v_url, a_pos1 + 2, a_pos2 - a_pos1 - 2 ); 
    RETURN v_host; 
끝; 
' 언어 'plpgsql';

참고: 포스트그레SQL다음이 없습니다instr함수이므로 다음 조합을 사용하여 문제를 해결할 수 있습니다. 다른 기능. 나는 이 일에 지쳐서 내 것을 만들었습니다. 소유instr기능은 Oracle과 똑같이 행동합니다(삶이 더 편해집니다). 참조섹션 19.11.6코드용.

19.11.3. 절차

Oracle 절차는 다음 작업에 좀 더 많은 유연성을 제공합니다. 개발자는 명시적으로 반환할 필요가 없지만 그것은 다음을 사용하여 가능합니다.INOUT또는아웃매개변수.

예:

프로시저 생성 또는 교체 cs_create_job(v_job_id IN INTEGER) IS
    a_running_job_count INTEGER;
    PRAGMA AUTONOMOUS_TRANSACTION;(1)시작
    독점 모드에서 LOCK TABLE cs_jobs;(2)선택 개수(*) INTO a_running_job_count 
    cs_jobs에서
    end_stamp가 NULL인 경우;

    IF a_running_job_count  0 그러면
        커밋; -- 자유 잠금(3)raise_application_error(-20000, '새 작업을 생성할 수 없습니다: 작업이 현재 실행 중입니다.');
    종료하면;

    cs_active_job에서 삭제;
    cs_active_job(job_id) 값(v_job_id)에 삽입;

    시작
        INSERT INTO cs_jobs(job_id, start_stamp) VALUES(v_job_id, sysdate);
        dup_val_on_index가 NULL인 경우 예외; -- 이미 존재하더라도 걱정하지 마세요.(4)END;
    저지르다;
끝;
/
오류 표시

이러한 절차는 다음으로 쉽게 변환될 수 있습니다.PostgreSQL함수 반환 anINTEGER. 이 절차는 특히 우리에게 몇 가지를 가르쳐 줄 수 있기 때문에 흥미롭습니다.

(1)
아무것도 없습니다프라그마성명 에서포스트그레SQL.
(2)
당신이 다음을 수행한다면락 테이블in토토 핫/pgSQL, 자물쇠는 호출 트랜잭션이 완료될 때까지 해제되지 않음 끝났습니다.
(3)
또한 거래를 할 수 없습니다토토 핫/pgSQL프로시저. 전체 함수(및 거기에서 호출되는 다른 함수)는 다음과 같습니다. 트랜잭션에서 실행되며PostgreSQL다음의 경우 결과를 롤백합니다. 뭔가 잘못되었습니다. 그러므로 하나만시작문이 허용됩니다.
(4)
다음으로 대체되어야 하는 예외는IF성명.

이 절차를 다음으로 포팅할 수 있는 방법 중 하나를 살펴보겠습니다.토토 핫/pgSQL:

함수 생성 또는 교체 cs_create_job(INTEGER)은 정수를 '로 반환합니다.
선언
    $1에 대한 v_job_id 별칭;
    a_running_job_count INTEGER;
    a_num INTEGER;
    -- PRAGMA AUTONOMOUS_TRANSACTION;
시작
    독점 모드에서 LOCK TABLE cs_jobs;
    SELECT 개수(*) INTO a_running_job_count 
    cs_jobs에서 
    end_stamp가 NULL인 경우;

    IF a_running_job_count  0
    그런 다음
        -- 커밋; -- 무료 잠금
        RAISE EXCEPTION ''새 작업을 생성할 수 없습니다. 작업이 현재 실행 중입니다.'';
    종료하면;

    cs_active_job에서 삭제;
    cs_active_job(job_id) 값(v_job_id)에 삽입;

    SELECT count(*)를 a_num으로 
    cs_jobs에서 
    어디서 job_id=v_job_id;
    IF NOT FOUND THEN -- 마지막 쿼리에서 아무것도 반환되지 않은 경우
        -- 이 작업은 테이블에 없으므로 삽입해 보겠습니다.
        INSERT INTO cs_jobs(job_id, start_stamp) VALUES (v_job_id, sysdate());
        1을 반환합니다.
    그 외
        RAISE NOTICE ''작업이 이미 실행 중입니다.'';(1)END IF;

    0을 반환합니다.
끝;
' 언어 'plpgsql';
(1)
알림(또는 오류)을 어떻게 제기할 수 있는지 알아보세요.토토 핫/pgSQL.

19.11.4. 패키지

참고:나는 패키지에 대해 많은 일을 하지 않았습니다. 그러니 여기에 실수가 있으면 알려주세요.

패키지는 Oracle이 PL/SQL을 캡슐화하기 위해 제공하는 방법입니다. 명령문과 함수를 Java 클래스와 같은 하나의 엔터티로 통합합니다. 메소드와 객체를 정의하는 곳입니다. 당신은 이것들에 접근할 수 있습니다 a가 있는 객체/메서드"."(점). 다음은 오라클의 예입니다. ACS 4의 패키지(ArsDigita 커뮤니티 시스템):

패키지 본문 acs 생성 또는 교체
그대로
  기능 add_user(
    user_id IN users.user_id%TYPE DEFAULT NULL,
    object_type IN acs_objects.object_type%TYPE DEFAULT '사용자',
    Creation_date IN acs_objects.creation_date%TYPE DEFAULT sysdate,
    Creation_user IN acs_objects.creation_user%TYPE DEFAULT NULL,
    Creation_ip IN acs_objects.creation_ip%TYPE DEFAULT NULL,
  ...
  ) 반환 users.user_id%TYPE
  IS
    v_user_id users.user_id%TYPE;
    v_rel_id 멤버십_rels.rel_id%TYPE;
  시작
    v_user_id := acs_user.new (user_id, object_type, 생성_날짜,
                생성_사용자, 생성_ip, 이메일, ...
    RETURN v_user_id;
  끝;
종료 AC;
/
오류 표시

우리는 이것을 다음으로 포팅합니다.포스트그레SQLOracle 패키지의 다른 개체를 다음과 같이 생성하여 표준 명명 규칙을 사용하여 기능합니다. 우리는 지불해야 채무불이행 부족과 같은 기타 세부사항에 주의 매개변수PostgreSQL함수. 위의 패키지는 다음과 같습니다. 이:

함수 생성 acs__add_user(INTEGER,INTEGER,VARCHAR,TIMESTAMP,INTEGER,INTEGER,...)
정수를 '로 반환합니다.
선언
    $1에 대한 user_id 별칭;
    $2에 대한 object_type 별칭;
    $3에 대한 생성_날짜 별칭;
    $4에 대한 Creation_user 별칭;
    $5에 대한 Creation_ip 별칭;
    ...
    v_user_id users.user_id%TYPE;
    v_rel_id 멤버십_rels.rel_id%TYPE;
시작
    v_user_id := acs_user__new(user_id,object_type,creation_date,creation_user,creation_ip, ...);
    ...

    RETURN v_user_id;
끝;
' 언어 'plpgsql';

19.11.5. 기타 볼만한 사항 에 대한

19.11.5.1. 실행

PostgreSQL버전실행잘 작동하지만 사용하는 것을 기억하기 위해quote_literal(TEXT)그리고quote_string(TEXT)설명된 대로섹션 19.5.4. 유형의 구성''SELECT * from $1'' 실행;작동하지 않습니다 이 기능을 사용하지 않는 한.

19.11.5.2. 최적화 중토토 핫/pgSQL기능

PostgreSQL두 개를 줍니다 실행을 최적화하기 위한 함수 생성 수정자:캐시 가능(함수는 항상 같은 값을 반환합니다. 동일한 인수가 주어지면 결과) 및엄격함(있는 경우 함수는 NULL을 반환합니다. 인수가 NULL입니다). 상담하세요만들기 기능자세한 내용은 참조하세요.

이러한 최적화 속성을 사용하려면 다음을 수행해야 합니다. 사용하다함께당신의 수식어함수 생성문장. 뭔가 좋아요:

함수 생성 foo(...)는 정수를 '로 반환합니다.
...
' 언어 'plpgsql'
WITH(제한적, 캐시 가능);

19.11.6. 부록

19.11.6.1. 내 코드instr함수

--
-- Oracle의 대응 기능을 모방한 instr 함수
-- 구문: instr(string1,string2,[n],[m]) 여기서 []는 선택적 매개변수를 나타냅니다.
-- 
-- n번째 문자부터 시작하는 string1에서 m번째 문자를 검색합니다.
-- string2의 발생. n이 음수이면 뒤로 검색합니다. 만약 m이
-- 전달되지 않았습니다. 1로 가정합니다(검색은 첫 번째 문자부터 시작됩니다).
--
-- 로베르토 멜로(rmello@fslc.usu.edu)
-- Robert Gaszewski 수정 (graszew@poland.com)
-- GPL v2 이상에 따라 라이센스가 부여됩니다.
--

CREATE FUNCTION instr(VARCHAR,VARCHAR)은 INTEGER를 '로 반환합니다.
선언
    위치 정수;
시작
    pos:= instr($1,$2,1);
    반환 위치;
끝;
' 언어 'plpgsql';

CREATE FUNCTION instr(VARCHAR,VARCHAR,INTEGER)는 INTEGER를 '로 반환합니다.
선언
    $1에 대한 문자열 별칭;
    string_to_search $2에 대한 별칭;
    $3에 대한 beg_index 별칭;
    위치 정수 NOT NULL DEFAULT 0;
    temp_str VARCHAR;
    INTEGER에게 구걸하세요;
    길이 INTEGER;
    ss_length INTEGER;
시작
    IF beg_index  0 그러면

       temp_str := substring(string FROM beg_index);
       pos := position(string_to_search IN temp_str);

       IF pos = 0이면
                 0을 반환합니다.
             그 외
                 RETURN pos + beg_index - 1;
             종료하면;
    그 외
       ss_length := char_length(string_to_search);
       길이 := char_length(string);
       구걸 := 길이 + 구걸_색인 - ss_length + 2;

       구걸하는 동안  0 LOOP
           temp_str := substring(string FROM beg FOR ss_length);
                 pos := position(string_to_search IN temp_str);

                 IF 위치  0 THEN
                           반환 구걸;
                 종료하면;

                 구걸하다 := 구걸하다 - 1;
       엔드 루프;
       0을 반환합니다.
    종료하면;
끝;
' 언어 'plpgsql';

--
-- Robert Gaszewski 작성(graszew@poland.com)
-- GPL v2 이상에 따라 라이센스가 부여됩니다.
--
CREATE FUNCTION instr(VARCHAR,VARCHAR,INTEGER,INTEGER)는 INTEGER를 '로 반환합니다.
선언
    $1에 대한 문자열 별칭;
    string_to_search $2에 대한 별칭;
    $3에 대한 beg_index 별칭;
    $4에 대한 발생_색인 별칭;
    위치 정수 NOT NULL DEFAULT 0;
    발생_번호 INTEGER NOT NULL DEFAULT 0;
    temp_str VARCHAR;
    INTEGER에게 구걸하세요;
    나는 정수;
    길이 INTEGER;
    ss_length INTEGER;
시작
    IF beg_index  0 그러면
        구걸 := 구걸_index;
        temp_str := substring(string FROM beg_index);

        FOR i IN 1..occur_index LOOP
            pos := position(string_to_search IN temp_str);

            I = 1이면
                구걸 := 구걸 + pos - 1;
            그 외
                구걸하다 := 구걸하다 + pos;
            종료하면;

            temp_str := substring(string FROM beg + 1);
        엔드 루프;

        IF pos = 0이면
            0을 반환합니다.
        그 외
            반환 구걸;
        종료하면;
    그 외
        ss_length := char_length(string_to_search);
        길이 := char_length(string);
        구걸 := 길이 + 구걸_색인 - ss_length + 2;

        구걸하는 동안  0 LOOP
            temp_str := substring(string FROM beg FOR ss_length);
            pos := position(string_to_search IN temp_str);

            IF 위치  0 THEN
                발생_번호 := 발생_번호 + 1;

                IF 발생_번호 = 발생_인덱스 THEN
                    반환 구걸;
                종료하면;
            종료하면;

            구걸하다 := 구걸하다 - 1;
        엔드 루프;

        0을 반환합니다.
    종료하면;
끝;
' 언어 'plpgsql';