39.2. 보기 및 규칙 시스템#

views inPostgreSQL는 규칙 시스템을 사용하여 구현됩니다. 스포츠 토토 결과는 기본적으로 빈 테이블 (실제 저장소가 없음)입니다.대신 선택규칙. 일반적으로 그 규칙은 이름입니다._return. 그래서스포츠 토토 결과

MyTab에서 MyView스포츠 토토 결과 작성 * From MyTab;

120PostgreSQL : 문서 : 17 : 39.2. 보기 및 규칙 시스템77

테이블 작성 myview (mytab과 같은 열 목록);
myview to myview 대신 규칙 "_return"을 작성하십시오.
    * mytab에서 * 선택;

실제로 쓸 수는 없지만 테이블이 허용되지 않기 때문에ON SELECT규칙.

스포츠 토토 결과에는 다른 종류의가있을 수 있습니다대신규칙, 허용삽입, 업데이트또는삭제기초 스토리지가 부족하더라도스포츠 토토 결과에서 수행해야합니다. 이것은 아래에서 더 자세히 설명합니다.섹션 39.2.4.

39.2.1. 어떻게select규칙 작업#

규칙ON SELECT주어진 명령이 an이더라도 마지막 단계로 모든 쿼리에 적용됩니다.삽입, 업데이트또는삭제. 그리고 그들은 새로운 쿼리 트리를 새로 만들지 않고 제자리에 수정한다는 점에서 다른 명령 유형에 대한 규칙과 다른 의미를 가지고 있습니다. 그래서select규칙이 먼저 설명됩니다.

현재,에는 한 가지 행동 만있을 수 있습니다ON SELECT규칙, 무조건적이어야합니다select행동대신. 이 제한은 일반 사용자를 위해 규칙을 열 수있을 정도로 안전한 규칙을 만들기 위해 필요했으며 제한됩니다ON SELECT견해처럼 행동하는 규칙.

이 장의 예제는 일부 계산을 수행하는 두 가지 조인 뷰와 차례로 사용하는 더 많은 뷰입니다. 두 개의 첫 번째보기 중 하나는에 대한 규칙을 추가하여 나중에 사용자 정의됩니다.삽입, 업데이트삭제최종 결과가 마법 기능을 갖춘 실제 테이블처럼 작동하는스포츠 토토 결과가되도록 작동합니다. 이것은 시작하기에 간단한 예제가 아니며, 이것은 일을 어렵게 만듭니다. 그러나 염두에두고 섞일 수있는 많은 다른 점을 갖지 않고 단계별로 논의 된 모든 점을 다루는 한 가지 예를 갖는 것이 좋습니다.

처음 두 규칙 시스템에 필요한 실제 테이블은 다음과 같습니다.

테이블 SHOE_DATA 만들기 (
    Shoename 텍스트 - 기본 키
    SH_AVAIL INTEGER - 사용 가능한 쌍
    Slcolor Text - 선호하는 떼 색상
    Slminlen Real, - 최소 신발 끈 길이
    Slmaxlen Real, - 최대 떼 길이
    슬루 니트 텍스트 - 길이 단위
);

테이블 생성 shoelace_data (
    SL_NAME 텍스트 - 기본 키
    SL_AVAIL INTEGER - 사용 가능한 수의 쌍
    SL_COLOR 텍스트 - 신발색
    SL_LEN Real, - 신발성 길이
    SL_UNIT 텍스트 - 길이 단위
);

테이블 장치 생성 (
    UN_NAME 텍스트 - 기본 키
    UN_FACT Real- CM으로 변환하는 요소
);

보시다시피, 신발 매장 데이터를 나타냅니다.

보기는 다음과 같이 생성됩니다.

스포츠 토토 결과 신발을 만듭니다
    sh.shoename 선택,
           sh.sh_avail,
           Sh.slcolor,
           Sh.slminlen,
           sh.slminlen * un.un_fact as slminlen_cm,
           sh.slmaxlen,
           sh.slmaxlen * slmaxlen_cm as as slmaxlen * un.un_fact,
           Sh.slunit
      Shoe_data Sh, Un
     여기서 sh.slunit = un.un_name;

Shoelace스포츠 토토 결과를 만듭니다
    s.sl_name 선택,
           s.sl_avail,
           s.sl_color,
           s.sl_len,
           s.sl_unit,
           s.sl_len * u.un_fact as sl_len_cm
      shoelace_data s, unit u
     여기서 s.sl_unit = u.un_name;

Shoe_ready를 View를 만듭니다
    rsh.shoename 선택,
           rsh.sh_avail,
           rsl.sl_name,
           rsl.sl_avail,
           최소한 (rsh.sh_avail, rsl.sl_avail) Total_avail
      Shoe Rsh, Shoelace RSL에서
     여기서 rsl.sl_color = rsh.slcolor
       및 rsl.sl_len_cm = rsh.slminlen_cm
       및 rsl.sl_len_cm <= rsh.slmaxlen_cm;

the스포츠 토토 결과 만들기명령Shoelace스포츠 토토 결과 (우리가 가진 가장 간단한 것)는 관계를 만들 것입니다Shoelace및 입력pg_rewrite관계가 적용될 때마다 적용 해야하는 재 작성 규칙이 있음을 알려줍니다.ShoelaceQuery의 범위 테이블에 참조됩니다. 규칙에는 규칙 자격이 없습니다 (나중에 논의, 비select규칙,select현재 규칙을 가질 수 없음).대신. 규칙 자격은 쿼리 자격과 같지 않습니다. 우리의 규칙의 조치에는 쿼리 자격이 있습니다. 규칙의 동작은의 사본 인 하나의 쿼리 트리입니다.selectView Creation Command의 명령문.

Note

두 개의 추가 범위 테이블 항목NEWandoldpg_rewrite입장에 관심이 없음select규칙.

이제 우리는 포기Unit, Shoe_dataandShoelace_data스포츠 토토 결과에서 간단한 쿼리를 실행합니다.

단위 값에 삽입 ( 'cm', 1.0);
단위 값에 삽입 ( 'm', 100.0);
단위 값에 삽입 ( '인치', 2.54);

Shoe_Data 값 ( 'SH1', 2, 'Black', 70.0, 90.0, 'cm')에 삽입;
Shoe_data 값에 삽입 ( 'sh2', 0, 'black', 30.0, 40.0, 'inch');
Shoe_data 값에 삽입 ( 'sh3', 4, 'brown', 50.0, 65.0, 'cm');
Shoe_data 값에 삽입 ( 'sh4', 3, 'brown', 40.0, 50.0, 'inch');

shoelace_data 값에 삽입 ( 'sl1', 5, 'black', 80.0, 'cm');
shoelace_data 값에 삽입 ( 'sl2', 6, 'black', 100.0, 'cm');
shoelace_data 값에 삽입 ( 'sl3', 0, 'black', 35.0, 'inch');
shoelace_data 값에 삽입 ( 'sl4', 8, 'black', 40.0, 'inch');
shoelace_data 값 ( 'sl5', 4, 'brown', 1.0, 'm')에 삽입;
shoelace_data 값 ( 'sl6', 0, 'brown', 0.9, 'm')에 삽입;
shoelace_data 값에 삽입 ( 'sl7', 7, 'brown', 60, 'cm');
shoelace_data 값에 삽입 ( 'sl8', 1, 'brown', 40, 'inch');

Shoelace에서 *를 선택하십시오.

 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 | m |       100
 SL6 |        0 | 브라운 |    0.9 | m |        90
(8 줄)

이것은 가장 간단합니다select당신은 우리의 견해에 대해 할 수 있으므로이 기회를 통해 관점 규칙의 기본 사항을 설명합니다. 그만큼Select * From Shoelace파서에 의해 해석되고 쿼리 트리를 생성했습니다.

shoelace.sl_name, shoelace.sl_avail 선택을 선택하십시오.
       shoelace.sl_color, shoelace.sl_len,
       shoelace.sl_unit, shoelace.sl_len_cm
  Shoelace Shoelace에서;

그리고 이것은 규칙 시스템에 제공됩니다. 규칙 시스템은 범위 테이블을 통과하고 관계에 대한 규칙이 있는지 확인합니다. 범위 테이블 항목을 처리 할 때Shoelace(지금까지 유일한 사람)는를 찾습니다._return쿼리 트리와 함께 규칙 :

S.SL_NAME, S.SL_AVAIL, SELECT SELECT
       s.sl_color, s.sl_len, s.sl_unit,
       s.sl_len * u.un_fact as sl_len_cm
  Shoelace Old, Shoelace New,
       shoelace_data s, 단위 u
 여기서 s.sl_unit = u.un_name;

보기를 확장하기 위해, 리 작가는 단순히 규칙의 조치 쿼리 트리를 포함하는 서브 쿼리 테이블 항목을 작성 하고이 범위 테이블 항목을 뷰를 참조하는 원래 테이블 항목으로 대체합니다. 결과적으로 다시 작성한 쿼리 트리는 입력 한 것과 거의 동일합니다.

shoelace.sl_name, shoelace.sl_avail 선택을 선택하십시오.
       shoelace.sl_color, shoelace.sl_len,
       shoelace.sl_unit, shoelace.sl_len_cm
  From (select s.sl_name,
               s.sl_avail,
               s.sl_color,
               s.sl_len,
               s.sl_unit,
               s.sl_len * u.un_fact as sl_len_cm
          shoelace_data s, unit u
         여기서 s.sl_unit = u.un_name) shoelace;

그러나 한 가지 차이점이 있습니다. 하위 쿼리의 범위 테이블에는 두 개의 추가 항목이 있습니다.Shoelace oldandShoelace New. 이 항목은 쿼리에 직접 참여하지 않습니다. 하위 쿼리의 조인 트리 또는 대상 목록에서 참조되지 않기 때문입니다. Rewriter는이를 사용하여 원래보기를 참조하는 Range-Table 항목에있는 Access Privilege Check 정보를 저장합니다. 이런 식으로, 집행자는 다시 쓰기 쿼리에 뷰를 직접 사용하지 않더라도 사용자가보기에 액세스 할 수있는 적절한 권한이 있는지 확인합니다..

첫 번째 규칙이 적용되었습니다. 규칙 시스템은 상단 쿼리의 나머지 범위 테이블 항목을 계속 확인할 것이며 (이 예에서는 더 이상 없음) 추가 하위 쿼리의 범위 테이블 항목을 재귀 적으로 확인하여 참조 뷰 중 하나를 확인합니다. (그러나 그것은 확장되지 않을 것입니다old또는NEW- 그렇지 않으면 우리는 무한 재귀가있을 것입니다!)이 예에서는에 대한 재 작성 규칙이 없습니다Shoelace_data또는Unit, 다시 쓰기가 완료되고 위는 플래너에게 주어진 최종 결과입니다.

이제 우리는 현재 상점에 어떤 신발을 신발을 찾는 쿼리를 쓰고 싶습니다.

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 줄)

파서의 출력은 이번에는 쿼리 트리입니다 :

SHOE_READY.SHOENAME, SHOE_READY.SH_AVAIL,
       shoe_ready.sl_name, shoe_ready.sl_avail,
       Shoe_ready.total_avail
  Shoe_ready Shoe_ready에서
 여기서 shoe_ready.total_avail = 2;

첫 번째 규칙은에 대한 첫 번째 규칙입니다.Shoe_ready스포츠 토토 결과와 쿼리 트리가 발생합니다 :

shoe_ready.shoename, 슈 _ready.sh_avail,
       shoe_ready.sl_name, shoe_ready.sl_avail,
       Shoe_ready.total_avail
  From (select rsh.shoename,
               rsh.sh_avail,
               rsl.sl_name,
               rsl.sl_avail,
               최소한 (rsh.sh_avail, rsl.sl_avail) Total_avail
          Shoe Rsh, Shoelace RSL에서
         여기서 rsl.sl_color = rsh.slcolor
           및 rsl.sl_len_cm = rsh.slminlen_cm
           및 rsl.sl_len_cm <= rsh.slmaxlen_cm) shoe_ready
 여기서 shoe_ready.total_avail = 2;

마찬가지로에 대한 규칙신발andShoelace서브 쿼리의 범위 테이블로 대체되어 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_name,
               rsl.sl_avail,
               최소한 (rsh.sh_avail, rsl.sl_avail) Total_avail
          에서 (select sh.shoename,
                       sh.sh_avail,
                       Sh.slcolor,
                       Sh.slminlen,
                       sh.slminlen * un.un_fact as slminlen_cm,
                       sh.slmaxlen,
                       sh.slmaxlen * slmaxlen_cm as as slmaxlen * un.un_fact,
                       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_unit,
                       s.sl_len * u.un_fact as sl_len_cm
                  shoelace_data s, unit u
                 여기서 s.sl_unit = u.un_name) rsl
         여기서 rsl.sl_color = rsh.slcolor
           및 rsl.sl_len_cm = rsh.slminlen_cm
           및 rsl.sl_len_cm <= rsh.slmaxlen_cm) shoe_ready
 여기서 shoe_ready.total_avail 2;

이것은 비효율적으로 보일지 모르지만 플래너는 이것을 단일 레벨 쿼리 트리로 붕괴시킬 것입니다.풀링하위 쿼리, 그리고 수동으로 작성한 것처럼 조인을 계획합니다. 따라서 쿼리 트리를 무너 뜨리는 것은 다시 쓰기 시스템이 스스로 관심을 가질 필요가없는 최적화입니다.

39.2.2. 비에서 규칙보기select진술#

쿼리 트리의 두 가지 세부 사항은 위의보기 규칙에 대한 설명에서 터치하지 않습니다. 이것들은 명령 유형과 결과 관계입니다. 실제로, 명령 유형은보기 규칙에 의해 필요하지 않지만, 결과 관계는 쿼리 재 작성자가 작동하는 방식에 영향을 줄 수 있습니다. 결과 관계가보기 인 경우 특별한주의를 기울여야하기 때문입니다..

쿼리 트리 사이에는 몇 가지 차이가 ​​있습니다select그리고 다른 명령을위한 것입니다. 분명히, 그들은 다른 명령 유형을 가지고 있으며 A 이외의 명령을 가지고 있습니다.select, 결과 관계는 결과가 진행되는 범위 테이블 항목을 가리 킵니다. 다른 모든 것은 절대적으로 동일합니다. 그래서 두 개의 테이블을 가지고T1andT2열이있는aB, 두 진술의 쿼리 트리 :

t1, t2에서 t2.b를 선택하십시오. 여기서 t1.a = t2.a;

T1 Set T2에서 T1 세트 B = T2.B를 업데이트합니다. 여기서 t1.a = t2.a;

거의 동일합니다. 특히:

  • 범위 테이블에는 테이블의 항목이 포함되어 있습니다T1andT2.

  • 대상 목록에는 열을 가리키는 하나의 변수가 포함되어 있습니다B테이블의 범위 테이블 항목T2.

  • 자격 표현식은 열을 비교합니다a평등을위한 레인지 테이블 항목의 두 항목.

  • 가입 트리는 간단한 결합을 보여줍니다T1andT2.

결과는 두 쿼리 트리 모두 비슷한 실행 계획을 초래한다는 것입니다. 둘 다 두 테이블에 결합됩니다.업데이트누락 된 열에서T1플래너에 의해 대상 목록에 추가되며 최종 쿼리 트리는 다음과 같이 읽습니다.

업데이트 T1 설정 a = t1.a, b = t2.b 여기서 t1.a = t2.a;.

따라서 Executor는 Join을 통해 실행됩니다.

t1.a, t2.b에서 t1.a = t2.a;를 선택하십시오.

그러나 약간의 문제가 있습니다업데이트: 가입을하는 집행자 계획의 일부는 조인의 결과가 무엇을 의미하는지 신경 쓰지 않습니다. 결과는 단지 결과 집합을 생성합니다. 하나라는 사실select명령이고 다른 하나는업데이트executor에서 더 높이 처리되어 이것이이라는 것을 알고 있습니다.업데이트, 그리고이 결과가 표로 들어가야한다는 것을 알고 있습니다T1. 그러나 새로운 행으로 교체 해야하는 행 중 어느 행을 대체해야합니까?

이 문제를 해결하려면 다른 항목이 대상 목록에 추가됩니다.업데이트(및 in삭제) 문 : 현재 튜플 ID (CTID).이것은 파일 블록 번호와 행 블록의 위치를 ​​포함하는 시스템 열입니다. 테이블을 알고,ctid원래 행을 검색하는 데 사용할 수 있습니다T1업데이트 될 예정입니다. 추가 후CTID대상 목록으로 쿼리는 실제로 다음과 같습니다.

t1.a, t2.b, t1.ctid t1, t2 여기서 t1.a = t2.a;를 선택하십시오.

이제 또 다른 세부 사항PostgreSQL스테이지에 들어갑니다. 오래된 테이블 행은 덮어 쓰지 않았으며 이것이 이유입니다롤백빠릅니다. 에서업데이트, 새 결과 행이 테이블에 삽입됩니다 (ctid) 그리고 이전 행의 행 헤드러에서CTID가리키는cmaxxmax항목은 현재 명령 카운터 및 현재 트랜잭션 ID로 설정됩니다. 따라서 이전 행은 숨겨져 있으며, 거래가 발생한 후 진공 청소기는 결국 데드 행을 제거 할 수 있습니다..

모든 것을 알고, 우리는 단순히 모든 명령과 동일한 방식으로보기 규칙을 적용 할 수 있습니다. 차이가 없습니다.

39.2.3. 견해의 힘PostgreSQL #

위의 내용은 규칙 시스템이 뷰 정의를 원래 쿼리 트리에 통합하는 방법을 보여줍니다. 두 번째 예에서는 간단한31851_31859One View에서 4 개의 테이블에 가입 한 최종 쿼리 트리를 만들었습니다 (Unit다른 이름으로 두 번 사용되었습니다).

규칙 시스템으로 뷰를 구현하면 플래너가 스캔 해야하는 테이블에 대한 모든 정보 와이 테이블 간의 관계에 대한 모든 정보와 뷰의 제한적인 자격과 하나의 단일 쿼리 트리의 원래 쿼리의 자격을 갖추고 있다는 것입니다. 그리고 이것은 원래의 쿼리가 이미 뷰에 대한 조인 인 경우에도 여전히 상황입니다. 플래너는 쿼리 실행을위한 가장 좋은 경로를 결정해야하며, 플래너의 정보가 많을수록이 결정이 더 좋을 수 있습니다. 그리고 구현 된 규칙 시스템PostgreSQL이것이 해당 시점까지 쿼리에 대한 모든 정보인지 확인합니다.

39.2.4. 보기 업데이트#

스포츠 토토 결과가 AN의 대상 관계로 지명되면 어떻게됩니다삽입, 업데이트, 삭제또는병합? 위에서 설명한 대체를 수행하면 결과 관계가 서브 쿼리 테이블 항목에서 가리키는 쿼리 트리를 제공 할 수 있습니다. 몇 가지 방법이 있습니다PostgreSQL33432_33717

하위 쿼리가 단일 기본 관계에서 선택하고 충분히 간단한 경우, Rewriter는 하위 쿼리를 기본 기본 관계로 자동으로 교체하여삽입, 업데이트, 삭제또는병합는 적절한 방식으로 기본 관계에 적용됩니다. 스포츠 토토 결과단순이것을 위해.자동 업데이트 가능. 자동으로 업데이트 할 수있는 견해 종류에 대한 자세한 정보는 참조하십시오.스포츠 토토 결과 만들기.

또는 사용자가 제공하는 작업이 처리 될 수 있습니다대신스포츠 토토 결과 트리거 (참조트리거 만들기). 이 경우 다시 쓰기는 약간 다르게 작동합니다. 을 위한삽입, Rewriter는스포츠 토토 결과와 전혀 아무것도하지 않으므로 쿼리의 결과 관계로 남겨 둡니다. 을 위한업데이트, 삭제병합old명령이 업데이트, 삭제 또는 병합을 시도하는 행. 따라서 뷰는 정상적으로 확장되지만 또 다른 미지급 범위 테이블 항목은 쿼리에 추가되어 결과 관계로서의 용량의 뷰를 나타냅니다.

현재 발생하는 문제는보기에서 업데이트 할 행을 식별하는 방법입니다. 결과 관계가 테이블 일 때 특별한CTID항목은 대상 목록에 추가되어 업데이트 할 행의 물리적 위치를 식별합니다. 뷰가 없기 때문에 결과 관계가보기 인 경우에는 작동하지 않습니다.CTID, 행에는 실제 물리적 위치가 없기 때문에. 대신,업데이트, 삭제또는병합운영, 특별Wholerow입력은 대상 목록에 추가되어 뷰에서 모든 열을 포함하도록 확장됩니다. 집행자는이 값을 사용하여old로드대신트리거. 이전 및 새 행 값을 기반으로 업데이트 할 내용을 해결하는 것은 방아쇠에 달려 있습니다.

또 다른 가능성은 사용자가 정의하는 것입니다대신대체 조치를 지정하는 규칙삽입, 업데이트삭제보기에 명령. 이 규칙은 명령을 일반적으로 뷰보다는 하나 이상의 테이블을 업데이트하는 명령으로 재 작성됩니다. 그것이의 주제입니다.섹션 39.4. 이것은 작동하지 않을 것입니다병합, 현재 이외의 대상 관계에 대한 규칙을 지원하지 않는select규칙.

37094_37222대신트리거 및 규칙삽입, 업데이트또는삭제, 그러면 규칙이 먼저 평가되고 결과에 따라 트리거가 전혀 사용되지 않을 수 있습니다..

자동 재 작성삽입, 업데이트, 삭제또는병합간단한보기의 쿼리는 항상 마지막으로 시도됩니다. 따라서보기에 규칙이 있거나 트리거가 있으면 자동으로 업데이트 가능한 뷰의 기본 동작을 무시합니다.

없는 경우대신규칙 또는대신뷰를 트리거하고 다시 작성자는 기본 기본 관계에 대한 업데이트로 쿼리를 자동으로 다시 작성할 수 없으며, 집행자가 뷰를 업데이트 할 수 없기 때문에 오류가 발생합니다..

정정 제출

문서에 올바르지 않은 내용이 있으면 일치하지 않습니다. 특정 기능에 대한 귀하의 경험 또는 추가 설명이 필요합니다. 사용이 양식문서 문제를보고하려면