이 섹션에서는 다음과 같은 차이점을 설명합니다.포스트그레SQL의토토 핫/pgSQL언어와 오라클의PL/SQL언어, 포팅하는 개발자를 돕기 위해 의 지원서오라클® ~포스트그레SQL.
토토 핫/pgSQLPL/SQL과 유사합니다. 여러 측면에서. 블록 구조의 명령형 언어입니다. 그리고 모든 변수는 선언되어야 합니다. 할당, 루프, 조건문도 비슷합니다. 유지해야 할 주요 차이점 이동할 때 주의하세요.PL/SQL에토토 핫/pgSQL다음은:
다음에는 매개변수에 대한 기본값이 없습니다.PostgreSQL.
함수 이름을 오버로드할 수 있습니다.포스트그레SQL. 이것은 종종 작업에 사용됩니다. 기본 매개변수가 부족합니다.
SQL 명령에 사용된 이름이 열일 수 있는 경우 테이블 이름 또는 함수 변수에 대한 참조,PL/SQL열로 취급합니다. 이름, 동안토토 핫/pgSQL대접하다 변수 이름으로 사용하세요. 그런 모호함을 피하는 것이 가장 좋습니다. 첫 번째로, 필요한 경우 다음 방법으로 수정할 수 있습니다. 모호한 이름을 적절하게 한정합니다. (참조섹션 38.10.1.)
커서가 필요하지 않습니다.토토 핫/pgSQL, 쿼리를에 입력하세요.for성명. (참조예 38-6.)
에포스트그레SQL함수 본문은 문자열 리터럴로 작성되어야 합니다. 그러므로 달러 인용을 사용하거나 작은따옴표를 이스케이프 처리해야 합니다. 기능 본체. (참조섹션 38.11.1.)
패키지 대신에 스키마를 사용하여 그룹으로 기능합니다.
패키지가 없으므로 패키지 수준이 없습니다. 변수든. 이것은 다소 성가신 일입니다. 당신은 유지할 수 있습니다 대신 임시 테이블의 세션별 상태입니다.
정수for다음으로 루프반전작동 방식이 다릅니다:PL/SQL두 번째부터 카운트다운됩니다. 처음부터 번호를 매기고, 반면토토 핫/pgSQL처음부터 카운트다운됩니다. 숫자를 초 단위로 변환해야 하며 루프 경계를 교체해야 합니다. 이식할 때. 이러한 비호환성은 불행한 일이지만 변경될 가능성이 없습니다. (참조섹션 38.6.3.5.)
예 38-5다음에서 간단한 함수를 이식하는 방법을 보여줍니다.PL/SQL에토토 핫/pgSQL.
예 38-5. 다음에서 간단한 함수 포팅하기PL/SQL에토토 핫/pgSQL
여기에 있습니다오라클 PL/SQL기능:
함수 생성 또는 교체 cs_fmt_browser_version(v_name varchar,
v_version varchar)
반환 varchar IS
시작
v_version이 NULL인 경우
RETURN v_name;
종료하면;
RETURN v_name || '/' || v_version;
끝;
/
오류 표시;
이 기능을 살펴보고 차이점을 살펴보겠습니다. 비교토토 핫/pgSQL:
그반환키워드 함수 프로토타입(함수 본문 아님)은 다음과 같습니다.반환inPostgreSQL. 또한,IS되다AS, 그리고 다음을 추가해야 합니다.언어절 왜냐하면토토 핫/pgSQL이것이 유일한 함수 언어는 아닙니다.
에포스트그레SQL, 함수 본문은 문자열 리터럴로 간주되므로 주위에 따옴표나 달러 따옴표를 사용해야 합니다. 이는 종료를 대체합니다./Oracle 접근 방식에서.
그오류 표시명령은 다음과 같습니다 에는 존재하지 않습니다.PostgreSQL, 오류가 보고되므로 필요하지 않습니다. 자동으로.
이 기능을 다음으로 이식하면 다음과 같습니다.PostgreSQL:
함수 생성 또는 교체 cs_fmt_browser_version(v_name varchar,
v_version varchar)
varchar를 $$로 반환합니다.
시작
v_version이 NULL인 경우
RETURN v_name;
종료하면;
RETURN v_name || '/' || v_version;
끝;
$$ 언어 plpgsql;
예 38-6다른 함수를 생성하는 함수를 이식하는 방법을 보여줍니다. 함수 및 그에 따른 인용 문제를 처리하는 방법을 설명합니다.
예 38-6. 생성하는 함수 포팅 다른 기능PL/SQL에토토 핫/pgSQL
다음 절차는 a에서 행을 가져옵니다.선택문을 작성하고 큰 함수를 빌드합니다. 결과는 다음과 같습니다.IF문장, 효율성을 위해서. 특히 주목하세요. 커서와의 차이점for루프.
이것은 오라클 버전입니다:
프로시저 생성 또는 교체 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 VARCHAR,
v_domain IN VARCHAR, v_url IN VARCHAR) RETURN VARCHAR 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;
끝;
/
오류 표시;
이 함수의 결과는 다음과 같습니다포스트그레SQL:
함수 생성 또는 교체 cs_update_referrer_type_proc()는 $func$로 void를 반환합니다.
선언
Referrer_key RECORD; -- FOR에서 사용할 일반 레코드를 선언합니다.
func_body 텍스트;
func_cmd 텍스트;
시작
func_body := '시작';
-- FOR 루프에서 쿼리 결과를 검색하는 방법에 주목하세요.
-- FOR <record 구문을 사용합니다.
FOR Referrer_key IN SELECT * FROM cs_referrer_keys ORDER BY try_order 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인용문 포함 마크.
예
38-7함수를 포팅하는 방법을 보여줍니다.아웃매개변수 및 문자열 조작.포스트그레SQL이 없습니다
내장instr기능이 있지만 당신은
다른 기능을 조합하여 만들 수 있습니다.에섹션
38.12.3이 있습니다토토 핫/pgSQL구현instr포팅에 사용할 수 있는 것
더 쉬워요.
예 38-7. 문자열을 사용하여 프로시저 이식하기 조작과아웃매개변수:PL/SQL에토토 핫/pgSQL
다음오라클PL/SQL 프로시저는 URL을 구문 분석하고 여러 가지를 반환하는 데 사용됩니다. 요소(호스트, 경로 및 쿼리).
이것은 Oracle 버전입니다:
프로시저 생성 또는 교체 cs_parse_url(
v_url IN VARCHAR,
v_host OUT VARCHAR, -- 다시 전달됩니다.
v_path OUT VARCHAR, -- 이것도 마찬가지입니다.
v_query OUT VARCHAR) -- 그리고 이건
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');
예 38-8여러 가지를 사용하는 프로시저를 포팅하는 방법을 보여줍니다. Oracle에만 해당되는 기능입니다.
예 38-8. 프로시저 포팅PL/SQL에토토 핫/pgSQL
오라클 버전:
프로시저 생성 또는 교체 cs_create_job(v_job_id IN INTEGER) IS
a_running_job_count INTEGER;
PRAGMA AUTONOMOUS_TRANSACTION;(1)시작
독점 모드에서 LOCK TABLE cs_jobs;(2)end_stamp가 NULL인 cs_jobs에서 a_running_job_count INTO 개수(*) 선택;
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일 때; -- 이미 존재하더라도 걱정하지 마세요.
끝;
저지르다;
끝;
/
오류 표시
이러한 절차는 다음으로 쉽게 변환될 수 있습니다.PostgreSQL함수 돌아오는 중공허. 이 절차는 특히 흥미로운 점은 우리에게 몇 가지를 가르쳐 줄 수 있기 때문입니다. 것들:
이 절차를 다음으로 포팅할 수 있는 방법은 다음과 같습니다.토토 핫/pgSQL:
함수 생성 또는 교체 cs_create_job(v_job_id 정수) $$로 void를 반환합니다.
선언
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 EXEPTION '새 작업을 생성할 수 없습니다. 작업이 현재 실행 중입니다.';(1)END IF;
cs_active_job에서 삭제;
cs_active_job(job_id) 값(v_job_id)에 삽입;
시작
INSERT INTO cs_jobs(job_id, start_stamp) VALUES(v_job_id, now());
예외
WHEN 고유_위반 THEN(2)-- 이미 존재하더라도 걱정하지 마세요.
끝;
끝;
$$ 언어 plpgsql;
이 섹션에서는 다음과 같은 경우에 주의해야 할 몇 가지 다른 사항을 설명합니다. 오라클 포팅PL/SQL기능포스트그레SQL.
에토토 핫/pgSQL, 때 예외는에 의해 포착됩니다.예외절, 블록 이후의 모든 데이터베이스 변경시작자동으로 롤백됩니다. 즉, 동작은 Oracle에서 얻을 수 있는 것과 동일합니다. 와 함께:
시작
세이브포인트 s1;
... 코드는 여기에 ...
예외
언제 ... 그때
s1으로 롤백합니다.
... 코드는 여기에 ...
언제 ... 그때
s1으로 롤백합니다.
... 코드는 여기에 ...
끝;
다음을 사용하는 Oracle 프로시저를 번역하는 경우세이브포인트그리고다음으로 롤백이 스타일에서는 작업이 쉽습니다. 그냥 생략하세요세이브포인트그리고다음으로 롤백. 절차가 있는 경우 을 사용하는세이브포인트그리고다음으로 롤백몇몇은 다른 방식으로 실제적인 생각이 필요할 것입니다.
그토토 핫/pgSQL버전실행다음과 유사하게 작동합니다PL/SQL버전이지만 당신은
사용하는 것을 기억하기 위해quote_literal그리고quote_ident설명된 대로섹션
38.5.4. 유형의 구성'SELECT * FROM $1' 실행;작동하지 않습니다
이러한 기능을 사용하지 않는 한 안정적입니다.
PostgreSQL두 개를 줍니다 실행을 최적화하기 위한 함수 생성 수정자:"변동성"(함수 여부 동일한 인수가 주어지면 항상 동일한 결과를 반환합니다) 그리고"엄격함"(어떠한지 인수가 null인 경우 함수는 null을 반환합니다. 상담하세요PostgreSQL :자세한 내용은 참조 페이지입니다.
이러한 최적화 속성을 사용할 때 귀하의함수 생성문은 다음과 같습니다 이런 것:
CREATE FUNCTION foo(...) 정수를 $$로 반환합니다. ... $$ LANGUAGE plpgsql STRICT IMMUTABLE;
이 섹션에는 다음 세트에 대한 코드가 포함되어 있습니다.
오라클 호환instr함수
포팅 작업을 단순화하는 데 사용할 수 있습니다.
--
-- Oracle의 대응 기능을 모방한 instr 함수
-- 구문: instr(string1, string2, [n], [m]) 여기서 []는 선택적 매개변수를 나타냅니다.
--
-- n번째 문자부터 시작하여 string1에서 m번째 발생을 검색합니다.
-- 문자열2의 n이 음수이면 뒤로 검색합니다. m이 전달되지 않으면,
-- 1로 가정합니다(검색은 첫 번째 문자부터 시작됩니다).
--
CREATE FUNCTION instr(varchar, varchar) 정수를 $$로 반환합니다.
선언
위치 정수;
시작
위치:= instr($1, $2, 1);
반환 위치;
끝;
$$ LANGUAGE plpgsql 엄격한 불변;
CREATE FUNCTION instr(string varchar, string_to_search 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 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을 반환합니다.
종료하면;
끝;
$$ LANGUAGE plpgsql 엄격한 불변;
CREATE FUNCTION instr(string varchar, string_to_search varchar,
beg_index 정수, 발생_index 정수)
$$로 정수를 반환합니다.
선언
위치 정수 NOT NULL DEFAULT 0;
발생_번호 정수 NOT NULL DEFAULT 0;
temp_str varchar;
정수를 구걸하다;
나는 정수;
길이 정수;
ss_length 정수;
시작
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을 반환합니다.
종료하면;
끝;
$$ LANGUAGE plpgsql STRICT IMMUTABLE;