| PostgreSQL 9.2.24 문서 | ||||
|---|---|---|---|---|
| PostgreSQL : 문서 : 9.2 : 와이즈 토토 프로 시저 | 위로 | 39장.스포츠 토토/pgSQL - SQL절차적 언어 | 다음 | |
이 섹션에서는 다음과 같은 구현 세부 사항에 대해 설명합니다. 자주 중요한스포츠 토토/pgSQL사용자가 알아야 할 내용입니다.
a 내의 SQL 문 및 표현식스포츠 토토/pgSQL함수는 변수를 참조할 수 있습니다. 그리고 함수의 매개변수. 비하인드 스토리,스포츠 토토/pgSQL다음의 쿼리 매개변수를 대체합니다. 그런 참고자료. 매개변수는 장소에서만 대체됩니다. 여기서 매개변수 또는 열 참조는 구문상 허용됩니다. 극단적인 경우로, 잘못된 프로그래밍의 예를 생각해 보십시오. 스타일:
foo(foo) 값(foo)에 삽입;
다음의 첫 번째 발생foo반드시 구문상 테이블 이름이므로 대체되지 않습니다. 함수에 이름이 지정된 변수가 있더라도foo. 두 번째 항목의 이름은 다음과 같아야 합니다. 테이블의 열이므로 대체되지 않습니다. 만 세 번째 발생은 다음에 대한 참조가 될 후보입니다. 함수의 변수입니다.
참고: 포스트그레SQL9.0 이전 버전에서는 다음의 변수를 대체하려고 시도합니다. 세 가지 경우 모두 구문 오류가 발생합니다.
변수 이름은 구문상 다르지 않기 때문에 테이블 열 이름에서 모호함이 있을 수 있습니다. 테이블도 참조하는 명령문: 다음을 의미하는 주어진 이름입니다. 테이블 열을 참조합니까, 아니면 변수를 참조합니까? 다음을 바꾸자 이전 예
INSERT INTO dest (col) SELECT foo + bar FROM src;
여기,대상그리고src테이블 이름이어야 하며,col다음 열이어야 합니다.대상하지만foo그리고바합리적으로 둘 중 하나일 수 있습니다. 함수의 변수 또는의 열src.
기본적으로,스포츠 토토/pgSQL할 것이다 SQL 문의 이름이 다음을 참조할 수 있으면 오류를 보고합니다. 변수 또는 테이블 열입니다. 그런 문제를 해결할 수 있어요 변수나 열의 이름을 바꾸거나 모호한 참조 또는 말함으로써스포츠 토토/pgSQL어떤 해석을 선호합니다.
가장 간단한 해결책은 변수나 열의 이름을 바꾸는 것입니다. 에이 일반적인 코딩 규칙은 다른 명명 규칙을 사용하는 것입니다.스포츠 토토/pgSQL변수가 당신보다 열 이름에 사용합니다. 예를 들어, 지속적으로 이름을 지정하는 경우 함수 변수v_뭔가당신의 열에는 아무것도 없습니다 이름은 다음으로 시작합니다.v_, 충돌이 발생하지 않습니다. 발생합니다.
또는 모호한 참조를 한정하여 만들 수 있습니다. 분명해요. 위의 예에서,src.foo에 대한 명확한 참조가 될 것입니다. 테이블 열. 변수에 대한 명확한 참조를 생성하려면, 라벨이 붙은 블록에서 선언하고 블록의 라벨을 사용합니다(참조Postgre범퍼카 토토 : 문서 : 9.2 : PL/PG범퍼카 토토의 구조). 에 대한 예
<<블록
선언
foo int;
시작
foo := ...;
INSERT INTO dest (col) SELECT block.foo + bar FROM src;
여기block.foo변수를 의미합니다. 열이 있더라도foo에src. 함수 매개변수뿐만 아니라 다음과 같은 특수 변수발견, 할 수 있어요 함수 이름으로 한정되어야 합니다. 라벨이 붙은 외부 블록에서 암시적으로 선언되었습니다. 함수 이름입니다.
때로는 모든 모호한 문제를 해결하는 것이 비실용적입니다. 큰 본문의 참조스포츠 토토/pgSQL코드. 그러한 경우에는 다음을 수행할 수 있습니다. 그것을 지정하십시오스포츠 토토/pgSQL해야 한다 모호한 참조를 변수로 해결합니다(이는 호환 가능스포츠 토토/pgSQL의 이전의 행동PostgreSQL9.0) 또는 테이블 열(일부 호환 가능) 다음과 같은 다른 시스템오라클).
시스템 전반에 걸쳐 이 동작을 변경하려면 구성 매개변수스포츠 토토pgsql.variable_contribute다음 중 하나에게오류, use_variable또는use_column(어디에서오류공장 기본값임). 이 매개변수 이후의 명령문 컴파일에 영향을 줍니다.스포츠 토토/pgSQL함수, 그러나 명령문은 아님 현재 세션에서 이미 컴파일되었습니다. 이렇게 바꾸니까 설정으로 인해 동작에 예상치 못한 변화가 발생할 수 있습니다.스포츠 토토/pgSQL기능을 수행할 수 있습니다. 슈퍼유저만 변경할 수 있습니다.
함수별로 동작을 설정할 수도 있습니다 기본적으로 시작 시 이러한 특수 명령 중 하나를 삽입하여 기능 텍스트 중:
#변수_충돌 오류 #변수_충돌 사용_변수 #변수_충돌 사용_열
이 명령은 작성된 기능에만 영향을 미칩니다. 그리고 설정을 재정의합니다.스포츠 토토pgsql.variable_contribute. 예는 다음과 같습니다.
CREATE FUNCTION stamp_user(id int, comment text) RETURNS void AS $$
#변수_충돌 사용_변수
선언
curtime 타임스탬프 := now();
시작
UPDATE 사용자 SET last_modified = curtime, 댓글 = 댓글
여기서 users.id = id;
끝;
$$ 언어 plpgsql;
에서업데이트명령,커타임, 댓글및id함수를 참조합니다. 변수 및 매개변수 여부사용자에 해당 이름의 열이 있습니다. 우리는 참조를 한정해야 했습니다.users.id에서어디절을 사용하여 테이블 열을 참조하도록 합니다. 하지만 우리는 그렇지 않았습니다 참조를 한정해야 합니다.댓글대상으로업데이트목록, 왜냐하면 구문론적으로는 다음과 같아야 하기 때문입니다. 의 열사용자. 우리는 에 의존하지 않고 동일한 기능변수_충돌이런 식으로 설정:
CREATE FUNCTION stamp_user(id int, comment text) RETURNS void AS $$
<<fn
선언
curtime 타임스탬프 := now();
시작
UPDATE 사용자 SET last_modified = fn.curtime, 댓글 = stamp_user.comment
여기서 users.id = stamp_user.id;
끝;
$$ 언어 plpgsql;
명령 문자열에서 변수 대체가 발생하지 않습니다. 에게 주어졌다실행또는 그 중 하나 변형. 이러한 변수에 다양한 값을 삽입해야 하는 경우 명령을 사용하여 문자열 값 구성의 일부로 수행하거나사용 중, 그림 참조섹션 39.5.4.
변수 대체는 현재 다음에서만 작동합니다.선택, 삽입, 업데이트및삭제명령, 왜냐하면 기본 SQL 엔진이 이러한 명령에서만 쿼리 매개변수를 허용합니다. 사용하려면 다른 문 유형의 상수가 아닌 이름이나 값 (일반적으로 유틸리티 명령문이라고 함) 문자열로 된 유틸리티 설명 및실행그것.
그스포츠 토토/pgSQL통역사 함수의 소스 텍스트를 구문 분석하고 내부 텍스트를 생성합니다. 함수가 처음 호출될 때 이진 명령 트리 (각 세션 내에서). 명령어 트리는 완전히 번역됩니다.스포츠 토토/pgSQL문장 구조이지만 개별적임SQL표현 및SQL함수에 사용된 명령은 다음과 같습니다. 즉시 번역되었습니다.
각 표현과SQL명령은 다음에서 처음 실행됩니다.
함수,스포츠 토토/pgSQL통역사는 명령을 구문 분석하고 분석하여
준비된 문, 다음을 사용하여SPI관리자SPI_prepare함수. 이후 방문
해당 표현식이나 명령은 준비된 문을 재사용합니다. 따라서,
거의 방문되지 않는 조건부 코드 경로가 있는 함수
해당 명령을 분석하는 데 드는 오버헤드가 발생하지 않습니다.
현재 세션 내에서는 실행되지 않습니다. 단점
특정 표현이나 명령의 오류는 오류가 될 수 없다는 것입니다
함수의 해당 부분에 도달할 때까지 감지됩니다.
실행. (사소한 구문 오류는
초기 구문 분석은 통과하지만 더 깊은 내용은 감지되지 않습니다.
실행될 때까지.)
스포츠 토토/pgSQL(또는 그 이상 정확하게 말하면 SPI 관리자)는 추가로 캐시를 시도할 수 있습니다. 특정 준비된 것과 관련된 실행 계획 성명. 캐시된 계획을 사용하지 않으면 새로 실행됩니다. 명세서를 방문할 때마다 계획이 생성되며, 현재 매개변수 값(즉,스포츠 토토/pgSQL변수 값)을 사용하여 선택한 계획을 최적화합니다. 명령문에 매개변수가 없는 경우 또는 여러 번 실행되면 SPI 관리자는 다음을 고려할 것입니다. 생성 중일반그렇지 않은 계획 특정 매개변수 값에 따라 달라지며 이를 캐싱합니다. 재사용. 일반적으로 이는 실행 계획이 다음과 같은 경우에만 발생합니다. 의 값에 그다지 민감하지 않습니다.스포츠 토토/pgSQL여기에서 참조된 변수입니다. 그렇다면 즉, 매번 계획을 세우는 것이 순익입니다.
왜냐하면스포츠 토토/pgSQL저장 이런 식으로 준비된 진술과 때로는 실행 계획, a에 직접 나타나는 SQL 명령스포츠 토토/pgSQL함수는 동일한 내용을 참조해야 합니다. 모든 실행 시 테이블과 열 즉, 당신은 사용할 수 없습니다 SQL 명령의 테이블이나 열 이름인 매개변수입니다. 이 제한 사항을 해결하기 위해 동적을 생성할 수 있습니다. 를 사용하는 명령스포츠 토토/pgSQL 실행진술 — 대가로 새로운 구문 분석을 수행하고 새로운 실행을 구성합니다. 모든 실행을 계획하세요.
기록 변수의 변경 가능 특성은 또 다른 특징을 제시합니다. 이와 관련하여 문제가 있습니다. 레코드 변수의 필드가 있는 경우 표현식이나 명령문에 사용되는 데이터 유형 필드는 한 번의 함수 호출에서 다음으로 변경되어서는 안 됩니다. 다음으로, 각 표현식은 데이터를 사용하여 분석되므로 표현식에 처음 도달할 때 존재하는 유형입니다.실행이 문제를 해결하는 데 사용할 수 있습니다 필요할 때 문제가 발생합니다.
동일한 함수가 둘 이상의 트리거로 사용되는 경우 테이블,스포츠 토토/pgSQL준비하고 각 테이블에 대해 독립적으로 명령문을 캐시합니다. 즉, 각 트리거 함수와 테이블에 대한 캐시가 있습니다. 단지 각 기능에 대한 조합이 아닙니다. 이는 일부 완화 다양한 데이터 유형의 문제; 예를 들어, 트리거 기능은 다음과 함께 성공적으로 작동할 수 있습니다. 이름이 지정된 열키만약 그런 일이 일어나더라도 테이블마다 유형이 다릅니다.
마찬가지로, 다형성 인수 유형을 갖는 함수는 실제 조합마다 별도의 명령문 캐시 호출된 인수 유형이므로 데이터 유형은 차이점으로 인해 예상치 못한 오류가 발생하지 않습니다.
문 캐싱은 때때로 다음에 놀라운 영향을 미칠 수 있습니다. 시간에 민감한 값의 해석. 예를 들어 거기에는 이 두 함수의 차이점은 다음과 같습니다.
CREATE FUNCTION logfunc1(logtxt text) 반환 $$로 무효
시작
INSERT INTO 로그 테이블 VALUES(logtxt, 'now');
끝;
$$ 언어 스포츠 토토pgsql;
그리고:
CREATE FUNCTION logfunc2(logtxt text) 반환 $$로 무효
선언
curtime 타임스탬프;
시작
curtime := '지금';
INSERT INTO 로그 테이블 VALUES(logtxt, curtime);
끝;
$$ 언어 스포츠 토토pgsql;
다음의 경우logfunc1, 그PostgreSQL메인 파서는 알고 있습니다
분석할 때삽입그건
문자열'지금'다음과 같이 해석되어야 합니다타임스탬프, 대상 열이로그 테이블이런 종류입니다. 따라서,'지금'a로 변환됩니다타임스탬프일 때 상수삽입분석된 후 모든 용도에 사용됩니다.
호출logfunc1중
세션의 수명. 말할 필요도 없이 이건 아니다.
프로그래머가 원했어요. 더 좋은 아이디어는 다음을 사용하는 것입니다.지금()또는현재_타임스탬프함수.
다음의 경우logfunc2, 그PostgreSQL메인 파서가 수행하는 작업
어떤 유형인지 모르겠습니다'지금'다음과 같아야 합니다
따라서 유형의 데이터 값을 반환합니다.텍스트문자열 포함지금. 이후 현지 임무를 수행하는 동안
변수커타임, 그스포츠 토토/pgSQL인터프리터는 이 문자열을 다음으로 변환합니다.타임스탬프다음을 호출하여 입력text_out그리고timestamp_in변환을 위한 함수.
따라서 계산된 타임스탬프는 실행될 때마다 업데이트됩니다.
프로그래머는 기대합니다. 이런 일이 발생하더라도
예상했지만 그다지 효율적이지 않으므로지금()함수를 사용하는 것이 더 나은 아이디어일 것입니다.