저자 :Roberto Mello (<rmello@fslc.usu.edu)
이 섹션에서는 Oracle의 PL/SQL과의 차이점을 설명합니다 PostgreSQL의 PL/PGSQL 언어를 도와주기 위해 언어 개발자는 Oracle에서 PostgreSQL까지의 포트 응용 프로그램입니다. 대부분의 여기의 코드는에서 나온 것입니다.arsdigita ClickStream 모듈내가 PostgreSQL로 포팅되었을 때 와 인턴쉽을 받았습니다.OpenForce Inc.2000 년 여름.
PL/PGSQL은 여러 측면에서 PL/SQL과 유사합니다. 블록입니다 구조화되고 명령적인 언어 (모든 변수는 있어야합니다 선언). PL/SQL은 PostgreSQL보다 더 많은 기능을 가지고 있습니다 대응하지만 PL/PGSQL은 많은 것을 허용합니다 기능과 지속적으로 개선되고 있습니다.
Oracle에서 포팅 할 때 명심해야 할 사항 윈 토토에 :
윈 토토의 기본 매개 변수 없음
윈 토토에서 함수를 과부하 할 수 있습니다. 이것은 종종입니다 기본 매개 변수의 부족을 해결하는 데 사용됩니다.
과제, 루프 및 조건부는 비슷합니다.
PostgreSQL에서 커서가 필요하지 않으면 쿼리를 넣으십시오. for 문 (아래 예제 참조)
윈 토토에서필요탈출 단일 따옴표. 보다섹션 24.5.1.1.
윈 토토에서 당신은 당신의 내부에서 단일 따옴표를 피해야합니다. 함수 정의. 이것은 상당히 재미있는 코드로 이어질 수 있습니다 특히 함수를 만드는 경우 다른 함수를 생성합니다.예제 24-6. 많은 것을 피할 때 명심해야 할 한 가지 단일 따옴표는 시작/끝을 제외하고는입니다 인용문, 다른 모든 사람들은 수량으로도 올 것입니다.
테이블 24-1특종을 제공합니다. (당신은이 작은 것을 사랑할 것입니다 차트.)
표 24-1. 단일 따옴표 도피 차트
아니오. 인용문 | usage | exam윈 토토e | 결과 |
---|---|---|---|
1 | 시작/종료하려면 기능 본체 |
함수 만들기 foo ()는 정수를 '...'로 반환합니다. 언어 '윈 토토pgsql'; |
as |
2 | 과제, 문자열을 정리하려면 선택합니다. |
a_output : = ''blah ''; f_name = ''foobar ''; 사용자 중에서 *를 선택하십시오. |
사용자에서 선택 *을 선택하십시오 f_name = 'foobar'; |
4 | 두 개가 필요할 때 결과 문자열이없는 단일 따옴표 그 문자열 종단. |
a_output : = a_output || ''그리고 이름 ``foobar '' 'and ...' '와 같은 |
및 'foobar'및 ... 같은 이름 |
6 | 두 배를 원할 때 결과 문자열의 따옴표and해당 문자열 종료. |
a_output : = a_output || ''그리고 이름 ``foobar '' '' ' |
및 'foobar'와 같은 이름 |
10 | 두 개를 원할 때 결과 문자열의 단일 따옴표 (계정 8 인용 용)and종료 그 끈 (2). 당신은 아마만 필요할 것입니다 다른 사람을 생성하기 위해 함수를 사용하는 경우 함수 (예 :예제 24-6). |
a_output : = a_output || ''v_ ''|| referrer_keys.kind || '' 좋다 '''''''''' || referrer_keys.key_string || '' '' '' '' '' '' ' 그런 다음`` '' '' '||를 반환하십시오 referrer_keys.referrer_type || '' '' '';; 끝 If; ''; |
if v _ <... 좋아요 ''<... ''그런 다음 돌아옵니다 ''<... ''; 끝 If; |
예제 24-5. 간단한 기능
여기 오라클 기능이 있습니다 :
함수 생성 또는 교체 CS_FMT_BROWSER_VERSION (VARCHAR의 V_NAME, v_version in Varchar) 반환 바르 르 차입니다 시작하다 v_version이 null이면 그렇다면 반환 v_name; 끝 IF; 반환 v_name || '/'|| v_version; 끝; / 오류 표시;
이 기능을 살펴보고 차이점을 보자. 윈 토토/pgsql :
the또는 교체절은 그렇지 않습니다 허용된. 기능을 명시 적으로 삭제해야합니다 비슷한 결과를 얻기 위해 만들기 전에.
PostgreSQL그렇지 않습니다 매개 변수 이름이 지정되었습니다. 당신은 그들을 명시 적으로 별명해야합니다 당신의 기능 내부.
Oracle은 가질 수 있습니다in, out및inout매개 변수가 함수로 전달되었습니다. 그만큼inout18673_18796"in"매개 변수 및 함수는 단일 만 반환 할 수 있습니다 값.
thereturn키워드 함수 프로토 타입 (기능 본문이 아님)이됩니다반환in PostgreSQL.
on PostgreSQL 함수는 단일을 사용하여 생성됩니다 구분자로 인용하므로 단일 따옴표를 피해야합니다. 당신의 기능 내부 (매우 성가신 일 수 있습니다 타임스; 보다섹션 24.5.1.1).
the/표시 오류명령 윈 토토에는 존재하지 않습니다.
그래서이 함수가 어떻게 포팅 된 것처럼 보일지 보자. 윈 토토에 :
드롭 함수 CS_FMT_BROWSER_VERSION (Varchar, Varchar); 기능 작성 CS_FMT_BROWSER_VERSION (Varchar, Varchar) Varchar를 retruns ' 선언하다 v_name 별칭 $ 1; $ 2에 대한 v_version 별칭; 시작하다 v_version이 null이면 그렇다면 반환 v_name; 끝 IF; 반환 v_name || ''/''|| v_version; 끝; '언어'plpgsql ';
예제 24-6. 다른 기능을 생성하는 함수 기능
다음 절차는 a에서 행을 잡습니다.select진술 및 큰 기능을 구축합니다 결과와 함께if진술, 효율성을 위해. 특히 주목하십시오 커서의 차이,for루프, 그리고 윈 토토에서 단일 따옴표를 피할 필요성.
절차 작성 또는 교체 CS_UPDATE_REFERRER_TYPE_PROC IS Cursor referrer_keys입니다 CS_REFERRER_KEYS에서 *를 선택하십시오 try_order의 주문; a_output varchar (4000); 시작하다 A_OUTPUT : = '기능 작성 또는 교체 CS_FIND_REFERRER_TYPE (VARCHOR의 V_HOST, VARCHAR, VARCHAR, VADDOMAIN Varchar의 v_url) 반환 바르 차르가 시작됩니다. '; referrer_key의 경우 referrer_keys 루프 a_output : = a_output || 'V_'|| referrer_key.kind || '좋아요' ''|| referrer_key.key_string || ````그런 다음 반환 '' '|| referrer_key.referrer_type || '' ';; 끝 If; '; 엔드 루프; a_output : = a_output || '귀환 널; 끝;'; 즉각적인 a_output를 실행합니다. 끝; / 오류 표시
이 함수가 PostgreSQL에서 어떻게 끝나는지는 다음과 같습니다.
함수 생성 CS_UPDATE_REFERRER_TYPE_PROC () 정수를 반환합니다. 선언하다 참조 _keys 레코드; - a에 사용할 일반 레코드를 선언하십시오. a_output varchar (4000); 시작하다 a_output : = ''기능 생성 CS_FIND_REFERRER_TYPE (Varchar, Varchar, Varchar) varchar를`` '' '로 반환합니다. 선언하다 $ 1의 V_host 별칭; V_Domain 별칭 $ 2; 3 달러에 대한 v_url 별칭; '';; - - 루프 용 쿼리 결과를 스캔하는 방법에 주목하십시오. - for <crecor 구성을 사용합니다. - select * in select * from cs_referrer_keys writ_order loop의 referrer_keys 용. a_output : = a_output || ''v_ ''|| referrer_keys.kind || '' 좋다 '''''''''' || referrer_keys.key_string || `` '' '' '' '' ''그런 다음‘ '' '' ' || referrer_keys.referrer_type || '' '' '';; 끝 If; ''; 엔드 루프; a_output : = a_output || ``return null; 끝; '' ''언어 '' 'PLPGSQL' '' ';' '; - 변수를 대체하지 않기 때문에 작동합니다. - 그렇지 않으면 실패합니다. 기능을 실행하는 다른 방법으로 수행하십시오 a_output를 실행하십시오. 끝; '언어'plpgsql ';
예제 24-7. 문자열이 많은 절차 조작 및 아웃 매개 변수
다음 Oracle PL/SQL 절차는 구문 분석에 사용됩니다. URL 및 여러 요소 (호스트, 경로 및 쿼리)를 반환합니다. 그것은 PL/PGSQL 기능에서는 하나의 값만 할 수 있기 때문에 절차 반환됩니다 (참조섹션 24.5.3). Postgresql 에서이 작업을 수행하는 한 가지 방법은 다음과 같습니다. 절차를 세 가지 다른 기능으로 분할하십시오 호스트를 반환하고, 또 다른 경로를 반환하고, 다른 하나는 질문.
절차 작성 또는 교체 CS_PARSE_URL ( Varchar의 v_url, V_HOST OUT VARCHAR-- 이것은 다시 전달됩니다 V_PATH OUT VARCHAR- - 이것도 v_query out varchar) - 그리고 이것 ~이다 A_POS1 정수; A_POS2 정수; 시작하다 v_host : = null; v_path : = null; v_query : = null; a_pos1 : = inst (v_url, '//'); - PostgreSQL에는 기기 기능이 없습니다 A_POS1 = 0이면 반품; 끝 IF; a_pos2 : = inst (v_url, '/', a_pos1 + 2); a_pos2 = 0이면 v_host : = substr (v_url, a_pos1 + 2); v_path : = '/'; 반품; 끝 IF; v_host : = substr (v_url, a_pos1 + 2, a_pos2 -a_pos1-2); a_pos1 : = inst (v_url, '?', a_pos2 + 1); A_POS1 = 0이면 v_path : = substr (v_url, a_pos2); 반품; 끝 IF; v_path : = substr (v_url, a_pos2, a_pos1 -a_pos2); v_query : = substr (v_url, a_pos1 + 1); 끝; / 오류 표시;
이 절차를 다음과 같은 방법은 다음과 같습니다 postgresql :
드롭 함수 CS_PARSE_URL_HOST (VARCHAR); 기능 작성 CS_PARSE_URL_HOST (VARCHAR) VARCHARS를 '로 반환합니다. 선언하다 $ 1의 V_URL 별칭; v_host varchar; v_path varchar; A_POS1 정수; A_POS2 정수; A_POS3 정수; 시작하다 v_host : = null; a_pos1 : = inst (v_url, ''// ''); A_POS1 = 0이면 반품 ''''; - 빈을 반환하십시오 끝 IF; a_pos2 : = inst (v_url, ''/'', a_pos1 + 2); a_pos2 = 0이면 v_host : = substr (v_url, a_pos1 + 2); v_path : = ''/''; 반환 v_host; 끝 IF; v_host : = substr (v_url, a_pos1 + 2, a_pos2 -a_pos1-2); 반환 v_host; 끝; '언어'plpgsql ';
참고 :PostgreSQL이 없습니다instr함수이므로 해결할 수 있습니다 다른 기능의 조합을 사용합니다. 나는 피곤했다 이 작업을 수행하고 내 자신을 만들었습니다instr정확히 같은 행동을하는 기능 오라클 (Oracle) (인생이 더 쉬워집니다). 참조섹션 24.5.6코드의 경우
Oracle 절차는 약간 더 유연성을 제공합니다 명시 적으로 반환 할 필요가 없기 때문에 개발자 inout 또는 out 매개 변수의 사용을 통해 가능합니다.
예 :
절차 생성 또는 교체 CS_CREATE_JOB (v_job_id in Integer) ~이다 a_running_job_count 정수; Pragma Autonomous_transaction;(1)시작 독점 모드의 잠금 테이블 CS_JOBS;(2)cs_jobs에서 a_running_job_count로 count (*)를 선택하십시오 여기서 end_stamp는 null; a_running_job_count 0 인 경우 저지르다; - 무료 잠금(3)REASE_AP윈 토토ICATION_ERROR (-20000, '새 작업을 만들 수 없습니다 : 현재 작업이 실행 중입니다.'); 끝 IF; cs_active_job에서 삭제; cs_active_job (job_id) 값 (v_job_id)에 삽입; 시작하다 cs_jobs (job_id, start_stamp) 값 (v_job_id, sysdate)에 삽입; DUP_VAL_ON_INDEX가 NULL으로 예외; - 이미 존재하는지 걱정하지 마십시오(4)끝; 저지르다; 끝; / 오류 표시
이와 같은 절차는 PostgreSQL로 쉽게 변환 할 수 있습니다 반환하는 기능Integer. 이것 특히 절차는 우리에게 가르 칠 수 있기 때문에 흥미 롭습니다. 몇 가지 :
그래서이 절차를 윈 토토/pgsql :
드롭 함수 CS_CREATE_JOB (Integer); 함수 만들기 cs_create_job (정수) 정수를 '선언으로 반환합니다 $ 1에 대한 v_job_id 별칭; a_running_job_count 정수; a_num 정수; -Pragma Autonomous_transaction; 시작하다 독점 모드에서 잠금 테이블 CS_JOBS; end_stamp가 null 인 cs_jobs에서 a_running_job_count로 count (*)를 선택하십시오. a_running_job_count 0 인 경우 -- 저지르다; - 무료 잠금 예외 제기``새 작업을 만들 수 없음 : 현재 작업이 실행 중입니다. ''; 끝 IF; cs_active_job에서 삭제; cs_active_job (job_id) 값 (v_job_id)에 삽입; cs_jobs에서 job_id = v_job_id; 찾을 수없는 경우 - 마지막 쿼리에 아무것도 반환되지 않은 경우 -이 작업은 테이블에 있지 않으므로 삽입하십시오. cs_jobs (job_id, start_stamp) 값 (v_job_id, sysdate ())에 삽입; 반환 1; 또 다른 ``일자리가 이미 실행되는 일 ''; 통지를 제기하십시오.(1)END IF; 반환 0; 끝; '언어'plpgsql ';
참고 :패키지를 직접 많이하지 않았습니다. 그러니 여기에 실수가 있으면 알려주세요.
패키지는 Oracle이 PL/SQL을 캡슐화하도록 제공하는 방법입니다. Java 클래스와 같은 한 엔티티로의 진술과 기능 방법과 객체를 정의하는 곳. 당신은 이것에 액세스 할 수 있습니다 a와 객체/방법"."(점). 다음은 오라클의 예입니다 ACS 4의 패키지 (Arsdigita 커뮤니티 시스템) :
패키지 바디 AC를 만들거나 교체하십시오 ~처럼 함수 add_user ( user_id user.user_id%유형 기본 널, acs_objects.object_type%유형의 Object_type 기본 '사용자', acs_objects.creation_date%유형의 creation_date 기본 sysdate, acs_objects.creation_user%유형의 creation_user 기본 널, acs_objects.creation_ip%유형 기본 널, creation_ip, ... ) user.user_id%유형을 반환합니다 ~이다 v_user_id users.user_id%유형; v_rel_id membership_rels.rel_id%유형; 시작하다 v_user_id : = acs_user.new (user_id, object_type, creation_date, creation_user, creation_ip, 이메일, ... 반환 v_user_id; 끝; 끝 AC; / 오류 표시
우리는 다른 객체를 만들어 PostgreSQL에 포트합니다. 표준 이름 지정 기능으로 Oracle 패키지의 협약. 우리는 다른 세부 사항에주의를 기울여야합니다. PostgreSQL 함수의 기본 매개 변수가 부족합니다. 위의 패키지는 다음과 같습니다.
기능 생성 ACS__ADD_USER (정수, 정수, Varchar, DateTime, Integer, Integer, ...) 정수를 '로 반환합니다. 선언하다 user_id alias $ 1; 대상 _type 별칭 $ 2; $ 3에 대한 Creation_date 별칭; Creation_user 별칭 $ 4; 5 달러에 대한 Creation_ip 별칭; ... v_user_id users.user_id%유형; v_rel_id membership_rels.rel_id%유형; 시작하다 v_user_id : = acs_user__new (user_id, object_type, creation_date, creation_user, creation_ip, ...); ... 반환 v_user_id; 끝; '언어'plpgsql ';
PostgreSQL 버전의execute잘 작동하지만 사용하는 것을 기억해야합니다quote_literal (텍스트)andquote_string (텍스트)설명대로섹션 24.2.5.3. 유형의 구성execute ''select * from $ 1 '';작동하지 않습니다 이 기능을 사용하지 않는 한.
PostgreSQL은 두 가지 기능 생성 수정 자에게 제공합니다 실행 최적화 :iscachable(함수는 동일하게 주어지면 항상 동일한 결과를 반환합니다. 논쟁) 및isstrict(함수 인수가 null이면 null을 반환합니다). 상담함수 생성자세한 내용 참조.
이러한 최적화 속성을 사용하려면 사용with당신의 수정 자함수 생성진술. 무엇 좋다:
함수 만들기 foo (...)는 정수를 반환합니다. ... '언어'plpgsql ' (isstrict, iscachable);
- - Oracle의 상대를 모방하는 기기 기능 - 구문 : inst (String1, String2, [n], [m]) 여기서 []는 선택적 매개 변수를 나타냅니다. - - mth의 nth 캐릭터에서 시작하는 string1을 검색합니다. - String2의 발생. n이 음수이면 뒤로 검색하십시오. M이라면 - 통과하지 말고 1이라고 가정합니다 (첫 번째 문자에서 검색이 시작됩니다). - - Roberto Mello (rmello@fslc.usu.edu) - Robert Gaszewski (graszew@poland.com)에 의해 수정되었습니다. -GPL V2 이상에 따라 라이센스가 부여됩니다. - 드롭 기능 기기 (Varchar, Varchar); 기능 기기 생성 (Varchar, Varchar)은 정수를 '로 반환합니다. 선언하다 POS 정수; 시작하다 POS : = 기기 ($ 1, $ 2,1); POS 리턴; 끝; '언어'plpgsql '; 드롭 기능 기기 (Varchar, Varchar, Integer); 기능 기기 생성 (Varchar, Varchar, Integer)은 정수를 '로 반환합니다. 선언하다 $ 1의 문자열 별칭; String_to_search alias $ 2; Beg_index 별칭 $ 3; POS 정수 NOL NULL DEFAULT 0; temp_str varchar; 정수를 구걸하십시오. 길이 정수; ss_length 정수; 시작하다 beg_index 0이면 temp_str : = substring (beg_index의 문자열); pos : = 위치 (temp_str의 String_to_search); POS = 0이면 반환 0; 또 다른 POS + BEG_INDEX를 반환합니다 -1; 끝 IF; 또 다른 ss_length : = char_length (String_to_search); 길이 : = char_length (문자열); beg : = 길이 + beg_index -ss_length + 2; beg 0 루프 temp_str : = 서브 스트링 (ss_length의 beg에서 문자열); pos : = 위치 (temp_str의 String_to_search); POS 0이라면 반환 구걸; 끝 IF; Beg : = Beg -1; 엔드 루프; 반환 0; 끝 IF; 끝; '언어'plpgsql '; - - Robert Gaszewski (graszew@poland.com) 작성 -GPL V2 이상에 따라 라이센스가 부여됩니다. - 드롭 기능 기기 (Varchar, Varchar, Integer, Integer); 기능 악기 생성 (Varchar, Varchar, Integer, Integer)은 정수를 다시 반환합니다. 선언하다 $ 1의 문자열 별칭; String_to_search alias $ 2; Beg_index 별칭 $ 3; 4 달러에 대한 alse_index 별칭; POS 정수 NOL NULL DEFAULT 0; alkes_number 정수 NOL NULL DEFAULT 0; temp_str varchar; 정수를 구걸하십시오. 나는 정수; 길이 정수; ss_length 정수; 시작하다 beg_index 0이면 beg : = beg_index; temp_str : = substring (beg_index의 문자열); 1. Occur_index 루프 pos : = 위치 (temp_str의 String_to_search); I = 1이면 beg : = beg + pos -1; 또 다른 beg : = beg + pos; 끝 IF; temp_str : = 서브 스트링 (beg + 1의 문자열); 엔드 루프; POS = 0이면 반환 0; 또 다른 반환 구걸; 끝 IF; 또 다른 ss_length : = char_length (String_to_search); 길이 : = char_length (문자열); beg : = 길이 + beg_index -ss_length + 2; beg 0 루프 temp_str : = 서브 스트링 (ss_length의 beg에서 문자열); pos : = 위치 (temp_str의 String_to_search); POS 0이라면 alkes_number : = alkes_number + 1; alke_number = cose_index가있는 경우 반환 구걸; 끝 IF; 끝 IF; Beg : = Beg -1; 엔드 루프; 반환 0; 끝 IF; 끝; '언어'plpgsql ';