43.13. 다음에서 이전 중입니다.오라클토토 꽁 머니/SQL

이 섹션에서는 다음과 같은 차이점을 설명합니다.포스트그레SQL's토토 꽁 머니/pgSQL언어와 Oracle의토토 꽁 머니/SQL언어, 애플리케이션을 포팅하는 개발자를 돕기 위해오라클® ~포스트그레SQL.

토토 꽁 머니/pgSQL은 여러 측면에서 토토 꽁 머니/SQL과 유사합니다. 블록 구조의 명령형 언어이므로 모든 변수를 선언해야 합니다. 할당, 루프 및 조건은 유사합니다. 에서 포팅할 때 염두에 두어야 할 주요 차이점토토 꽁 머니/SQL토토 꽁 머니/pgSQL다음은:

  • SQL 명령에 사용된 이름이 명령에 사용된 테이블의 열 이름이거나 함수 변수에 대한 참조일 수 있는 경우,토토 꽁 머니/SQL열 이름으로 취급합니다. 기본적으로,토토 꽁 머니/pgSQL이름이 모호하다는 오류가 발생합니다. 지정할 수 있습니다토토 꽁 머니pgsql.variable_contribute = use_column이 동작을 일치하도록 변경하려면토토 꽁 머니/SQL, 설명된 대로섹션 43.11.1. 처음에 이러한 모호성을 피하는 것이 가장 좋은 경우가 많지만, 이 동작에 의존하는 많은 양의 코드를 이식해야 하는 경우에는 다음을 설정하세요.변수_충돌가장 좋은 해결책이 될 수 있습니다.

  • PostgreSQL함수 본문은 문자열 리터럴로 작성되어야 합니다. 따라서 함수 본문에서 달러 인용을 사용하거나 작은따옴표를 이스케이프 처리해야 합니다. (참조섹션 43.12.1.)

  • 데이터 유형 이름은 종종 번역이 필요합니다. 예를 들어 Oracle에서 문자열 값은 일반적으로 다음 유형으로 선언됩니다.varchar2은 SQL 표준이 아닌 유형입니다. 에서PostgreSQL, 유형 사용varchar또는텍스트대신. 마찬가지로 유형을 교체하세요.번호함께숫자또는 더 적절한 숫자 데이터 유형이 있으면 다른 숫자 데이터 유형을 사용하세요.

  • 패키지 대신 스키마를 사용하여 함수를 그룹으로 구성하세요.

  • 패키지가 없으므로 패키지 수준 변수도 없습니다. 이것은 다소 성가신 일입니다. 대신 임시 테이블에 세션별 상태를 유지할 수 있습니다.

  • 정수for다음으로 루프반전작동 방식이 다릅니다:토토 꽁 머니/SQL두 번째 숫자부터 첫 번째 숫자까지 카운트다운하는 반면토토 꽁 머니/pgSQL첫 번째 숫자에서 두 번째 숫자까지 카운트다운하므로 포팅 시 루프 경계를 교체해야 합니다. 이러한 비호환성은 불행한 일이지만 변경될 가능성은 거의 없습니다. (참조섹션 43.6.5.5.)

  • for쿼리에 대한 루프(커서 제외)도 다르게 작동합니다. 대상 변수는 선언되어야 하지만토토 꽁 머니/SQL항상 암시적으로 선언합니다. 이것의 장점은 루프가 종료된 후에도 변수 값에 계속 액세스할 수 있다는 것입니다.

  • 커서 변수 사용에는 다양한 표기법 차이가 있습니다.

43.13.1. 포팅 예시

예 43.9다음에서 간단한 함수를 이식하는 방법을 보여줍니다.토토 꽁 머니/SQL토토 꽁 머니/pgSQL.

예제 43.9. 다음에서 간단한 함수 포팅하기토토 꽁 머니/SQL토토 꽁 머니/pgSQL

다음은오라클 토토 꽁 머니/SQL기능:

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

이 기능을 살펴보고 다음과 비교하여 차이점을 살펴보겠습니다.토토 꽁 머니/pgSQL:

  • 유형 이름varchar2다음으로 변경되어야 합니다.varchar또는텍스트. 이 섹션의 예에서는 다음을 사용합니다.varchar하지만텍스트17574_17651

  • 반환함수 프로토타입(함수 본문 아님)의 키워드는 다음과 같습니다반환inPostgreSQL. 또한,IS되다AS, 그리고 다음을 추가해야 합니다.언어절 왜냐하면토토 꽁 머니/pgSQL이것이 유일한 함수 언어는 아닙니다.

  • 포스트그레SQL, 함수 본문은 문자열 리터럴로 간주되므로 주위에 따옴표나 달러 따옴표를 사용해야 합니다. 이는 종료를 대체합니다./Oracle 접근 방식에서.

  • 오류 표시명령이 존재하지 않습니다.포스트그레SQL오류가 자동으로 보고되므로 필요하지 않습니다.

이 기능을 다음으로 이식하면 다음과 같습니다.PostgreSQL:

함수 생성 또는 교체 cs_fmt_browser_version(v_name varchar,
                                                  v_version varchar)
varchar를 $$로 반환합니다.
시작
    v_version이 NULL인 경우
        RETURN v_name;
    종료하면;
    RETURN v_name || '/' || v_version;
끝;
$$ 언어 plpgsql;

예 43.10다른 함수를 생성하는 함수를 이식하는 방법과 그에 따른 인용 문제를 처리하는 방법을 보여줍니다.

예제 43.10. 다음에서 다른 함수를 생성하는 함수 포팅토토 꽁 머니/SQL토토 꽁 머니/pgSQL

다음 절차는 a에서 행을 가져옵니다.선택문을 작성하고 그 결과를 사용하여 큰 함수를 빌드합니다.IF문, 효율성을 위해.

이것은 Oracle 버전입니다:

프로시저 생성 또는 교체 cs_update_referrer_type_proc IS
    커서 Referrer_keys IS
        SELECT * cs_referrer_keys에서
        ORDER BY try_order;
    func_cmd VARCHAR(4000);
시작
    func_cmd := '함수 생성 또는 교체 cs_find_referrer_type(v_host IN VARCHAR2,
                 v_domain IN VARCHAR2, v_url IN VARCHAR2) RETURN VARCHAR2 IS BEGIN';

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

    func_cmd := func_cmd || ' NULL을 반환합니다. 끝;';

    즉시 실행 func_cmd;
끝;
/
오류 표시;

이 기능은 다음과 같이 종료됩니다.PostgreSQL:

프로시저 cs_update_referrer_type_proc()를 $func$로 생성 또는 교체
선언
    Referrer_keys 커서는 IS입니다.
        SELECT * cs_referrer_keys에서
        ORDER BY try_order;
    func_body 텍스트;
    func_cmd 텍스트;
시작
    func_body := '시작';

    FOR Referrer_key IN Referrer_keys LOOP
        func_body := func_body ||
          ' IF v_' || Referrer_key.kind
          || '좋아요' || quote_literal(referrer_key.key_string)
          || ' 그런 다음 반환 ' || quote_literal(referrer_key.referrer_type)
          || '; END IF;' ;
    엔드 루프;

    func_body := func_body || ' NULL을 반환합니다. 종료;';

    func_cmd :=
      '함수 생성 또는 교체 cs_find_referrer_type(v_host varchar,
                                                        v_domain varchar,
                                                        v_url varchar)
        varchar AS '를 반환합니다.
      || quote_literal(func_body)
      || ' 언어 plpgsql;' ;

    실행 func_cmd;
끝;
$func$ 언어 plpgsql;

함수 본문이 어떻게 별도로 구축되고 전달되는지 주목quote_literal따옴표 안에 있는 따옴표를 두 배로 늘립니다. 이 기술은 새 함수를 정의하기 위해 달러 인용을 안전하게 사용할 수 없기 때문에 필요합니다. 우리는 어떤 문자열이referrer_key.key_string필드. (여기서는 다음과 같이 가정합니다.referrer_key.kind항상 신뢰할 수 있음호스트, 도메인또는url하지만referrer_key.key_string무엇이든 가능하며 특히 달러 기호가 포함될 수 있습니다.) 이 함수는 실제로 Oracle 원본보다 향상된 기능입니다. 왜냐하면 다음과 같은 경우 깨진 코드를 생성하지 않기 때문입니다.referrer_key.key_string또는referrer_key.referrer_type따옴표가 포함되어 있습니다.


예 43.11함수를 포팅하는 방법을 보여줍니다.아웃매개변수 및 문자열 조작.PostgreSQL내장되어 있지 않습니다.instr함수이지만 다른 함수의 조합을 사용하여 함수를 만들 수 있습니다. 에서섹션 43.13.3이 있습니다토토 꽁 머니/pgSQL구현instr포팅을 더 쉽게 만드는 데 사용할 수 있습니다.

예제 43.11. 문자열 조작을 사용하여 프로시저 포팅 및OUT매개변수:토토 꽁 머니/SQL토토 꽁 머니/pgSQL

다음오라클토토 꽁 머니/SQL 프로시저는 URL을 구문 분석하고 여러 요소(호스트, 경로 및 쿼리)를 반환하는 데 사용됩니다.

이것은 Oracle 버전입니다:

프로시저 생성 또는 교체 cs_parse_url(
    VARCHAR2의 v_url,
    v_host OUT VARCHAR2, -- 이것은 다시 전달됩니다.
    v_path OUT VARCHAR2, -- 이것도 마찬가지입니다.
    v_query OUT VARCHAR2) -- 그리고 이건
IS
    a_pos1 INTEGER;
    a_pos2 INTEGER;
시작
    v_host := NULL;
    v_path := NULL;
    v_query := 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 := '/';
        반품;
    종료하면;

    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);
끝;
/
오류 표시;

다음에 가능한 번역이 있습니다.토토 꽁 머니/pgSQL:

함수 생성 또는 교체 cs_parse_url(
    v_url IN VARCHAR,
    v_host OUT VARCHAR, -- 다시 전달됩니다.
    v_path OUT VARCHAR, -- 이것도 마찬가지입니다.
    v_query OUT VARCHAR) -- 그리고 이건
AS $$
선언
    a_pos1 INTEGER;
    a_pos2 INTEGER;
시작
    v_host := NULL;
    v_path := NULL;
    v_query := 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 := '/';
        반품;
    종료하면;

    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);
끝;
$$ 언어 plpgsql;

이 함수는 다음과 같이 사용될 수 있습니다:

SELECT * FROM cs_parse_url('http://foobar.com/query.cgi?baz');

예 43.12Oracle에 특정한 다양한 기능을 사용하는 프로시저를 이식하는 방법을 보여줍니다.

예제 43.12. 프로시저 포팅토토 꽁 머니/SQL토토 꽁 머니/pgSQL

오라클 버전:

프로시저 생성 또는 교체 cs_create_job(v_job_id IN INTEGER) IS
    a_running_job_count INTEGER;
시작
    독점 모드에서 LOCK TABLE cs_jobs;

    SELECT 개수(*) INTO a_running_job_count FROM cs_jobs WHERE end_stamp가 NULL입니다.

    IF a_running_job_count  0 그러면
        커밋; -- 무료 잠금
        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, now());
    예외
        dup_val_on_index가 NULL일 때; -- 이미 존재하더라도 걱정하지 마세요.
    끝;
    저지르다;
끝;
/
오류 표시

이것이 우리가 이 절차를 다음으로 포팅할 수 있는 방법입니다.토토 꽁 머니/pgSQL:

프로시저 cs_create_job(v_job_id 정수)을 $$로 생성 또는 교체
선언
    a_running_job_count 정수;
시작
    독점 모드에서 LOCK TABLE cs_jobs;

    SELECT 개수(*) INTO a_running_job_count FROM cs_jobs WHERE end_stamp가 NULL입니다.

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

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

    시작
        INSERT INTO cs_jobs(job_id, start_stamp) VALUES(v_job_id, now());
    예외
        고유한 위반이 있을 때 --(2)
            -- 이미 존재하더라도 걱정하지 마세요.
    끝;
    저지르다;
끝;
$$ 언어 plpgsql;

(1)

구문상승기본적인 경우이지만 Oracle의 진술과 상당히 다릅니다상승 예외_이름비슷하게 작동합니다.

(2)

다음에서 지원하는 예외 이름토토 꽁 머니/pgSQL오라클과 다릅니다. 내장된 예외 이름 세트는 훨씬 더 큽니다(참조스포츠 토토 결과 : 문서 : 15 : 부록 A. 스포츠 토토 결과 스포츠 토토 결과 코드). 현재는 사용자 정의 예외 이름을 선언하는 방법이 없지만 대신 사용자가 선택한 SQLSTATE 값을 발생시킬 수 있습니다.


43.13.2. 기타 주의할 사항

이 섹션에서는 Oracle을 포팅할 때 주의해야 할 몇 가지 다른 사항을 설명합니다.토토 꽁 머니/SQL기능포스트그레SQL.

43.13.2.1. 예외 후 암시적 롤백

토토 꽁 머니/pgSQL, 예외가에 의해 포착된 경우예외절, 블록 이후의 모든 데이터베이스 변경시작자동으로 롤백됩니다. 즉, 동작은 다음을 통해 Oracle에서 얻을 수 있는 것과 동일합니다.

시작
    세이브포인트 s1;
    ... 코드는 여기에 ...
예외
    언제 ... 그때
        s1으로 롤백합니다.
        ... 코드는 여기에 ...
    언제 ... 그때
        s1으로 롤백합니다.
        ... 코드는 여기에 ...
끝;

다음을 사용하는 Oracle 프로시저를 번역하는 경우세이브포인트그리고다음으로 롤백이 스타일에서는 작업이 쉽습니다. 그냥 생략하면 됩니다.세이브포인트그리고다음으로 롤백. 다음을 사용하는 프로시저가 있는 경우세이브포인트그리고다음으로 롤백다른 방식으로는 실제적인 생각이 필요할 것입니다.

43.13.2.2. 실행

토토 꽁 머니/pgSQL버전실행다음과 유사하게 작동합니다토토 꽁 머니/SQL버전이지만 사용해야 한다는 점을 기억해야 합니다quote_literal그리고quote_ident설명된 대로섹션 43.5.4. 유형의 구성'SELECT * FROM $1' 실행;이 기능을 사용하지 않으면 안정적으로 작동하지 않습니다.

43.13.2.3. 최적화 중토토 꽁 머니/pgSQL기능

포스트그레SQL실행을 최적화하기 위한 두 가지 함수 생성 수정자를 제공합니다.변동성(동일한 인수가 주어졌을 때 함수가 항상 동일한 결과를 반환하는지 여부) 및엄격함(인수가 null인 경우 함수가 null을 반환하는지 여부). 상담하세요함수 생성자세한 내용은 참조 페이지입니다.

이러한 최적화 속성을 사용할 때 귀하의함수 생성문은 다음과 같을 수 있습니다:

CREATE FUNCTION foo(...) 정수를 $$로 반환합니다.
...
$$ LANGUAGE plpgsql STRICT IMMUTABLE;

43.13.3. 부록

이 섹션에는 Oracle 호환 세트에 대한 코드가 포함되어 있습니다입력포팅 작업을 단순화하는 데 사용할 수 있는 기능입니다.

--
-- Oracle의 대응 기능을 모방한 instr 함수
-- 구문: instr(string1, string2 [, n [, m]])
-- 여기서 []는 선택적 매개변수를 나타냅니다.
--
-- n번째 문자부터 시작하여 string1에서 m번째 문자를 검색합니다.
-- 문자열2의  n이 음수이면 abs(n)번째부터 거꾸로 검색합니다.
-- string1 끝의 문자입니다.
-- n이 전달되지 않으면 1로 가정합니다(첫 번째 문자부터 검색 시작).
-- m이 전달되지 않으면 1로 가정합니다(첫 번째 발생 찾기).
-- string1에서 string2의 시작 인덱스를 반환하거나 string2를 찾을 수 없으면 0을 반환합니다.
--

CREATE FUNCTION instr(varchar, varchar) 정수를 $$로 반환합니다.
시작
    RETURN instr($1, $2, 1);
끝;
$$ LANGUAGE plpgsql 엄격한 불변;

CREATE FUNCTION instr(string varchar, string_to_search_for varchar,
                      beg_index 정수)
$$로 정수를 반환합니다.
선언
    위치 정수 NOT NULL DEFAULT 0;
    temp_str varchar;
    정수를 구걸하다;
    길이 정수;
    ss_length 정수;
시작
    IF beg_index  0 그러면
        temp_str := substring(string FROM beg_index);
        pos := position(string_to_search_for IN temp_str);

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

        구걸하는 동안  0 LOOP
            temp_str := substring(string FROM beg FOR ss_length);
            IF string_to_search_for = temp_str THEN
                반환 구걸;
            종료하면;

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

        0을 반환합니다.
    그 외
        0을 반환합니다.
    종료하면;
끝;
$$ LANGUAGE plpgsql 엄격한 불변;

CREATE FUNCTION instr(string varchar, string_to_search_for varchar,
                      beg_index 정수, 발생_index 정수)
$$로 정수를 반환합니다.
선언
    위치 정수 NOT NULL DEFAULT 0;
    발생_번호 정수 NOT NULL DEFAULT 0;
    temp_str varchar;
    정수를 구걸하다;
    나는 정수;
    길이 정수;
    ss_length 정수;
시작
    IF 발생_지수 <= 0 THEN
        RAISE '인수 ''%''이(가) 범위를 벗어났습니다.', 발생_색인
          ERRCODE 사용 = '22003';
    종료하면;

    IF beg_index  0 그러면
        구걸 := beg_index - 1;
        FOR i IN 1..occur_index LOOP
            temp_str := substring(string FROM beg + 1);
            pos := position(string_to_search_for IN temp_str);
            IF pos = 0이면
                0을 반환합니다.
            종료하면;
            구걸하다 := 구걸하다 + pos;
        엔드 루프;

        반환 구걸;
    ELSIF beg_index < 0 THEN
        ss_length := char_length(string_to_search_for);
        길이 := char_length(string);
        구걸 := 길이 + 1 + 구걸_색인;

        구걸하는 동안  0 LOOP
            temp_str := substring(string FROM beg FOR ss_length);
            IF string_to_search_for = temp_str THEN
                발생_번호 := 발생_번호 + 1;
                IF 발생_번호 = 발생_인덱스 THEN
                    반환 구걸;
                종료하면;
            종료하면;

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

        0을 반환합니다.
    그 외
        0을 반환합니다.
    종료하면;
끝;
$$ LANGUAGE plpgsql STRICT IMMUTABLE;

수정사항 제출

문서에 올바르지 않은 내용이 있으면 일치하지 않습니다. 특정 기능에 대한 경험이 있거나 추가 설명이 필요한 경우 이용해주세요이 양식문서 문제를 보고합니다.