이 페이지는 기계 번역되었습니다. 영어 원본을 읽어보세요. English

IBSurgeon 라이브러리

뷰 (InterBase 및 Firebird)

Alexey Kovyazin, last update 13-April-2012

SQL 언어에 익숙한 사람들은 이 주제에 대한 자세한 설명이 필요하지 않지만, 설명의 순서를 유지하기 위해 뷰에 대한 간략한 정의를 소개하겠습니다.

VIEW는 일반 테이블에 대한 질의를 기반으로 생성된 가상 테이블입니다. 뷰는 서버에 저장되고 뷰를 참조할 때마다 실행되는 질의로 구현됩니다.

뷰 사용의 다양한 변형을 고려해 보겠습니다. 뷰는 데이터 구조의 수준을 생성하여 데이터 저장 구현을 해당 유형과 분리할 수 있게 합니다. 예를 들어, 여러 테이블에서 데이터를 선택하는 뷰를 만들 수 있습니다. 클라이언트가 기본 테이블을 직접 참조하는 대신 이 뷰를 사용한다면, 데이터베이스 개발자는 뷰의 기반이 되는 질의를 변경하거나 수정(예: 최적화)할 수 있으며, 클라이언트는 아무것도 인지하지 못할 것입니다 - 그에게는 동일한 뷰로 보일 것입니다. 뷰는 데이터 저장 구현을 사용자로부터 격리시킨다는 사실 외에도 데이터를 더 편리하고 간단한 방식으로 구성할 수 있게 합니다. 데이터 구조의 “단순화” 문제는 데이터베이스의 테이블 수가 충분히 많아지고 테이블 간의 관계가 복잡해질 때 발생합니다. 뷰는 특정 데이터베이스 클라이언트에게 필요하지 않은(또는 필요한) 데이터의 일부를 제거(또는 반대로 추가)할 수 있게 합니다.

또한 뷰는 InterBase 데이터베이스에서 보안을 더 간단하게 구성할 수 있게 합니다. 일부 사용자는 뷰의 데이터를 읽거나 업데이트할 권한만 가질 수 있으며, 뷰의 기반이 되는 테이블에 대한 권한(또는 존재조차)은 없을 수 있습니다! InterBase의 보안에 대한 자세한 내용은 “InterBase의 보안: 사용자, 기능 및 권한”(4부) 장을 참조하십시오.

뷰 작업을 위한 DDL 구문

이제 DDL(Data Definition Language - SQL 하위 집합, 용어집 참조)로 정의된 뷰 생성 및 삭제 명령을 고려하겠습니다. InterBase에서 뷰를 생성하려면 다음 구문의 문장을 사용해야 합니다:

CREATE VIEW viewname [(view_column[, view_column…])] AS [WITH CHECK OPTION]; 여기서 viewname은 데이터베이스 내에서 고유해야 하는 뷰의 이름이며, 그 다음에는 뷰에 포함된 필드 이름의 그룹(항상 필수는 아님)이 옵니다: [(view_column [, view_column …])]. 뷰에 포함된 데이터를 선택하는 문장을 정의하는 것이 필수적입니다. 선택적 매개변수 WITH CHECK OPTION에 대해서는 “수정된 뷰” 부분에서 나중에 논의하겠습니다.

뷰를 변경하려면 뷰를 다시 생성해야 합니다, 즉 삭제하고 다시 만들어야 합니다. 뷰를 삭제할 때는 모든 종속 객체(트리거, 저장 프로시저 및 기타 뷰)도 삭제해야 합니다. 이것은 뷰 작업의 주요 불편 사항 중 하나입니다: 뷰를 사용하는 객체 트리를 다시 생성해야 하는 필요성(이를 더 쉽게 해주는 유틸리티가 있습니다, 예: IBAlterView, “관리자 및 InterBase 디자이너 도구” 응용 프로그램 참조). 뷰를 삭제하려면 다음 DDL 명령을 사용해야 합니다:

DROP VIEW viewname;

뷰의 예

다음은 간단한 뷰의 예입니다:

CREATE VIEW MyView AS SELECT NAME, PRICE_1 FROM Table_example;

이 예에서는 “테이블. 기본 키 및 생성기” 장에서 고려한 Table_example 테이블에 대한 질의를 기반으로 뷰를 생성합니다. 이 경우 뷰는 Table_example 테이블에서 조건 없이 선택되는 NAME 및 PRICE_1의 두 필드로 구성됩니다, 즉 MyView 뷰의 레코드 수는 Table_example의 레코드 수와 같습니다. 그러나 뷰가 항상 이렇게 간단한 것은 아닙니다. 여러 테이블의 데이터와 다른 뷰를 기반으로 할 수도 있습니다. 또한 뷰는 다양한 표현식(집계 함수 포함)을 기반으로 수신된 데이터를 포함할 수 있습니다. 이 뷰 응용 프로그램의 사용을 더 자세히 고려하기 위해 일대다 관계(종종 마스터-디테일 관계라고 함)로 연결된 두 개의 테이블을 만들어 보겠습니다. 다음은 이러한 테이블을 생성하는 DDL 스크립트입니다:

/\* Table: WISEMEN */

CREATE TABLE WISEMEN ( ID_WISEMAN INTEGER NOT NULL, WISEMAN_NAME VARCHAR(80));

/\* Primary keys definition */

ALTER TABLE WISEMEN ADD CONSTRAINT PK_WISEMEN PRIMARY KEY (ID_WISEMAN);

/\* Table: WISEBOOK */

CREATE TABLE WISEBOOK ( ID_BOOK INTEGER NOT NULL, ID_WISEMAN INTEGER, BOOK VARCHAR(80));

/\* Primary keys definition */

ALTER TABLE WISEBOOK ADD CONSTRAINT PK_WISEBOOK PRIMARY KEY (ID_BOOK);

/\* Foreign keys definition */

ALTER TABLE WISEBOOK ADD CONSTRAINT FK_WISEBOOK FOREIGN KEY (ID_WISEMAN) REFERENCES WISEMEN (ID_WISEMAN);

따라서 FOREIGN KEY 제약 조건인 외래 키를 사용하여 마스터-디테일 관계로 연결된 WISEMEN 및 WISEBOOK의 두 테이블을 만들었습니다. 이 테이블들이 위대한 중국 현인들과 그들의 저작에 대한 정보를 저장한다고 가정하겠습니다. 이제 이러한 테이블을 기반으로 몇 가지 뷰를 만들 수 있습니다. 예를 들어, 각 현인이 가진 저작 수를 보여주는 뷰를 만들어 보겠습니다:

CREATE VIEW WiseBookCount (WISEMAN, HOW_WISEBOOKS) AS SELECT M.WISEMAN_NAME, COUNT(B.BOOK) FROM WISEMEN M, WISEBOOK B WHERE (M.ID_WISEMAN = B.ID_WISEMAN) GROUP BY M.WISEMAN_NAME

COUNT(), SUM(), MAX() 등과 같은 집계 함수와 같은 계산된 표현식을 사용할 때는 뷰 필드의 명확한 이름을 사용하는 것이 필수적입니다, 즉 질의에서 반환된 모든 필드에 이름을 지정해야 합니다. 이 예에서 볼 수 있듯이 이러한 이름은 질의 필드 이름과 반드시 일치할 필요는 없지만, 그 수는 질의에서 반환된 필드 수와 일치해야 합니다. 질의에서 반환된 필드가 뷰의 어떤 필드에 해당하는지 정의는 일련 번호로 이루어집니다 - 첫 번째 질의 필드는 뷰의 첫 번째 필드에 반영되고, 두 번째는 두 번째에 반영되는 식입니다.

그리고 어떤 현인이 가장 많은 책을 썼는지 알고 싶다면 어떻게 할까요? 뷰의 기반이 되는 질의에 정렬 표현식 ORDER BY를 추가해 보겠습니다. 그러나 이 시도는 실패할 것입니다: 뷰에서 ORDER BY 정렬 사용은 허용되지 않으며 ORDER BY가 포함된 질의로 뷰를 생성하려고 하면 오류가 발생합니다. 뷰에서 반환된 결과를 정렬하려면 클라이언트 측에서 수행해야 합니다:

SELECT * FROM WiseBookCount ORDER BY HOW_WISEBOOKS

이 SQL 질의를 실행하면 원하는 결과가 나옵니다. 뷰에서 ORDER BY 표현식 사용에 대한 제약 외에도 저장 프로시저 실행 결과로 수신된 데이터 집합을 데이터 소스로 사용할 수도 없습니다(아래 “저장 프로시저” 장 참조).

아마도 뷰 응용 프로그램을 보여주는 예를 하나 더 드는 것이 좋을 것입니다. 이름이 “K"로 시작하는 현인 목록을 출력해야 한다고 가정하겠습니다. 이 경우 조건이 있는 뷰를 사용합니다:

CREATE VIEW WiseMen2 (WISEMAN) AS SELECT M.WISEMAN_NAME FROM WISEMEN M WHERE M.WISEMAN_NAME LIKE ‘K%’

따라서 특정 조건에 따라 데이터베이스에서 데이터를 선택하여 지속적으로 업데이트되는 데이터 공급자 역할을 하는 뷰를 쉽게 만들 수 있습니다.

수정된 뷰

위에서 수정된 데이터 뷰를 생성할 수 있는 기능이 있다고 언급했습니다. 실제로 그렇습니다 - 뷰에서 데이터를 읽을 수 있을 뿐만 아니라 수정할 수도 있습니다!

뷰를 수정 가능하게 만드는 두 가지 방법이 있습니다. 첫 번째 방법은 뷰가 단일 테이블(또는 다른 수정된 뷰)을 기반으로 생성되고, 해당 테이블의 모든 열이 NULL 존재를 허용해야 하는 경우에 적용됩니다. 따라서 뷰의 기반이 되는 질의는 하위 질의, 집계 함수, UDF, 저장 프로시저, DISTINCT 및 HAVING 문을 포함할 수 없습니다. 이러한 모든 조건이 충족되면 뷰는 자동으로 수정 가능해집니다, 즉 DELETE, INSERT 및 UPDATE 질의를 실행할 수 있으며, 이는 원본 테이블의 데이터를 변경합니다.

조건 목록은 상당히 방대하며 이러한 수정된 뷰의 응용 프로그램을 크게 제한하므로 거의 사용되지 않습니다.

수정된 뷰가 위에 나열된 조건 중 하나라도 위반하도록 만들기 위해 트리거 메커니즘이 적용됩니다. 트리거에 대한 자세한 내용은 “트리거” 장(1부)을 참조하십시오. 지금은 뷰에서 데이터 변경을 구성하는 일반적인 원칙만 고려하겠습니다.

트리거를 사용하여 업데이트 가능한 뷰를 구현하려면 다음을 수행해야 합니다. 주어진 뷰에 대해 BEFORE DELETE, BEFORE UPDATE 및 BEFORE INSERT 이벤트에 대한 트리거 3개를 생성합니다. 이러한 트리거에서 삭제, 업데이트 및 삽입 시 데이터로 무엇을 해야 하는지 설명합니다.

그런 다음 수정 쿼리(DELETE, INSERT 또는 UPDATE)에서 주어진 뷰를 사용해야 합니다. InterBase가 이 쿼리를 받으면 주어진 뷰에 적절한 트리거, 즉 BEFORE DELETE/INSERT/UPDATE가 있는지 확인합니다. 실행 가능한 작업에 대한 트리거가 있으면 InterBase는 뷰의 기반이 되는 테이블의 실제 데이터를 수정하기 위해 이를 호출하고(다른 데이터일 수도 있음 - 이러한 트리거에는 텍스트 제약이 없음), 그런 다음 수정이 수행된 문자열(또는 문자열들)을 다시 읽습니다.

따라서 뷰에서 복잡한 데이터 업데이트 체인을 구현할 수 있는 기능이 있습니다.

WITH CHECK OPTION 옵션은 뷰 생성 구문 설명에서 언급되었습니다. 수정된 뷰를 생성할 때 이 옵션이 설정되면 이 뷰에 삽입되거나 변경된 모든 데이터 문자열은 뷰에 포함되는 조건에 대해 검사됩니다. 이는 다음과 같이 설명할 수 있습니다. 사용자가 삽입한 새 레코드나 기존 레코드 업데이트 결과로 얻은 레코드가 VIEW의 데이터 공급자인 쿼리의 조건을 충족하지 않으면 이 레코드의 삽입이 취소되고 오류가 발생합니다.

결론

뷰 생성 및 사용의 단순함에도 불구하고 뷰는 데이터베이스의 데이터 구성을 개선하는 훌륭한 기능을 제공하며 데이터 구성의 계층 구조를 만들 수 있게 해줍니다.

일부 데이터베이스 애플리케이션 설계자는 작업에서 뷰를 매우 자주 사용하는 반면, 다른 설계자는 뷰 수정의 복잡성과 데이터베이스 스키마를 가능한 한 단순하고 효율적으로 유지하려는 경향을 이유로 뷰 사용을 피합니다. 작업에서 뷰를 어떻게 적용할지는 사용자의 몫입니다. 가장 중요한 점은 뷰와 같은 강력한 도구의 존재를 기억하고 이를 사용하는 방법을 아는 것입니다.