이 문서는 지원되지 않는 PostgreSQL 버전에 대한 것입니다.
당신은 다음과 같은 페이지를 보고 싶을 수도 있습니다.PostgreSQL : 문서 : 17 : 41.11. 범퍼카 토토/PGSQL 아래의 후드버전 또는 위에 나열된 다른 지원 버전 중 하나를 사용하세요.

40.10. 토토 사이트/pgSQL내부적으로

이 섹션에서는 자주 중요한 구현 세부 사항을 논의합니다.토토 사이트/pgSQL사용자가 알아야 합니다.

40.10.1. 변수 대체

a 내의 SQL 문 및 표현식토토 사이트/pgSQL함수는 함수의 변수 및 매개변수를 참조할 수 있습니다. 비하인드 스토리,토토 사이트/pgSQL해당 참조를 쿼리 매개변수로 대체합니다. 매개변수는 매개변수 또는 열 참조가 구문상 허용되는 위치에서만 대체됩니다. 극단적인 경우로 다음과 같은 잘못된 프로그래밍 스타일의 예를 고려해 보세요.

foo(foo) 값(foo)에 삽입;

다음의 첫 번째 발생foo구문적으로 테이블 이름이어야 하므로 함수에 이름이 지정된 변수가 있더라도 대체되지 않습니다.foo. 두 번째로 나타나는 것은 테이블의 열 이름이어야 하므로 대체되지 않습니다. 세 번째 발생만이 함수 변수에 대한 참조가 될 수 있는 후보입니다.

참고: 포스트그레SQL9.0 이전 버전에서는 세 가지 경우 모두 변수를 대체하려고 시도하여 구문 오류가 발생했습니다.

변수의 이름은 테이블 열의 이름과 구문상 다르지 않기 때문에 테이블을 참조하는 명령문에는 모호함이 있을 수 있습니다. 주어진 이름이 테이블 열을 참조하기 위한 것입니까, 아니면 변수를 참조하기 위한 것입니까? 이전 예를 다음과 같이 변경해 보겠습니다.

INSERT INTO dest (col) SELECT foo + bar FROM src;

여기,대상src테이블 이름이어야 하며,col다음 열이어야 합니다.대상하지만foo그리고합리적으로 함수의 변수 또는 열일 수 있습니다.src.

기본적으로,토토 사이트/pgSQLSQL 문의 이름이 변수나 테이블 열을 참조할 수 있으면 오류를 보고합니다. 변수나 열의 이름을 바꾸거나 모호한 참조를 한정하거나 다음과 같이 말하여 이러한 문제를 해결할 수 있습니다.토토 사이트/pgSQL어떤 해석을 선호하는지.

가장 간단한 해결책은 변수나 열의 이름을 바꾸는 것입니다. 일반적인 코딩 규칙은 다른 명명 규칙을 사용하는 것입니다.토토 사이트/pgSQL변수는 열 이름에 사용하는 것보다 높습니다. 예를 들어 함수 변수의 이름을 일관되게 지정하는 경우v_뭔가열 이름이 다음으로 시작하지 않는 동안v_, 충돌이 발생하지 않습니다.

또는 모호한 참조를 명확하게 하기 위해 한정할 수 있습니다. 위의 예에서,src.foo은 테이블 열에 대한 명확한 참조입니다. 변수에 대한 명확한 참조를 생성하려면 레이블이 지정된 블록에서 선언하고 블록의 레이블을 사용하십시오(참조)Postgre스포츠 토토 : 문서 : 9.4 : PL/PG스포츠 토토의 구조). 예를 들어,

<<블록
선언
    foo int;
시작
    foo := ...;
    INSERT INTO dest (col) SELECT block.foo + bar FROM src;

여기block.foo열이 있어도 변수를 의미함fooinsrc. 함수 매개변수 및 다음과 같은 특수 변수발견은 함수 이름으로 레이블이 지정된 외부 블록에서 암시적으로 선언되기 때문에 함수 이름으로 한정될 수 있습니다.

때로는 큰 본문에서 모든 모호한 참조를 수정하는 것이 비실용적입니다.토토 사이트/pgSQL코드. 그러한 경우에는 다음과 같이 지정할 수 있습니다.토토 사이트/pgSQL모호한 참조를 변수로 해결해야 합니다(호환 가능토토 사이트/pgSQL이전의 행동PostgreSQL9.0) 또는 테이블 열(다음과 같은 다른 시스템과 호환 가능)오라클).

시스템 전체에서 이 동작을 변경하려면 구성 매개변수를 설정하십시오.토토 사이트pgsql.variable_conflect다음 중 하나에게오류, 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;

다음에 주어진 명령 문자열에서는 변수 대체가 발생하지 않습니다.실행또는 그 변종 중 하나. 이러한 명령에 다양한 값을 삽입해야 하는 경우 문자열 값 구성의 일부로 삽입하거나 다음을 사용하세요.사용 중, 그림 참조섹션 40.5.4.

변수 대체는 현재 다음에서만 작동합니다.선택, 삽입, 업데이트삭제명령. 기본 SQL 엔진은 이러한 명령에서만 쿼리 매개변수를 허용하기 때문입니다. 다른 문 유형(일반적으로 유틸리티 문이라고 함)에서 상수가 아닌 이름이나 값을 사용하려면 유틸리티 문을 문자열로 구성해야 하며실행그것.

40.10.2. 캐싱 계획

토토 사이트/pgSQL인터프리터는 함수의 소스 텍스트를 구문 분석하고 함수가 처음 호출될 때(각 세션 내에서) 내부 바이너리 명령 트리를 생성합니다. 지침 트리는 다음을 완전히 번역합니다.토토 사이트/pgSQL문 구조, 그러나 개별SQL표현식 및SQL함수에 사용된 명령은 즉시 번역되지 않습니다.

각 표현과SQL명령이 함수에서 처음 실행되면,토토 사이트/pgSQL인터프리터는 명령을 구문 분석하고 분석하여 준비된 명령문을 생성합니다.SPI관리자SPI_prepare함수. 이후에 해당 표현식이나 명령을 방문하면 준비된 문이 재사용됩니다. 따라서 거의 방문되지 않는 조건부 코드 경로가 있는 함수는 현재 세션 내에서 한 번도 실행되지 않은 명령을 분석하는 오버헤드를 발생시키지 않습니다. 단점은 함수의 해당 부분이 실행될 때까지 특정 표현식이나 명령의 오류를 감지할 수 없다는 것입니다. (사소한 구문 오류는 초기 구문 분석 단계에서 감지되지만 더 깊은 내용은 실행될 때까지 감지되지 않습니다.)

토토 사이트/pgSQL(더 정확하게는 SPI 관리자)는 또한 특정 준비된 문과 관련된 실행 계획을 캐시하려고 시도할 수 있습니다. 캐시된 계획이 사용되지 않으면 명령문을 방문할 때마다 새로운 실행 계획이 생성되고 현재 매개변수 값(즉,토토 사이트/pgSQL변수 값)을 사용하여 선택한 계획을 최적화할 수 있습니다. 명령문에 매개변수가 없거나 여러 번 실행되는 경우 SPI 관리자는일반특정 매개변수 값에 종속되지 않는 계획이며 재사용을 위해 이를 캐싱합니다. 일반적으로 이는 실행 계획이 값에 그다지 민감하지 않은 경우에만 발생합니다.토토 사이트/pgSQL여기에서 참조된 변수입니다. 그렇다면 매번 계획을 세우는 것이 순 승리입니다. 참조준비Prepared 문의 동작에 대한 자세한 내용은.

왜냐하면토토 사이트/pgSQL이런 방식으로 준비된 문과 때로는 실행 계획을 저장합니다. SQL 명령은 a토토 사이트/pgSQL함수는 모든 실행에서 동일한 테이블과 열을 참조해야 합니다. 즉, 매개변수를 SQL 명령의 테이블이나 열 이름으로 사용할 수 없습니다. 이 제한을 해결하려면 다음을 사용하여 동적 명령을 구성할 수 있습니다.토토 사이트/pgSQL 실행statement — 새로운 구문 분석을 수행하고 모든 실행에서 새로운 실행 계획을 구성하는 대가를 치르게 됩니다.

레코드 변수의 변경 가능 특성은 이와 관련하여 또 다른 문제를 나타냅니다. 레코드 변수의 필드가 표현식이나 명령문에 사용되는 경우 각 함수 호출에서 필드의 데이터 유형이 변경되어서는 안 됩니다. 각 표현식은 표현식에 처음 도달할 때 존재하는 데이터 유형을 사용하여 분석되기 때문입니다.실행필요할 때 이 문제를 해결하는 데 사용할 수 있습니다.

동일한 함수가 둘 이상의 테이블에 대한 트리거로 사용되는 경우,토토 사이트/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, 그포스트그레SQL메인 파서는 분석할 때 알고 있습니다.삽입그 문자열'지금'다음과 같이 해석되어야 합니다타임스탬프, 대상 열이로그 테이블그런 종류입니다. 따라서,'지금'a로 변환됩니다타임스탬프일 때 상수삽입분석된 후 모든 호출에 사용됩니다.logfunc1세션 수명 동안. 말할 필요도 없이 이것은 프로그래머가 원하는 것이 아닙니다. 더 좋은 아이디어는 다음을 사용하는 것입니다.지금()또는현재_타임스탬프함수.

다음의 경우logfunc2, 그PostgreSQL메인 파서는 어떤 유형인지 모릅니다'지금'다음과 같아야 하므로 다음 유형의 데이터 값을 반환합니다.텍스트문자열 포함지금. 지역 변수에 대한 후속 할당 중커타임, 그토토 사이트/pgSQL통역사는 이 문자열을타임스탬프다음을 호출하여 입력text_out그리고timestamp_in변환을 위한 함수. 따라서 계산된 타임스탬프는 프로그래머가 예상하는 대로 각 실행마다 업데이트됩니다. 이것이 예상대로 작동하더라도 그다지 효율적이지는 않으므로지금()함수를 사용하는 것이 더 나은 아이디어일 것입니다.