다음의 조회수포스트그레은 스포츠 토토 결과 시스템을 사용하여 구현되었습니다. 사실은 절대적으로 있어요 a 사이에는 차이가 없습니다.
CREATE VIEW myview AS SELECT * FROM mytab;두 명령과 비교
테이블 생성 myview (mytab과 동일한 속성 목록);
    대신 myview를 선택하려면 스포츠 토토 결과 "_RETmyview"를 생성하세요.
        SELECT * FROM mytab;이것이 바로 CREATE VIEW 명령이 하는 일이기 때문입니다
내부적으로. 여기에는 몇 가지 부작용이 있습니다. 그 중 하나는
뷰에 대한 정보는포스트그레시스템 카탈로그는 정확히 동일합니다
테이블과 마찬가지로. 따라서 쿼리 파서의 경우 절대적으로
테이블과 뷰 사이에는 차이가 없습니다. 그것들은 똑같습니다 -
처지. 지금은 그게 중요해요.스포츠 토토 결과 ON SELECT는 마지막 단계로 모든 쿼리에 적용됩니다. 주어진 명령이 INSERT, UPDATE 또는 DELETE인 경우에도 마찬가지입니다. 그리고 그것들은 다른 것들과 의미가 다르다는 점에서 새로운 구문 분석 트리를 생성하는 대신 해당 구문 분석 트리를 수정하십시오. 그래서 SELECT 스포츠 토토 결과이 먼저 설명됩니다.
현재 ON SELECT에는 하나의 작업만 있을 수 있습니다. 규칙이며 무조건적인 SELECT 작업이어야 합니다. 대신에. 이 제한은 규칙을 안전하게 만들기 위해 필요했습니다. 일반 사용자에게 공개하기에 충분하며 규칙을 제한합니다. ON 실제 보기 규칙을 선택합니다.
이 문서의 예는 다음을 수행하는 두 개의 조인 뷰입니다. 일부 계산과 이를 차례로 사용하는 추가 보기. 하나 두 개의 첫 번째 보기 중 나중에 다음에 대한 규칙을 추가하여 사용자 정의됩니다. INSERT, UPDATE 및 DELETE 작업을 수행하여 최종 결과를 얻습니다. 마법이 적용된 실제 테이블처럼 동작하는 뷰가 될 것입니다. 기능. 시작하기에는 그렇게 간단한 예가 아닙니다. 그리고 이것은 일을 시작하기 더 어렵게 만듭니다. 하지만 더 나은 단계별로 논의된 모든 사항을 다루는 하나의 예를 가지고 여러 가지가 섞일 수 있는 것보다 한 단계 더 나아가세요. 염두에 두세요.
예제를 가지고 놀기 위해 필요한 데이터베이스의 이름은 다음과 같습니다 al_bundy. 이것이 왜 데이터베이스 이름인지 곧 알게 될 것입니다. 그리고 그것은 절차적 언어 PL/pgSQL이 설치되어 있어야 합니다. 2 정수 중 낮은 값을 반환하는 작은 min() 함수가 필요합니다. 가치. 우리는 그것을 다음과 같이 만듭니다
CREATE FUNCTION min(정수, 정수) 정수 AS를 반환합니다.
        '시작하다
            $1 < $2이면
                $1를 반환합니다.
            종료하면;
            $2를 반환합니다.
        끝;'
    언어 'plpgsql';
    처음 두 스포츠 토토 결과 시스템에 필요한 실제 테이블 설명은 다음과 같습니다:
테이블 신발_데이터 생성(
        shoename char(10), -- 기본 키
        sh_avail 정수, -- 사용 가능한 쌍 수
        slcolor char(10), -- 선호하는 신발끈 색상
        slminlen float, -- 최소 신발끈 길이
        slmaxlen float, -- 최대 신발끈 길이
        slunit char(8) - 길이 단위
    );
    CREATE TABLE 신발끈_데이터(
        sl_name char(10), -- 기본 키
        sl_avail 정수, -- 사용 가능한 쌍 수
        sl_color char(10), -- 신발끈 색상
        sl_len float, -- 신발끈 길이
        sl_unit char(8) -- 길이 단위
    );
    CREATE TABLE 단위(
        un_name char(8), -- 기본 키
        un_fact float -- cm로 변환할 인수
    );나는 우리 대부분이 신발을 신으며 이것이 무엇인지 알 수 있다고 생각합니다.
정말 유용한 데이터. 세상에는 그런 신발이 있어요
신발끈은 필요하지 않지만 이것이 Al의 삶을 더 쉽게 만들고
그래서 우리는 그것을 무시합니다.보기는 다음과 같이 생성됩니다.
신발 AS 보기 만들기
        sh.신발이름 선택,
               sh.sh_avail,
               sh.slcolor,
               sh.slminlen,
               sh.slminlen * un.un_fact AS slminlen_cm,
               sh.slmaxlen,
               sh.slmaxlen * un.un_fact AS slmaxlen_cm,
               sh.slunit
          shoe_data sh, 단위 un에서
         sh.slunit = un.un_name;
    신발끈 AS 보기 만들기
        s.sl_name 선택,
               s.sl_avail,
               s.sl_color,
               s.sl_len,
               s.sl_유닛,
               s.sl_len * u.un_fact AS sl_len_cm
          신발끈_데이터 s, 단위 u에서
         s.sl_unit = u.un_name;
    shoe_ready AS 보기 만들기
        rsh.신발이름 선택,
               rsh.sh_avail,
               rsl.sl_이름,
               rsl.sl_avail,
               min(rsh.sh_avail, rsl.sl_avail) AS total_avail
          FROM 신발 rsh, 신발끈 rsl
         여기서 rsl.sl_color = rsh.slcolor
           그리고 rsl.sl_len_cm = rsh.slminlen_cm
           그리고 rsl.sl_len_cm <= rsh.slmaxlen_cm;다음에 대한 CREATE VIEW 명령신발끈보기(가장 간단한 보기)
관계 신발끈과 항목을 생성합니다.pg_rewrite재작성 규칙이 있음을 알려줍니다.
신발끈 관계가 참조될 때마다 적용되어야 하는 것입니다.
쿼리의 범위 테이블에서. 규칙에 규칙 자격이 없습니다.
(나중에 SELECT 규칙이 아닌 규칙에 대해 논의합니다.
현재는 가질 수 없음) INSTEAD입니다. 그 규칙을 참고하세요
자격은 쿼리 자격과 동일하지 않습니다! 규칙의
작업에 쿼리 자격이 있습니다.규칙의 작업은 다음의 복사본인 하나의 쿼리 트리입니다. 뷰 생성 명령의 SELECT 문입니다.
참고:NEW에 대한 두 개의 추가 범위 테이블 항목 및 OLD(역사적 이유로 *NEW* 및 *CURRENT*로 명명됨) 인쇄된 쿼리 트리에서) 다음에서 볼 수 있습니다.pg_rewrite다음 항목에 관심이 없습니다. 선택 규칙.
al_bundy= INSERT INTO 단위 VALUES('cm', 1.0);
    al_bundy= 단위 VALUES('m', 100.0)에 삽입;
    al_bundy= 단위 값에 삽입('인치', 2.54);
    al_bundy= 
    al_bundy= shoe_data 값에 삽입 
    al_bundy- ('sh1', 2, '검은색', 70.0, 90.0, 'cm');
    al_bundy= shoe_data 값에 삽입 
    al_bundy- ('sh2', 0, '검은색', 30.0, 40.0, '인치');
    al_bundy= shoe_data 값에 삽입 
    al_bundy- ('sh3', 4, '갈색', 50.0, 65.0, 'cm');
    al_bundy= shoe_data 값에 삽입 
    al_bundy- ('sh4', 3, '갈색', 40.0, 50.0, '인치');
    al_bundy= 
    al_bundy= 신발끈_데이터 값에 삽입 
    al_bundy- ('sl1', 5, '검정색', 80.0, 'cm');
    al_bundy= 신발끈_데이터 값에 삽입 
    al_bundy- ('sl2', 6, '검정색', 100.0, 'cm');
    al_bundy= 신발끈_데이터 값에 삽입 
    al_bundy- ('sl3', 0, '검은색', 35.0 , '인치');
    al_bundy= 신발끈_데이터 값에 삽입 
    al_bundy- ('sl4', 8, '검은색', 40.0 , '인치');
    al_bundy= 신발끈_데이터 값에 삽입 
    al_bundy- ('sl5', 4, '갈색', 1.0 , 'm');
    al_bundy= 신발끈_데이터 값에 삽입 
    al_bundy- ('sl6', 0, '갈색', 0.9 , 'm');
    al_bundy= 신발끈_데이터 값에 삽입 
    al_bundy- ('sl7', 7, '갈색', 60 , 'cm');
    al_bundy= 신발끈_데이터 값에 삽입 
    al_bundy- ('sl8', 1, '갈색', 40 , '인치');
    al_bundy= 
    al_bundy= SELECT * 신발끈에서;
    sl_name |sl_avail|sl_color |sl_len|sl_unit |sl_len_cm
    ----------+---------+----------+------+---------+---------
    sl1 |       5|검은색 |    80|cm |       80
    sl2 |       6|검은색 |   100|cm |      100
    sl7 |       7|갈색 |    60|cm |       60
    sl3 |       0|검은색 |    35|인치 |     88.9
    sl4 |       8|검은색 |    40|인치 |    101.6
    sl8 |       1|갈색 |    40|인치 |    101.6
    sl5 |       4|갈색 |     1|분 |      100
    sl6 |       0|갈색 |   0.9|분 |       90
    (8행)이것은 우리의 뷰에 대해 SELECT Al이 할 수 있는 가장 간단한 방법입니다.
이것은 보기 규칙의 기본을 설명하기 위한 것입니다. 'SELECT * FROM
신발끈'은 파서에 의해 해석되어 파싱 트리를 생성했습니다.SELECT 신발끈.sl_name, 신발끈.sl_avail,
           신발끈.sl_color, 신발끈.sl_len,
           신발끈.sl_unit, 신발끈.sl_len_cm
      신발끈 신발끈에서;그리고 이것은 스포츠 토토 결과 시스템에 제공됩니다. 룰 시스템 워크
범위 테이블을 통해 규칙이 있는지 확인합니다.pg_rewrite모든 관계에 대해. 언제
    에 대한 범위 테이블 항목을 처리하는 중입니다.신발끈(지금까지 유일한 것) 그것은
    구문 분석 트리를 사용하여 '_RETshoelace' 스포츠 토토 결과
    SELECT s.sl_name, s.sl_avail,
           s.sl_color, s.sl_len, s.sl_unit,
           float8mul(s.sl_len, u.un_fact) AS sl_len_cm
      FROM 신발끈 *OLD*, 신발끈 *NEW*,
           신발끈_데이터 s, 단위 u
     WHERE bpchareq(s.sl_unit, u.un_name);
파서가 계산을 변경했으며
적절한 기능에 대한 호출에 대한 자격을 부여합니다. 하지만 사실
아무것도 바뀌지 않습니다.뷰를 확장하기 위해 리라이터는 단순히 하위 선택을 생성합니다 규칙의 작업 구문 분석 트리를 포함하는 rangetable 항목 이 범위 테이블 항목을 원래 항목으로 대체합니다. 뷰를 참고했습니다. 결과적으로 다시 작성된 구문 분석 트리는 다음과 같습니다. Al이 입력한 것과 거의 같습니다
SELECT 신발끈.sl_name, 신발끈.sl_avail,
           신발끈.sl_color, 신발끈.sl_len,
           신발끈.sl_unit, 신발끈.sl_len_cm
      FROM(SELECT s.sl_name,
                   s.sl_avail,
                   s.sl_color,
                   s.sl_len,
                   s.sl_유닛,
                   s.sl_len * u.un_fact AS sl_len_cm
              신발끈_데이터 s, 단위 u에서
             WHERE s.sl_unit = u.un_name) 신발끈;그러나 한 가지 차이점이 있습니다: 하위 쿼리의 범위 테이블
신발끈 *기존*, 신발끈 *새* 두 개의 추가 항목이 있습니다. 이 항목
쿼리에 직접 참여하지 마세요.
하위 쿼리의 조인 트리 또는 대상 목록에서 참조됩니다. 재작성자
이를 사용하여 액세스 권한 확인 정보를 저장합니다.
원래는
보다. 이러한 방식으로 실행자는 사용자가
보기에 액세스할 수 있는 적절한 권한이 없더라도
다시 작성된 쿼리에서 뷰를 직접 사용합니다.그것이 첫 번째로 적용된 규칙이었습니다. 스포츠 토토 결과 시스템은 상단의 나머지 범위 테이블 항목을 계속 확인하세요. 쿼리(이 예에서는 더 이상 없음)가 수행됩니다. 추가된 하위 쿼리의 범위 테이블 항목을 재귀적으로 확인합니다. 그 중 뷰를 참조하는 것이 있는지 확인하세요. (근데 확장은 안됨 *OLD* 또는 *NEW* --- 그렇지 않으면 무한 재귀가 발생합니다!) 이 예에서는 shoelace_data에 대한 재작성 규칙이 없습니다. 단위이므로 다시 작성이 완료되었으며 위가 최종입니다. 결과는 기획자에게 전달됩니다.
이제 우리는 블루스 브라더스가 겪고 있는 문제에 직면해 있습니다. 그의 가게에 나타나 새 신발을 사고 싶어 합니다. 블루스 브라더스는, 같은 신발을 신고 싶어해요. 그리고 그들은 바로 신고 싶어서 신발끈도 필요해요.
Al은 현재 매장에 어떤 신발이 있는지 알아야 합니다. 일치하는 신발끈(색상 및 크기)이 있고 총 금액이 어디에 있는지 정확히 일치하는 쌍의 수가 2보다 크거나 같습니다. 우리 그에게 무엇을 해야 하는지 가르쳐 주고 그는 데이터베이스에 질문합니다.
al_bundy= SELECT * FROM shoe_ready WHERE total_avail = 2;
    신발 이름 |sh_avail|sl_name |sl_avail|total_avail
    ---------+---------+----------+---------+-----------
    sh1 |       2|sl1 |       5|          2
    sh3 |       4|sl7 |       7|          4
    (2행)Al은 신발 전문가이므로 그는 sh1 유형의 신발만
맞을 것 같아요(신발끈 sl7은 갈색이고 신발은 갈색이 필요해요)
신발끈은 블루스 브라더스가 신는 신발이 아닙니다.이번 파서의 출력은 파서 트리입니다.
SELECT shoe_ready.shoename, shoe_ready.sh_avail,
           shoe_ready.sl_name, shoe_ready.sl_avail,
           shoe_ready.total_avail
      신발 준비 신발 준비에서
     어디 int4ge(shoe_ready.total_avail, 2);적용되는 첫 번째 규칙은 다음에 대한 규칙이 될 것입니다.shoe_ready뷰 결과는 파싱 트리가 됩니다SELECT shoe_ready.shoename, shoe_ready.sh_avail,
           shoe_ready.sl_name, shoe_ready.sl_avail,
           shoe_ready.total_avail
      FROM (SELECT rsh.shoename,
                   rsh.sh_avail,
                   rsl.sl_이름,
                   rsl.sl_avail,
                   min(rsh.sh_avail, rsl.sl_avail) AS total_avail
              FROM 신발 rsh, 신발끈 rsl
             여기서 rsl.sl_color = rsh.slcolor
               그리고 rsl.sl_len_cm = rsh.slminlen_cm
               AND rsl.sl_len_cm <= rsh.slmaxlen_cm) shoe_ready
     어디 int4ge(shoe_ready.total_avail, 2);마찬가지로 다음 규칙은신발그리고신발끈으로 대체됩니다.
3레벨 최종으로 이어지는 하위 쿼리의 범위 테이블
쿼리트리:선택 shoe_ready.shoename, shoe_ready.sh_avail,
           shoe_ready.sl_name, shoe_ready.sl_avail,
           shoe_ready.total_avail
      FROM (SELECT rsh.shoename,
                   rsh.sh_avail,
                   rsl.sl_이름,
                   rsl.sl_avail,
                   min(rsh.sh_avail, rsl.sl_avail) AS total_avail
              FROM (SELECT sh.신발이름,
                           sh.sh_avail,
                           sh.slcolor,
                           sh.slminlen,
                           sh.slminlen * un.un_fact AS slminlen_cm,
                           sh.slmaxlen,
                           sh.slmaxlen * un.un_fact AS slmaxlen_cm,
                           sh.slunit
                      shoe_data sh, 단위 un에서
                     sh.slunit = un.un_name) rsh,
                   (s.sl_name 선택,
                           s.sl_avail,
                           s.sl_color,
                           s.sl_len,
                           s.sl_유닛,
                           s.sl_len * u.un_fact AS sl_len_cm
                      신발끈_데이터 s, 단위 u에서
                     어디서 s.sl_unit = u.un_name) rsl
             여기서 rsl.sl_color = rsh.slcolor
               그리고 rsl.sl_len_cm = rsh.slminlen_cm
               AND rsl.sl_len_cm <= rsh.slmaxlen_cm) shoe_ready
     어디 int4ge(shoe_ready.total_avail, 2);계획자는 이 트리를 축소하여
2단계 쿼리 트리: 맨 아래 선택 항목이 "풀업"됩니다.
처리할 필요가 없으므로 중간 선택으로 넣습니다.
갈라져. 그러나 중간 선택은
상단에는 집계 함수가 포함되어 있기 때문입니다. 우리가 그걸 뽑아내면
이는 최상위 선택 항목의 동작을 변경하지만 우리는 이를 변경하지 않습니다.
원하다. 그러나 쿼리 트리를 축소하는 것은 다음과 같은 최적화입니다.
재작성 시스템은 걱정할 필요가 없습니다.참고:현재 재귀 중지가 없습니다. 스포츠 토토 결과 시스템의 보기 규칙 메커니즘( 다른 종류의 규칙). 별로 아프지 않으니까. 이것을 무한 루프에 빠뜨리는 유일한 방법은 백엔드가 메모리 제한에 도달할 때까지)을 생성하는 것입니다. 테이블을 만든 다음 CREATE를 사용하여 직접 뷰 규칙을 설정합니다. RULE 방식으로 하나는 다른 것 중에서 선택합니다. 중 하나를 선택합니다. CREATE라면 이런 일은 절대 일어날 수 없습니다 VIEW가 사용되는 이유는 첫 번째 CREATE VIEW에 대해 두 번째 관계가 존재하지 않으므로 첫 번째 뷰는 두 번째에서 선택하세요.
파싱 트리의 두 가지 세부 사항은 위의 보기 규칙에 대한 설명입니다. 이는 명령 유형과 결과관계. 실제로 뷰 규칙에는 이것이 필요하지 않습니다. 정보.
분석 트리 사이에는 단지 몇 가지 차이점이 있습니다. SELECT와 다른 명령에 대한 것입니다. 분명히 그들은 또 다른 명령 유형과 이번에는 결과 관계가 다음을 가리킵니다. 결과가 이동해야 하는 범위 테이블 항목입니다. 모든 것 그 밖의 것은 완전히 동일합니다. 따라서 두 개의 테이블 t1과 t2가 있습니다. 속성 a와 b를 사용하여 두 속성에 대한 구문 분석 트리 진술
t1.a = t2.a인 경우 t1, t2에서 t2.b를 선택하세요.
    업데이트 t1 SET b = t2.b WHERE t1.a = t2.a;거의 동일합니다.범위 테이블에는 테이블 t1 및 t2.
대상 목록에는 다음을 가리키는 하나의 변수가 포함되어 있습니다. 테이블 t2에 대한 범위 테이블 항목의 속성 b.
한정 표현식은 속성을 비교합니다. 두 범위 모두 동일합니다.
조인트트리는 t1과 t2 사이의 간단한 조인을 보여줍니다.
t1 설정 업데이트 a = t1.a, b = t2.b WHERE t1.a = t2.a;따라서 조인을 실행하는 실행자는 정확히 다음을 생성합니다. a와 동일한 결과 세트
t1.a = t2.a인 경우 t1, t2에서 t1.a, t2.b를 선택하세요.그렇습니다. 그런데 UPDATE에 약간의 문제가 있습니다. 그만큼 실행자는 자신이 수행하는 조인의 결과가 무엇인지 신경 쓰지 않습니다. 을 의미합니다. 단지 행의 결과 집합을 생성합니다. 그만큼 하나는 SELECT 명령이고 다른 하나는 UPDATE라는 차이점이 있습니다. 실행자의 호출자에서 처리됩니다. 발신자는 아직 알고 있어요 (파싱 트리를 보면서) 이것이 업데이트이고 그는 알고 있습니다. 이 결과는 테이블 t1에 들어가야 합니다. 그러나 어느 행 새 행으로 교체해야 합니까?
이 문제를 해결하기 위해 다른 항목이 UPDATE(및 DELETE) 문의 대상 목록: 현재 튜플 ID(ctid). 이는 다음을 포함하는 시스템 속성입니다. 행에 대한 파일 블록 번호 및 블록 내 위치입니다. 테이블을 알면 ctid를 사용하여 업데이트할 원래 t1 행. ctid를 추가한 후 targetlist, 쿼리는 실제로 다음과 같습니다.
t1.a = t2.a인 경우 t1, t2에서 t1.a, t2.b, t1.ctid를 선택하세요.이제 또 다른 세부사항포스트그레무대에 들어갑니다. 지금 이 순간, 테이블 행은 덮어쓰지 않으므로 ABORT TRANSACTION이 빠른. UPDATE에서는 새 결과 행이 테이블에 삽입됩니다. (ctid를 제거한 후) 및 ctid가 있는 행의 튜플 헤더에 cmax를 가리키고 xmax 항목은 현재 명령으로 설정됩니다. 카운터 및 현재 거래 ID. 따라서 이전 행은 숨겨지고 트랜잭션이 커밋된 후 진공청소기가 실제로 움직일 수 있습니다. 밖으로.
이 모든 것을 알고 있으면 우리는 보기 스포츠 토토 결과을 간단히 적용할 수 있습니다. 모든 명령과 완전히 동일한 방식입니다. 없다 차이점.
위는 스포츠 토토 결과 시스템이 보기를 통합하는 방법을 보여줍니다. 원래 구문 분석 트리에 정의합니다. 두 번째 예에서는 하나의 뷰에서 간단한 SELECT를 수행하면 최종 구문 분석 트리가 생성됩니다. 4개 테이블의 조인(단위는 서로 다른 테이블로 두 번 사용됨) 이름).
스포츠 토토 결과 시스템으로 보기를 구현하면 다음과 같은 이점이 있습니다. 플래너는 어떤 테이블에 대한 모든 정보를 가지고 있는지 스캔하고 이들 사이의 관계를 스캔해야 합니다. 테이블과 뷰의 제한적 자격 게다가 원래 쿼리의 자격을 하나의 단일 항목으로 파스트리. 그리고 이것은 원래의 상황이 여전히 그렇습니다. 쿼리는 이미 뷰에 대한 조인입니다. 이제 기획자는 쿼리를 실행하는 데 가장 적합한 경로를 결정합니다. 더 기획자가 정보를 갖고 있을수록 이 결정은 더 좋을 수 있습니다. 그리고 구현된 스포츠 토토 결과 시스템은포스트그레이것이 전부임을 보장합니다 현재까지 쿼리에 대해 사용 가능한 정보입니다.
뷰가 대상 관계로 명명되면 어떻게 됩니까? INSERT, UPDATE 또는 DELETE? 교체 작업을 마친 후 위에서 설명한 대로 쿼리 트리가 있습니다. resultrelation은 하위 쿼리 범위 테이블 항목을 가리킵니다. 이것은 작동하지 않으므로 리라이터는 작동하지 않는 것을 확인하면 오류를 발생시킵니다. 그런 걸 만들어냈어.
이를 변경하기 위해 우리는 행동을 수정하는 규칙을 정의할 수 있습니다 SELECT가 아닌 쿼리. 이것이 다음의 주제이다 부분.