저자 :Roberto Mello (
<rmello@fslc.usu.edu
)
이 섹션은 Oracle의 PL/SQL과의 차이점을 설명합니다.PostgreSQL's토토 핫/pgsql도움을 희망하는 언어 개발자 포트 응용 프로그램 Oracle에서PostgreSQL. 여기의 대부분의 코드는 왔습니다 그만큼arsdigita ClickStream 모듈내가 포팅 한PostgreSQL내가 인턴쉽을했을 때OpenForce Inc.2000 년 여름.
토토 핫/pgsqlPL/SQL과 유사합니다 여러 측면에서. 블록 구조화되고 명령적인 언어입니다 (모든 변수는 선언되어야합니다). PL/SQL에는 더 많은 것이 있습니다 그것보다 특징PostgreSQL대응하지만토토 핫/pgsql허용 많은 기능을 위해 개선되고 있습니다. 끊임없이.
Oracle에서 포팅 할 때 명심해야 할 사항 에게PostgreSQL:
기본 매개 변수 없음PostgreSQL.
당신은 함수를 과부하 할 수 있습니다PostgreSQL. 이것은 종종 작동하는 데 사용됩니다 기본 매개 변수가 부족합니다.
과제, 루프 및 조건부는 비슷합니다.
커서가 필요 없음postgresql, 쿼리를 문장 (아래 예제 참조)
inPostgreSQLYou필요탈출 단일 따옴표. 보다섹션 19.11.1.1.
inPostgreSQL당신은 필요합니다 기능 정의 내부에서 단일 따옴표를 피하십시오. 이것 때때로, 특히 당신이 다른 함수를 생성하는 함수를 생성하고 있습니다 안에예제 19-6. 많은 것을 피할 때 명심해야 할 한 가지 단일 따옴표는 시작/끝을 제외하고는입니다 인용문, 다른 모든 사람들은 수량으로도 올 것입니다.
테이블 19-1특종을 제공합니다. (당신은이 작은 것을 사랑할 것입니다 차트.)
표 19-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). 당신은 아마도 그것을 필요로 할 것입니다 다른 기능을 생성하기 위해 함수를 사용하고있었습니다 (in예 19-6). |
a_output : = a_output || ''v_ ''|| referrer_keys.kind || '' 좋다 '''''''''' || referrer_keys.key_string || '' '' '' '' '' '' ' 그런 다음`` '' '' '||를 반환하십시오 referrer_keys.referrer_type || '' '' '';; 끝 If; ''; |
if v _ <... 좋아요 ``<... ''그런 다음``<... ''; 끝 만약에; |
예 19-5. 간단한 기능
여기 오라클 기능이 있습니다 :
함수 생성 또는 교체 CS_FMT_BROWSER_VERSION (VARCHAR의 V_NAME, v_version in Varchar) 반환 바르 르 차입니다 시작하다 v_version이 null이면 그렇다면 반환 v_name; 끝 IF; 반환 v_name || '/'|| v_version; 끝; / 오류 표시;
이 기능을 살펴보고의 차이점을 보자.토토 핫/pgsql:
PostgreSQL그렇지 않습니다 매개 변수 이름이 지정되었습니다. 당신은 그들을 명시 적으로 별명해야합니다 당신의 기능 내부.
Oracle은 가질 수 있습니다in, out및inout매개 변수가 함수로 전달되었습니다. 그만큼inout18565_18668PostgreSQL"in"매개 변수 및 함수 단일 값 만 반환 할 수 있습니다.
thereturn키워드 함수 프로토 타입 (기능 본문이 아님)이됩니다반환inPostgreSQL.
onPostgreSQL함수는 단일 따옴표를 구분 제작자로 사용하여 생성됩니다. 그래서 당신은 당신의 기능 내에서 단일 따옴표를 피해야합니다. (때때로 꽤 성가시킬 수 있습니다. 참조섹션 19.11.1.1).
the/표시 오류명령 존재하지 않음PostgreSQL.
그래서 포팅 될 때이 함수가 어떻게 보이는지 봅시다PostgreSQL:
함수 생성 또는 교체 CS_FMT_BROWSER_VERSION (Varchar, Varchar) varchar를 '로 반환합니다. 선언하다 v_name 별칭 $ 1; $ 2에 대한 v_version 별칭; 시작하다 v_version이 null이면 그렇다면 반환 v_name; 끝 IF; 반환 v_name || ''/''|| v_version; 끝; '언어'plpgsql ';
예 19-6. 다른 기능을 생성하는 함수 기능
다음 절차는 a에서 행을 잡습니다.select진술 및 큰 기능을 구축합니다 결과와 함께if진술, 효율성을 위해. 특히 주목하십시오 커서의 차이,for루프, 그리고 단일 따옴표를 피해야 할 필요성PostgreSQL.
절차 작성 또는 교체 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 ';
예 19-7. 문자열이 많은 절차 조작 및 아웃 매개 변수
다음 Oracle PL/SQL 절차는 구문 분석에 사용됩니다. URL 및 여러 요소 (호스트, 경로 및 쿼리)를 반환합니다. 그것은 이후 절차토토 핫/pgsql함수는 하나의 값만이 될 수 있습니다 반품 (참조섹션 19.11.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) 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과 똑같이 행동하십시오 (인생이 더 쉬워집니다). 보다 그만큼섹션 19.11.6코드의 경우
Oracle 절차는 약간 더 유연성을 제공합니다 명시 적으로 반환 할 필요가 없기 때문에 개발자 사용을 통해 가능합니다.inout또는out매개 변수.
예 :
절차 작성 또는 교체 CS_CREATE_JOB (v_JOB_ID Integer)는 IS입니다 a_running_job_count 정수; Pragma Autonomous_transaction;(1)시작 독점 모드의 잠금 테이블 CS_JOBS;(2)a_running_job_count로 count (*)를 선택하십시오 CS_JOBS에서 여기서 end_stamp는 null; a_running_job_count 0 인 경우 저지르다; - 무료 잠금(3)REASE_APPLICATION_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. 이 절차는 특히 우리에게 몇 가지를 가르쳐 줄 수 있기 때문에 흥미 롭습니다 :
그래서 우리 가이 절차를 포트 할 수있는 방법 중 하나를 봅시다PL/PGSQL:
함수 작성 또는 교체 CS_CREATE_JOB (Integer) 정수를 반환합니다. 선언하다 $ 1에 대한 v_job_id 별칭; a_running_job_count 정수; a_num 정수; -Pragma Autonomous_transaction; 시작하다 독점 모드에서 잠금 테이블 CS_JOBS; a_running_job_count로 count (*)를 선택하십시오 CS_JOBS에서 여기서 end_stamp는 null; a_running_job_count 0 인 경우 그 다음에 -- 저지르다; - 무료 잠금 예외 제기``새 작업을 만들 수 없음 : 현재 작업이 실행 중입니다. ''; 끝 IF; cs_active_job에서 삭제; cs_active_job (job_id) 값 (v_job_id)에 삽입; a_num으로 count (*)를 선택하십시오 CS_JOBS에서 여기서 job_id = v_job_id; 찾을 수없는 경우 - 마지막 쿼리에 아무것도 반환되지 않은 경우 -이 작업은 테이블에 있지 않으므로 삽입하십시오. cs_jobs (job_id, start_stamp) 값 (v_job_id, sysdate ())에 삽입; 반환 1; 또 다른 ``일자리가 이미 실행되는 일 ''; 통지를 제기하십시오.(1)종료 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%유형 기본 sysdate의 creation_date, 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; / 오류 표시
우리는 이것을 포트로PostgreSQLOracle 패키지의 다른 객체를 표준 명명 규칙과 기능합니다. 우리는 지불해야합니다 기본값 부족과 같은 다른 세부 사항에 대한 관심 매개 변수PostgreSQL함수. 위의 패키지는 같은 것이 될 것입니다 이것:
함수 생성 ACS__ADD_USER (정수, 정수, 바르 차, 타임 스탬프, 정수, 정수, ...) 정수를 '로 반환합니다. 선언하다 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 ';
thePostgreSQL버전execute잘 작동하지만 당신은 가지고 있습니다
사용하는 것을 기억하려면quote_literal (텍스트)
andquote_string (텍스트)
설명대로섹션 19.5.4. 유형의 구성execute ''select * from $ 1 '';작동하지 않습니다
이 기능을 사용하지 않는 한.
PostgreSQL두 가지를 제공합니다 실행 최적화를위한 기능 생성 수정 자 :iscachable(함수는 항상 동일하게 반환합니다 동일한 논증이 주어지면 결과) 및isstrict(함수가 있으면 NULL을 반환합니다 인수는 null). 상담생성 기능자세한 내용 참조.
이러한 최적화 속성을 사용하려면 사용with당신의 수정 자기능 만들기진술. 무엇 좋다:
함수 만들기 foo (...)는 정수를 반환합니다. ... '언어'plpgsql ' (isstrict, iscachable);
instr
기능- - 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)은 정수를 '로 반환합니다. 선언하다 POS 정수; 시작하다 POS : = 기기 ($ 1, $ 2,1); POS 리턴; 끝; '언어'plpgsql '; 기능 기기 생성 (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)은 정수를 다시 반환합니다. 선언하다 $ 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 ';