<4D F736F F D20BFC0B6F3C5AC20C8A3C8AFBCBA20B0B3B9DFC0DA20B0A1C0CCB5E539372E646F63>
|
|
- 하라 탁
- 7 years ago
- Views:
Transcription
1 Postgres Plus Advanced Server 8.3 March 14,
2 Oracle 오라클호환성개발자가이드 By EnterpriseDB Corporation Copyright 2008 EnterpriseDB Corporation EnterpriseDB Corporation, 499 Thornall Street, Edison, New Jersey , USA T F E info@enterprisedb.com www. enterprisedb.com 2
3 제 1 장소개 1.1 개정내역 1.2 본설명서작성규칙 1.3 Oracle 호환매개변수구성 edb_redwood_date edb_redwood_strings edb_stmt_level_tx 1.4 본설명서에대한예제제 2 장 SQL 자습서 2.1 자시작하자 예제 새테이블만들기 테이블에행을삽입 테이블에문의 테이블간의결합 집계함수 업데이트 삭제 2.2 고급제반기능 보기 외래키 ROWNUM 가짜열 Synonyms 계층문의제 3 장 SQL 언어 3.1 SQL 구문 어휘구성 식별자와키워드 상수 코멘트 3.2 자료형 숫자데이터형식 문자형식 이진열데이터형식 날짜 / 시간데이터형식 논리값데이터형식 3.3 SQL 명령 ALTER INDEX ALTER ROLE ALTER SEQUENCE ALTER SESSION ALTER TABLE ALTER TABLESPACE ALTER USER COMMENT COMMIT CREATE DATABASE CREATE DATABASE LINK CREATE DIRECTORY 목차 3
4 CREATE FUNCTION CREATE INDEX CREATE PACKAGE CREATE PACKAGE BODY CREATE PROCEDURE CREATE PUBLIC SYNONYM CREATE ROLE CREATE SCHEMA CREATE SEQUENCE CREATE TABLE CREATE TABLE AS CREATE TRIGGER CREATE USER CREATE VIEW DELETE DROP DATABASE LINK DROP FUNCTION DROP INDEX DROP PACKAGE DROP PROCEDURE DROP PUBLIC SYNONYM DROP ROLE DROP SEQUENCE DROP TABLE DROP TABLESPACE DROP TRIGGER DROP USER DROP VIEW GRANT INSERT LOCK REVOKE ROLLBACK ROLLBACK TO SAVEPOINT SAVEPOINT SELECT SET CONSTRAINTS SET ROLE SET TRANSACTION TRUNCATE UPDATE 3.4 최적화 기본조각모음모드 액세스방법팁 조인 / 관계팁 글로벌팁 충돌팁 3.5 함수와연산자 논리연산자 비교연산자 수학함수와연산자 4
5 3.5.4 문자열함수와연산자 LIKE 식에의한패턴매칭 데이터형식서식함수 날짜 / 시간함수와연산자 시퀀스조작함수 조건문 집계함수 하부문의표현 제 4 장스토리지프로시저언어 4.1 SPL 의기본요소 문자집합 대소문자구분 식별자 한정자 상수 4.2 SPL 프로그램 SPL 블록구조 익명블록 프로시저개요 기능설명 프로시저와함수인자 프로그램의보안 4.3 변수선언 변수선언 변수선언에서 % TYPE 사용 레코드선언 % ROWTYPE 사용 사용자정의레코드형과레코드변수 4.4 기본적인문장 NULL 지정 SELECT INTO INSERT UPDATE DELETE RETURNING INTO 절사용법 결과상태포획 4.5 제어구조 조건부 CASE 식 CASE 문장 간단한루프 오류를포착 응용프로그램오류발생 4.6 동적 SQL 4.7 정적커서 커서변수선언 커서열기 커서에서행을가져오기 커서근접 커서에서 % ROWTYPE 이용 5
6 4.7.6 커서속성 커서 FOR 루프 변수화커서 4.8 REF 커서와커서변수 REF 커서개요 커서변수선언 커서변수오픈 커서변수에서행 커서변수근접 사용제한 예제 REF 커서로동적쿼리 4.9 소장품 연관배열 수집방법 FORALL 문장사용 BULK COLLECT 항목사용 4.10 오류메시지 제 5 장트리거 5.1 개요 5.2 트리거유형 5.3 트리거발생 5.4 트리거변수 5.5 트랜잭션과예외처리 5.6 트리거예제 문수준이전트리거 문수준후에트리거 행 - 레벨전트리거 행 - 레벨이후트리거제 6 장패키지 6.1 패키지구성요소 패키지사양구문 패키지본문의구문 6.2 패키지구성 패키지생성사용 패키지본문생성 6.3 패키지참조 6.4 사용자정의유형포장사양 6.5 패키지제거제 7 장통합패키지 7.1 DBMS_ALERT REGISTER REMOVE REMOVEALL SIGNAL WAITANY WAITONE 종합적인예제 7.2 DBMS_OUTPUT DISABLE 6
7 7.2.2 ENABLE GET_LINE NEW_LINE PUT PUT_LINE SERVEROUTPUT 7.3 DBMS_PIPE CREATE_PIPE NEXT_ITEM_TYPE PACK_MESSAGE PURGE RECEIVE_MESSAGE REMOVE_PIPE RESET_BUFFER SEND_MESSAGE UNIQUE_SESSION_NAME UNPACK_MESSAGE 합성보기 7.4 UTL_FILE FCLOSE FCLOSE_ALL FCOPY FFLUSH FOPEN FREMOVE FRENAME GET_LINE IS_OPEN NEW_LINE PUT PUT_LINE PUTF 제 8 장오픈클라이언트라이브러리제 9 장 Oracle 목록뷰 9.1 ALL_OBJECTS 9.2 ALL_SOURCE 9.3 ALL_SYNONYMS 9.4 ALL_TAB_COLUMNS 9.5 ALL_TABLES 9.6 ALL_USERS 9.7 ALL_VIEW_COLUMNS 9.8 ALL_VIEWS 9.9 DBA_ROLE_PRIVS 9.10 DBA_ROLES 9.11 USER_OBJECTS 9.12 USER_SOURCE 9.13 USER_SYNONYMS 9.14 USER_TAB_COLUMNS 9.15 USER_TABLES 9.16 USER_VIEW_COLUMNS 9.17 USER_VIEWS 7
8 제 10 장유틸리티 10.1 EDB* 플러스 EDB* 플러스시작 명령요약 10.3 EDB * 로더 EDB 의 * 기능로더 8.3 기능이릴리스에서지원되지않음 : EDB * 부터로더는커맨드라인에서 EDB * 로더예 노트 10.3 동적런타임계장 활성화 DRI 카탈로그조회 포함사용 DRITA 스크립트 개인전이벤트설명 조정권고 추가기능과테이블 8.3 릴리스에대한추가 11 부록 11.1 감사 8
9 제 1 장소개 이가이드에서는 Postgres Plus Advanced Server 의오라클호환성사양에대한설명을합니다. 오라클호환성은응용프로그램의소스코드를거의또는전혀변경하지않고응용프로그램을 Postgres Plus Advanced Server 환경과마찬가지로오라클환경에서사용할수있음을의미합니다. Postgres Plus Advanced Server, PostgreSQL 또는오라클데이터베이스응용프로그램을개발할수있는다양한기능을가지고있습니다. 이설명서는 Oracle 호환성기능에만초점을맞추고있기때문에 Postgres Plus Advanced Server 의모든기능에대해배우고싶은분은, "Postgres Plus Advanced Server Advanced Server documentation" 를참조하십시오. Postgres Plus Advanced Server 에서오라클전환응용프로그램을개발하려면응용프로그램의설계에특히주의해야합니다. 예를들면, Oracle 호환애플리케이션을개발하는경우에는다음사항이필요합니다. 응용프로그램데이터베이스테이블을정의하는것은 Oracle 호환데이터형식이어야합니다 Oracle 의 SQL 과호환되는 SQL 문장이어야합니다. SQL 문장이나절차상의논리에서는 Oracle 호환시스템및내장함수를사용하지않으면안됩니다. 저장처리절차, 함수, 트리거, 패키지의데이터베이스의서버측응용프로그램을만들려면 Stored Procedure Language (SPL) 를사용하지않으면안됩니다. 오라클데이터사전과호환되는시스템카탈로그뷰를사용하지않으면안됩니다. Postgres Plus Advanced Server 에는이같은기능이있습니다. 또한 Oracle Call Interface (OCI) 를사용하여개발된응용프로그램과상호연결하기위하여, EnterpriseDB 는 Open Client Library (OCL) 를제공합니다. 이상은 EnterpriseDB 사양에대한자세한내용을설명합니다. 1.1 개정내역 여기서는 Postgres Plus Advanced Server 8.2 에서추가된 Oracle 호환사양을제공합니다. 매개변수구성 edb_redwood_strings 하면문자열연결시 null 의변수혹은 null 열을 null 값대신빈문자열로처리할수있게되었습니다. edb_redwood_strings 에대한자세한 내용은제 장을참조하십시오. 9
10 매개변수구성 edb_stmt_level_tx 를통해 SQL 명령을자동으로삭제하는롤백영역을트랜잭션내의모든 SQL 명령이아닌 1 개의 SQL 명령에만제한할수있습니다. edb_stmt_level_tx 에대한자세한내용은제 장을참조하십시오. 데이터베이스연결, DELETE, INSERT, SELECT, UPDATE 명령이지원되었습니다. 자세한내용은 CREATE DATABASE LINK 명령과 DROP DATABASE LINK 명령을참조하십시오. 지정된실행계획을최적화프로그램에사용하는최적화팁, DELETE, SELECT, UPDATE 명령이지원되었습니다. 최적화힌트에대한자세한내용은 3.4 장을참조하십시오. AUTHID DEFINER, AUTHID CURRENT_USER 어구가 CREATE FUNCTION, CREATE PROCEDURE, CREATE PACKAGE 명령에지원되었습니다. 이프로그램을참조하는데이터베이스개체에대한액세스권한을결정하기위해프로그램소유자의권한을사용하는지, 프로그램을실행하여현재사용자의권한을사용하는방법을지정합니다. 또자격이되지않는개체를참조하는데사용하는사용자의검색경로를지정합니다. SPL 프로그램보안에대한자세한내용은제 장을참조하십시오. NOMINVALUE, NOMAXVALUE 어구가 CREATE SEQUENCE 명령에지원되었습니다. 이것은각시퀀스의기본최소값또는최대값을사용하도록지정합니다. FORALL 명령문은 DELETE, INSERT, UPDATE 명령이데이터베이스서버에여러개의값집합을전달할수있도록합니다. 이것은다른가치에대해여러번의명령을실행함으로써발생하는오버헤드를줄일수있습니다. FORALL 문장에대한자세한내용은제 장을참조하십시오. BULK COLLECT 어구를사용하여 SELECT INTO, FETCH, DELETE RETURNING, INSERT RETURNING, UPDATE RETURNING 명령결과모집을할수있습니다. 자세한내용은제 장을참조하십시오. EDB*Plus 유틸리티프로그램은 SQL*Plus 명령라인터미널인터페이스를제공합니다. 자세한내용은 10.1 장을참조하십시오. 1.2 본설명서작성규칙 본가이드에는다양한명령, 문장, 프로그램, 예제와같은의미로사용하는방법을명확하게하기위해여러종류의기술규칙이사용됩니다. 여기서는이규칙의요지를설명합니다. 여기서는용어는언어키워드사용자제공값이나문자등의단어또는단어군을말합니다. 용어의정확한의미는사용되는상황에따라결정됩니다. 이탤릭체는새로운용어가처음등장했을때사용됩니다. 고정폭글꼴은 SQL 명령, 지문중에서특정테이블및열이름, 프로그래밍언어키워드처럼그대로지정받아야하는용어를사용합니다. 예 ) SELECT * FROM emp; 이탤릭체고정폭글꼴은실제로는사용자가값을할당받아야하는용어를사용합니다. 예 ) DELETE FROM table_name; 10
11 파이프 ( ), 오른쪽또는왼쪽또는중하나의어휘를선택하는것을의미합니다. 파이프는대괄호 ( 옵션선택 ) 나괄호 (1 개를선택 ) 가운데 2 개이상의옵션을분리하는데사용됩니다. 대괄호 ([]) 는둘러싸인용어중에서 1 개를선택하거나아무것도선택하지않았는지보여줍니다. 예를들면, [a b] 는 a 또는 b 중 1 개를선택하거나둘다선택하지않을수있습니다. 괄호 ({}) 는둘러싸인용어중에서반드시 1 개를선택받아야하는것을의미합니다. 예를들면, {a b} 는 a 또는 b 중 1 개를선택하지않으면안됩니다.... 이용어가반복되는것을의미합니다. 예를들면, [a b]... 는 "b a a b a" 로이어질가능성이있다는것을보여줍니다. 1.3 오라클호환매개변수구성 시작부분에서언급한대로, Postgres Plus Advanced Server 는 PostgreSQL 와 Oracle 애플리케이션을개발하고실행할수있습니다. 시스템이 PostgreSQL 이나 Oracle 준수도달리게많은기능을가지고있습니다. 이데이터베이스클러스터데이터디렉토리에있는 postgresql.conf 파일매개변수구성으로제어됩니다. postgresql.conf 파일의매개변수를변경하면클러스터의모든데이터베이스의동작이변경됩니다. 이매개변수보다나은조정하는방법은데이터베이스사용자, 그룹수업으로조정하는것입니다. 매개변수는다음과같습니다. edb_redwood_date - 시간요소를 DATE 열을포함할지여부를제어합니다. Oracle 호환을위해서는 edb_redwood_date "true" 로설정합니다. edb_redwood_strings - 문자열의결합을위해, null 값을빈문자열로취급합니다. Oracle 호환을위해서는 edb_redwood_strings "true" 로설정합니다. edb_stmt_level_tx - SQL 명령을자동으로삭제하는롤백기능을 1 개의 SQL 문장만을롤백으로변경합니다. PostgreSQL 의기본동작이다현재트랜잭션의모든 SQL 문장을자동으로롤백하는것은아닙니다. Oracle 호환을위해서는 edb_stmt_level_tx "true" 로설정합니다. 그러나절대로필요한경우에만사용하도록하십시오. 자세한내용은제 장을참조하십시오. oracle_home - 오라클설치디렉토리에 Postgres Plus Advanced Server 의포인트. 자세한내용은제 장을참조하십시오 edb_redwood_date CREATE TABLE 명령또는 ALTER TABLE 명령에서열의데이터형식으로 DATE 를지정하면데이터베이스에테이블정의를저장하는동시에데이터형식이 TIMESTAMP (0) 으로변환됩니다. ( 단, 매개변수구성 edb_redwood_date 가 "true" 로설정되어있는경우 ) 따라서열은날짜와함께시간도포함됩니다. 이것은오라클 DATE 데이터형식과일치합니다. 11
12 edb_redwood_date "false" 로설정되어있는경우, CREATE TABLE 명령또는 ALTER TABLE 명령에서 열의데이터형식은 PostgreSQL 의 DATE 데이터형식그대로데이터베이스에저장됩니다. PostgreSQL 의 DATE 데이터형식은열사이시간은포함하지않고, 날짜만저장합니다. edb_redwood_date 설정에관계없이, SPL 선언부분에변수의데이터형식, 절차와함수의매개변수의데이터형식, 함수의반환데이터형식과같은다른형식의데이터형식으로 DATE 이지정되지때는항상내부에 TIMESTAMP (0) 으로변환됩니다. 따라서시간을처리할수있습니다. 날짜 / 시간데이터형식에대한자세한내용은제 장을참조하십시오 edb_redwood_strings Oracle 에서는문자열이 null 변수와 null 열과결합되면, 결과는원래텍스트로변경되지않습니다. 그러나 PostgreSQL 에서는문자열이 null 변수와 null 열과결합되면, 결과는 null 입니다. edb_redwood_strings 매개변수가 "true" 로설정되어있는경우이러한결합결과는 Oracle 과마찬가지입니다. edb_redwood_strings "false" 로설정되어있는경우, PostgreSQL 동작은변경되지않습니다. 아래에는차이예시로설명합니다. 다음장에서소개하는샘플응용프로그램은직원테이블을가지고있습니다. 이테이블은대부분의직원이 null 값인 comm 이라는열을가지고있습니다. edb_redwood_string "false" 로설정하면다음과같은쿼리를수행합니다. null 열을비어있지않은문자열과결합하면최종결과는 null 입니다. 따라서수수료를가진직원만이문의결과에표시됩니다. 다른모든직원의출력열은 null 입니다 SET edb_redwood_strings TO off; SELECT RPAD (ename, 10) '' TO_CHAR (sal, ' ') ' ' TO_CHAR (comm, ' ') "EMPLOYEE COMPENSATION"FROM emp; EMPLOYEE COMPENSATION ALLEN 1, WARD 1, MARTIN 1, , TURNER 1, (14 rows) 다음은 edb_redwood_strings "true" 로설정하면같은쿼리를수행합니다. 여기서 null 값이빈 문자열로취급됩니다. 빈문자열이비어있지않은문자열과결합하면비어있지않은문자열로 결과가산출됩니다. 같은질문을실행하면그결과는 Oracle 의결과와일치합니다. SET edb_redwood_strings TO on; 12
13 SELECT RPAD (ename, 10) '' TO_CHAR (sal, ' ') ' ' TO_CHAR (comm, ' ') "EMPLOYEE COMPENSATION"FROM emp; EMPLOYEE COMPENSATION SMITH ALLEN 1, WARD 1, JONES 2, MARTIN 1, , BLAKE 2, CLARK 2, SCOTT 3, KING 5, TURNER 1, ADAMS 1, JAMES FORD 3, MILLER 1, (14 rows) edb_stmt_level_tx Oracle 에서는 SQL 명령을실행할때오류가발생하면 1 개의명령으로생긴데이터베이스의 모든변경내용이롤백됩니다. 이것을, 명령문레벨의고립이라고합니다. 예를들면, 1 개의 UPDATE 명령에 5 개의행업데이트에성공했으나 6 번째줄의업데이트하는동안예외가 발생하면이명령이실행된 6 개의모든행을업데이트가롤백됩니다. 커밋또는롤백되지 않은이명령이전 SQL 명령의실행결과는대기상태가됩니다. PostgreSQL 에서는 SQL 명령실행중에예외가발생하면트랜잭션을시작하고그때까지는 데이터베이스에서일어난모든변화가롤백됩니다. 또한, 트랜잭션도중단상태로남아있기때문에, 다른트랜잭션을시작하기전에 COMMIT 명령 또는 ROLLBACK 명령이실행되지않으면안됩니다. edb_stmt_level_tx "true" 로설정되어있는경우, Oracle 과같이예외가발생했을때, 이전커밋 되지않은데이터베이스의변경사항은자동으로롤백되지않습니다. edb_stmt_le vel_tx "false" 로설정되어있는경우예외가발생했을경우는커밋되지않은데이터베이스의변경 사항은롤백할수있습니다. 주의 : 현재 SPL 프로그램에서항상 edb_stmt_level_tx "false" 로설정하는것과같은동작을 합니다. SPL 프로그램에서예외가발생하면마지막으로예외가발생한블록범위내에서일어난 변화에반영되지않은것은항상롤백됩니다. SPL 프로그램에서 edb_stmt_level_tx = "true" 를 지원하는것은향후릴리스입니다. 주의 : 이매개변수는성능에영향을주기때문에, 절대로필요한경우에만 edb_stmt_level_tx "true" 로설정하십시오. PSQL 에서실행되는다음은 edb_stmt_level_tx "false" 의경우두번째 INSERT 명령이취소되는 것과동시에, 첫번째 INSERT 명령을롤백되는것을의미합니다. PSQL 에서 \ set AUTOCOMMIT off 명령을실행해야할주의하십시오. 그렇지않으면모든 SQL 문이자동으로 반영되어버리고 edb_stmt_level_tx 의효과를거둘수없습니다. \ set AUTOCOMMIT off 13
14 SET edb_stmt_level_tx TO off; INSERT INTO emp (empno, ename, deptno) VALUES (9001, 'JONES', 40); INSERT INTO emp (empno, ename, deptno) VALUES (9002, 'JONES', 00); ERROR : insert or update on table "emp"violates foreign key constraint "emp_ref_dept_fk" DETAIL : Key (deptno) = (0) is not present in table "dept" COMMIT; SELECT empno, ename, deptno FROM emp WHERE empno> 9000; empno ename deptno (0 rows) 다음은, edb_stmt_level_tx "true" 로설정합니다. 첫번째 INSERT 명령에오류가발생하면처음 INSERT 명령이롤백되지않습니다. 이때첫번째 INSERT 명령을커밋또는롤백할수 있습니다. \ set AUTOCOMMIT off SET edb_stmt_level_tx TO on; INSERT INTO emp (empno, ename, deptno) VALUES (9001, 'JONES', 40); INSERT INTO emp (empno, ename, deptno) VALUES (9002, 'JONES', 00); ERROR : insert or update on table "emp"violates foreign key constraint "emp_ref_dept_fk" DETAIL : Key (deptno) = (0) is not present in table "dept" SELECT empno, ename, deptno FROM emp WHERE empno> 9000; empno ename deptno JONES 40 (1 row) COMMIT; COMMIT 명령대신 ROLLBACK 명령을실행할수있습니다. 이경우직원 ID 9001 삽입은롤백됩니다 oracle_home 그설정매개변수 oracle_home는파일시스템내의정정된 Oracle Home directory에 Postgres Plus Advanced Server 에접근할수있습니다. 이매개변수는오직슈퍼유저에의해설정되어질수있고, 온, 오프라인의어느레벨에서도설정될수있습니다. 따라서단일 EDB 서버에서여러 Oracle 클라이언트를설치와오라클의기존및최신버전의접근을동시에사용할수있도록했습니다. 실행에서만약설정되었다면 oracle_home 설정매개변수는기본인 ORACLE_HOME 환경변수에오버라이드될것입니다. 1.4 본설명서에대한예제본설명서에지명되는예제는 Postgres Plus Advanced Server 의 PSQL 프로그램을사용하고있습니다. PSQL 를사용할때일반적으로나타나는프롬프트는이경우에서는생략합니다. 설명하는점이매우분명하게표현하고있습니다. 14
15 Examples and output from examples are shown in fixed - width, blue font on a light blue background. 또한다음사항을주의해야합니다. Postgres Plus Advanced Server 를설치할때본가이드에지명되는경우와동일한결과를얻기 위하여, Oracle 호환설정및기본설정해야합니다. 기본 Oracle 호환구성은 PSQL 에서다음 명령을실행하여확인할수있습니다. 다음결과와동일하다면문제가되지않습니다. SHOW edb_redwood_date; edb_redwood_date on SHOW datestyle; DateStyle Redwood, DMY SHOW edb_redwood_strings; edb_redwood_strings on 예제에서는 Postgres Plus Advanced Server 설치시생성, 로드되는샘플테이블 dept, emp, jobhist 를사용합니다. emp 테이블은트리거와함께설치되지만이설명서에서보여주는결과와동일한결과를얻기위하여트리거를사용할수없도록해야합니다. enterprisedb 슈퍼에서 Postgres Plus Advanced Server 에로그인하여다음명령으로트리거를사용하지못하도록합니다. ALTER TABLE emp DISABLE TRIGGER USER; emp 테이블의트리거는다음명령으로다시사용할수있습니다. ALTER TABLE emp ENABLE TRIGGER USER; 제 2 장 SQL 자습서 이장에서는관계형데이터베이스관리시스템을처음사용하는분들을위해 SQL 언어를 소개합니다. 테이블만들기, 삽입쿼리업데이트등기본사항은보기를들어설명합니다. 15
16 뷰, 외래키, 거래같은고급개념도설명합니다. 2.1 시작 Postgres Plus Advanced Server 는관계형데이터베이스관리시스템 (RDBMS) 입니다. 이것은연결된데이터를관리하는시스템입니다. 관계는본질적으로테이블을가리키는수학용어입니다. 테이블에데이터를저장한다는생각은오늘날아주일반적이며, 이해할수있는사고방식이지만데이터베이스를구성하는다른방법도있습니다. Unix 와같은운영체제의파일및디렉토리구성은계층적데이터베이스의예라고말할수있으며, 또한최근에는객체지향데이터베이스도개발되어있습니다. 각테이블은행집합입니다. 행은동일한열집합입니다. 각항목에는데이터형식을 지정합니다. 각줄줄은정해진순서대로나란히있는반면 SQL 은테이블의행순서를 보증하지않습니다. ( 비록명시적으로표시하기위해정렬할수있습니다 ) 테이블은데이터베이스에서그룹화됩니다. 단순한 EnterpriseDB 서버인스턴스에서처리한그 데이터베이스집합이데이터베이스클러스터를구성합니다 예제 이매뉴얼에서는데이터베이스의개념을기본부터고급까지설명하기위하여데이터베이스를 사용합니다 예제데이터베이스설치 Postgres Plus Advanced Server 을설치한경우 edb 라는예제데이터베이스를자동으로 만들어집니다. 이데이터베이스에는사용하는테이블이나프로그램이포함되어있습니다. 예제데이터베이스의테이블과프로그램은 edb - sample.sql 스크립트를실행하면언제든지다시 만들수있습니다. 스크립트는 EnterpriseDB 의홈디렉토리의 samples 디렉토리에있습니다. 이스크립트는다음작업을수행합니다. 현재연결된데이터베이스에서예제테이블과프로그램을만듭니다 PUBLIC 그룹테이블에모든권한을부여합니다 16
17 테이블과프로그램은검색경로의첫번째스키마에만들어집니다. 현재사용자는스키마에서 테이블과절차를만들능력을가지고있습니다. 다음명령을사용하여검색경로를볼수 있습니다. SHOW SEARCH_PATH; EnterpriseDB 의 PSQL 명령을사용하여검색경로를변경할수있습니다 예제설명 데이터베이스는조직의직원에대한데이터입니다. 직원, 부서, 직원의기록을 3 개의레코드를포함하고있습니다. 각직원은직원 ID, 이름, 직업, 봉급, 관리자의데이터를가지고있습니다. 월급이외에수수료를 벌어직원도있습니다. 직원과관련된모든정보는 emp 테이블에저장됩니다. 샘플회사는여러곳에부서가있습니다. 그래서부서의주소를기록하고있습니다. 각직원은 부서에속해있으며각부서는부서번호와약어로식별됩니다. 또한각부처는 1 개의주소에 연결되어있습니다. 부서에속한모든정보는 dept 테이블에저장됩니다. 회사는직원이종사하고있던직업정보를기록하고있습니다. 오랫동안회사에서일하고있는직원도있고, 승진, 승급하는직원도있고, 부서가바뀐직원도있습니다. 직원들의상황이바뀐경우, 회사는이전직책마지막날을기록합니다. 그리고, 새로운일을시작날짜, 제목, 부서, 급여, 배치전환의이유를새로운일을기록으로추가합니다. 직원기록의모든정보는 jobhist 테이블에저장됩니다. 다음은예제데이터베이스의테이블에대한관계를보여주는다이어그램입니다. 17
18 그림 1 데이터베이스테이블 다음은 edb - sample.sql 스크립트입니다. - - Script that creates the 'sample'tables, views, procedures, - functions, triggers, etc. - - Start new transaction - commit all or nothing - BEGIN; / - - Create and load tables used in the documentation examples. - - Create the 'dept'table - CREATE TABLE dept ( deptno NUMBER (2) NOT NULL CONSTRAINT dept_pk PRIMARY KEY, dname VARCHAR2 (14) CONSTRAINT dept_dname_uq UNIQUE, loc VARCHAR2 (13) ); - - Create the 'emp'table - CREATE TABLE emp ( empno NUMBER (4) NOT NULL CONSTRAINT emp_pk PRIMARY KEY, ename VARCHAR2 (10), 18
19 job VARCHAR2 (9) mgr NUMBER (4), hiredate DATE, sal NUMBER (7,2) CONSTRAINT emp_sal_ck CHECK (sal> 0) comm NUMBER (7,2), deptno NUMBER (2) CONSTRAINT emp_ref_dept_fk REFERENCES dept (deptno) ); - - Create the 'jobhist'table - CREATE TABLE jobhist ( empno NUMBER (4) NOT NULL, startdate DATE NOT NULL, enddate DATE, job VARCHAR2 (9) sal NUMBER (7,2), comm NUMBER (7,2), deptno NUMBER (2), chgdesc VARCHAR2 (80), CONSTRAINT jobhist_pk PRIMARY KEY (empno, startdate) CONSTRAINT jobhist_ref_emp_fk FOREIGN KEY (empno) REFERENCES emp (empno) ON DELETE CASCADE, CONSTRAINT jobhist_ref_dept_fk FOREIGN KEY (deptno) REFERENCES dept (deptno) ON DELETE SET NULL, CONSTRAINT jobhist_date_chk CHECK (startdate <= enddate) 19
20 ); - - Create the 'salesemp'view - CREATE OR REPLACE VIEW salesemp AS SELECT empno, ename, hiredate, sal, comm FROM emp WHERE job = 'SALESMAN'; - - Sequence to generate values for function 'new_empno'. - CREATE SEQUENCE next_empno START WITH 8000 INCREMENT BY 1; - - Issue PUBLIC grants - GRANT ALL ON emp TO PUBLIC; GRANT ALL ON dept TO PUBLIC; GRANT ALL ON jobhist TO PUBLIC; GRANT ALL ON salesemp TO PUBLIC; GRANT ALL ON next_empno TO PUBLIC; - - Load the 'dept'table - INSERT INTO dept VALUES (10, 'ACCOUNTING', 'NEW YORK'); INSERT INTO dept VALUES (20, 'RESEARCH', 'DALLAS'); INSERT INTO dept VALUES (30, 'SALES', 'CHICAGO'); INSERT INTO dept VALUES (40, 'OPERATIONS', 'BOSTON'); - 20
21 - Load the 'emp'table - INSERT INTO emp VALUES (7369, 'SMITH', 'CLERK', 7902, '17 - DEC - 80 ', 800, NULL, 20); INSERT INTO emp VALUES (7499, 'ALLEN', 'SALESMAN', 7698, '20 - FEB - 81 ', 1600,300,30); INSERT INTO emp VALUES (7521, 'WARD', 'SALESMAN', 7698, '22 - FEB - 81 ', 1250,500,30); INSERT INTO emp VALUES (7566, 'JONES', 'MANAGER', 7839, '02 - APR - 81 ', 2975, NULL, 20); INSERT INTO emp VALUES (7654, 'MARTIN', 'SALESMAN', 7698, '28 - SEP - 81 ', 1250,1400,30); INSERT INTO emp VALUES (7698, 'BLAKE', 'MANAGER', 7839, '01 - MAY - 81 ', 2850, NULL, 30); INSERT INTO emp VALUES (7782, 'CLARK', 'MANAGER', 7839, '09 - JUN - 81 ', 2450, NULL, 10); INSERT INTO emp VALUES (7788, 'SCOTT', 'ANALYST', 7566, '19 - APR - 87 ', 3000, NULL, 20); INSERT INTO emp VALUES (7839, 'KING', 'PRESIDENT', NULL, '17 - NOV - 81 ', 5000, NULL, 10); INSERT INTO emp VALUES (7844, 'TURNER', 'SALESMAN', 7698, '08 - SEP - 81 ', 1500,0,30); INSERT INTO emp VALUES (7876, 'ADAMS', 'CLERK', 7788, '23 - MAY - 87 ', 1100, NULL, 20); INSERT INTO emp VALUES (7900, 'JAMES', 'CLERK', 7698, '03 - DEC - 81 ', 950, NULL, 30); INSERT INTO emp VALUES (7902, 'FORD', 'ANALYST', 7566, '03 - DEC - 81 ', 3000, NULL, 20); INSERT INTO emp VALUES (7934, 'MILLER', 'CLERK', 7782, '23 - JAN - 82 ', 1300, NULL, 10); - - Load the 'jobhist'table - INSERT INTO jobhist VALUES (7369, '17 - DEC - 80 ', NULL,'CLERK ', 800, NULL, 20,'New Hire '); 21
22 INSERT INTO jobhist VALUES (7499, '20 - FEB - 81 ', NULL,'SALESMAN ', 1600,300,30,'New Hire '); INSERT INTO jobhist VALUES (7521, '22 - FEB - 81 ', NULL,'SALESMAN ', 1250,500,30,'New Hire '); INSERT INTO jobhist VALUES (7566, '02 - APR - 81 ', NULL,'MANAGER ', 2975, NULL, 20,'New Hire '); INSERT INTO jobhist VALUES (7654, '28 - SEP - 81 ', NULL,'SALESMAN ', 1250,1400,30,'New Hire '); INSERT INTO jobhist VALUES (7698, '01 - MAY - 81 ', NULL,'MANAGER ', 2850, NULL, 30,'New Hire '); INSERT INTO jobhist VALUES (7782, '09 - JUN - 81 ', NULL,'MANAGER ', 2450, NULL, 10,'New Hire '); INSERT INTO jobhist VALUES (7788, '19 - APR - 87 ', '12 - APR - 88', 'CLERK', 1000, NULL, 20, 'New Hire'); INSERT INTO jobhist VALUES (7788, '13 - APR - 88 ', '04 - MAY - 89', 'CLERK', 1040, NULL, 20, 'Raise'); INSERT INTO jobhist VALUES (7788, '05 - MAY - 90 ', NULL,'ANALYST ', 3000, NULL, 20,'Promoted to Analyst '); INSERT INTO jobhist VALUES (7839, '17 - NOV - 81 ', NULL,'PRESIDENT ', 5000, NULL, 10,'New Hire '); INSERT INTO jobhist VALUES (7844, '08 - SEP - 81 ', NULL,'SALESMAN ', 1500,0,30,'New Hire '); INSERT INTO jobhist VALUES (7876, '23 - MAY - 87 ', NULL,'CLERK ', 1100, NULL, 20,'New Hire '); INSERT INTO jobhist VALUES (7900, '03 - DEC - 81 ', '14 - JAN - 83', 'CLERK', 950, NULL, 10, 'New Hire'); INSERT INTO jobhist VALUES (7900, '15 - JAN - 83 ', NULL,'CLERK ', 950, NULL, 30,'Changed to Dept 30 '); INSERT INTO jobhist VALUES (7902, '03 - DEC - 81 ', NULL,'ANALYST ', 3000, NULL, 20,'New Hire '); INSERT INTO jobhist VALUES (7934, '23 - JAN - 82 ', NULL,'CLERK ', 1300, NULL, 10,'New Hire '); - - Populate statistics table and view (pg_statistic / pg_stats) - 22
23 ANALYZE dept; ANALYZE emp; ANALYZE jobhist; - - Procedure that lists all employees 'numbers and names - from the 'emp'table using a cursor. - CREATE OR REPLACE PROCEDURE list_emp IS v_empno NUMBER (4); v_ename VARCHAR2 (10); CURSOR emp_cur IS SELECT empno, ename FROM emp ORDER BY empno; BEGIN OPEN emp_cur; DBMS_OUTPUT.PUT_LINE ( 'EMPNO ENAME'); DBMS_OUTPUT.PUT_LINE (' '); LOOP FETCH emp_cur INTO v_empno, v_ename; EXIT WHEN emp_cur % NOTFOUND; DBMS_OUTPUT.PUT_LINE (v_empno '' v_ename); END LOOP; CLOSE emp_cur; END; / - 23
24 - Procedure that selects an employee row given the employee - number and displays certain columns. - CREATE OR REPLACE PROCEDURE select_emp ( p_empno IN NUMBER ) IS v_ename emp.ename % TYPE; v_hiredate emp.hiredate % TYPE; v_sal emp.sal % TYPE; v_comm emp.comm % TYPE; v_dname dept.dname % TYPE; v_disp_date VARCHAR2 (10); BEGIN SELECT ename, hiredate, sal, NVL (comm, 0), dname INTO v_ename, v_hiredate, v_sal, v_comm, v_dname FROM emp e, dept d WHERE empno = p_empno AND e.deptno = d.deptno; v_disp_date : = TO_CHAR (v_hiredate, 'MM / DD / YYYY'); DBMS_OUTPUT.PUT_LINE ( 'Number :' p_empno); DBMS_OUTPUT.PUT_LINE ( 'Name :' v_ename); DBMS_OUTPUT.PUT_LINE ( 'Hire Date :' v_disp_date); DBMS_OUTPUT.PUT_LINE ( 'Salary :' v_sal); DBMS_OUTPUT.PUT_LINE ( 'Commission :' v_comm); DBMS_OUTPUT.PUT_LINE ( 'Department :' v_dname); 24
25 EXCEPTION WHEN NO_DATA_FOUND THEN DBMS_OUTPUT.PUT_LINE ( 'Employee' p_empno 'not found'); WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE ( 'The following is SQLERRM :'); DBMS_OUTPUT.PUT_LINE (SQLERRM); DBMS_OUTPUT.PUT_LINE ( 'The following is SQLCODE :'); DBMS_OUTPUT.PUT_LINE (SQLCODE); END; / - - Procedure that queries the 'emp'table based on - department number and employee number or name. Returns - employee number and name as IN OUT parameters and job, - hire date, and salary as OUT parameters. - CREATE OR REPLACE PROCEDURE emp_query ( p_deptno IN NUMBER, p_empno IN OUT NUMBER, p_ename IN OUT VARCHAR2, p_job OUT VARCHAR2, p_hiredate OUT DATE, p_sal OUT NUMBER ) IS BEGIN 25
26 SELECT empno, ename, job, hiredate, sal INTO p_empno, p_ename, p_job, p_hiredate, p_sal FROM emp WHERE deptno = p_deptno AND (empno = p_empno OR ename = UPPER (p_ename)); END; / - - Procedure to call 'emp_query_caller'with IN and IN OUT - parameters. Displays the results received from IN OUT and - OUT parameters. - CREATE OR REPLACE PROCEDURE emp_query_caller IS v_deptno NUMBER (2); v_empno NUMBER (4); v_ename VARCHAR2 (10); v_job VARCHAR2 (9); v_hiredate DATE; v_sal NUMBER; BEGIN v_deptno : = 30; v_empno : = 0; v_ename : = 'Martin'; emp_query (v_deptno, v_empno, v_ename, v_job, v_hiredate, v_sal); 26
27 DBMS_OUTPUT.PUT_LINE ( 'Department :' v_deptno); DBMS_OUTPUT.PUT_LINE ( 'Employee No :' v_empno); DBMS_OUTPUT.PUT_LINE ( 'Name :' v_ename); DBMS_OUTPUT.PUT_LINE ( 'Job :' v_job); DBMS_OUTPUT.PUT_LINE ( 'Hire Date :' v_hiredate); DBMS_OUTPUT.PUT_LINE ( 'Salary :' v_sal); EXCEPTION WHEN TOO_MANY_ROWS THEN DBMS_OUTPUT.PUT_LINE ( 'More than one employee was selected'); WHEN NO_DATA_FOUND THEN DBMS_OUTPUT.PUT_LINE ( 'No employees were selected'); END; / - - Function to compute yearly compensation based on semimonthly - salary. - CREATE OR REPLACE FUNCTION emp_comp ( p_sal NUMBER, p_comm NUMBER ) RETURN NUMBER IS BEGIN RETURN (p_sal + NVL (p_comm, 0)) * 24; END; / 27
28 - - Function that gets the next number from sequence, 'next_empno', - and ensures it is not already in use as an employee number. - CREATE OR REPLACE FUNCTION new_empno RETURN NUMBER IS v_cnt INTEGER : = 1; v_new_empno NUMBER; BEGIN WHILE v_cnt> 0 LOOP SELECT next_empno.nextval INTO v_new_empno FROM dual; SELECT COUNT (*) INTO v_cnt FROM emp WHERE empno = v_new_empno; END LOOP; RETURN v_new_empno; END; / - - EDB - SPL function that adds a new clerk to table 'emp'. This function - uses package 'emp_admin'. - CREATE OR REPLACE FUNCTION hire_clerk ( p_ename VARCHAR2, p_deptno NUMBER ) RETURN NUMBER IS v_empno NUMBER (4); 28
29 v_ename VARCHAR2 (10); v_job VARCHAR2 (9); v_mgr NUMBER (4); v_hiredate DATE; v_sal NUMBER (7,2); v_comm NUMBER (7,2); v_deptno NUMBER (2); BEGIN v_empno : = new_empno; INSERT INTO emp VALUES (v_empno, p_ename, 'CLERK', 7782, TRUNC (SYSDATE), , NULL, p_deptno); SELECT empno, ename, job, mgr, hiredate, sal, comm, deptno INTO v_empno, v_ename, v_job, v_mgr, v_hiredate, v_sal, v_comm, v_deptno FROM emp WHERE empno = v_empno; DBMS_OUTPUT.PUT_LINE ( 'Department :' v_deptno); DBMS_OUTPUT.PUT_LINE ( 'Employee No :' v_empno); DBMS_OUTPUT.PUT_LINE ( 'Name :' v_ename); DBMS_OUTPUT.PUT_LINE ( 'Job :' v_job); DBMS_OUTPUT.PUT_LINE ( 'Manager :' v_mgr); DBMS_OUTPUT.PUT_LINE ( 'Hire Date :' v_hiredate); DBMS_OUTPUT.PUT_LINE ( 'Salary :' v_sal); DBMS_OUTPUT.PUT_LINE ( 'Commission :' v_comm); RETURN v_empno; EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE ( 'The following is SQLERRM :'); 29
30 DBMS_OUTPUT.PUT_LINE (SQLERRM); DBMS_OUTPUT.PUT_LINE ( 'The following is SQLCODE :'); DBMS_OUTPUT.PUT_LINE (SQLCODE); RETURN -1; END; / - - PostgreSQL PL / pgsql function that adds a new salesman - to table 'emp'. - CREATE OR REPLACE FUNCTION hire_salesman ( p_ename VARCHAR, p_sal NUMERIC, p_comm NUMERIC ) RETURNS NUMERIC AS $ $ DECLARE v_empno NUMERIC (4); v_ename VARCHAR (10); v_job VARCHAR (9); v_mgr NUMERIC (4); v_hiredate DATE; v_sal NUMERIC (7,2); v_comm NUMERIC (7,2); v_deptno NUMERIC (2); BEGIN 30
31 v_empno : = new_empno (); INSERT INTO emp VALUES (v_empno, p_ename, 'SALESMAN', 7698, CURRENT_DATE, p_sal, p_comm, 30); SELECT INTO v_empno, v_ename, v_job, v_mgr, v_hiredate, v_sal, v_comm, v_deptno empno, ename, job, mgr, hiredate, sal, comm, deptno FROM emp WHERE empno = v_empno; RAISE INFO 'Department : %', v_deptno; RAISE INFO 'Employee No : %', v_empno; RAISE INFO 'Name : %', v_ename; RAISE INFO 'Job : %', v_job; RAISE INFO 'Manager : %', v_mgr; RAISE INFO 'Hire Date : %', v_hiredate; RAISE INFO 'Salary : %', v_sal; RAISE INFO 'Commission : %', v_comm; RETURN v_empno; EXCEPTION WHEN OTHERS THEN RAISE INFO 'The following is SQLERRM :'; RAISE INFO '%', SQLERRM; RAISE INFO 'The following is SQLSTATE :'; RAISE INFO '%', SQLSTATE; RETURN -1; END; $ $ LANGUAGE 'plpgsql'; / 31
32 - - Rule to INSERT into view 'salesemp' - CREATE OR REPLACE RULE salesemp_i AS ON INSERT TO salesemp DO INSTEAD INSERT INTO emp VALUES (NEW.empno, NEW.ename, 'SALESMAN', 7698, NEW.hiredate, NEW.sal, NEW.comm, 30); - - Rule to UPDATE view 'salesemp' - CREATE OR REPLACE RULE salesemp_u AS ON UPDATE TO salesemp DO INSTEAD UPDATE emp SET empno = NEW.empno, ename = NEW.ename, hiredate = NEW.hiredate, sal = NEW.sal, comm = NEW.comm WHERE empno = OLD.empno; - - Rule to DELETE from view 'salesemp' - CREATE OR REPLACE RULE salesemp_d AS ON DELETE TO salesemp DO INSTEAD DELETE FROM emp WHERE empno = OLD.empno; - - After statement - level trigger that displays a message after 32
33 - an insert, update, or deletion to the 'emp'table. One message - per SQL command is displayed. - CREATE OR REPLACE TRIGGER user_audit_trig AFTER INSERT OR UPDATE OR DELETE ON emp DECLARE v_action VARCHAR2 (24); BEGIN IF INSERTING THEN v_action : = 'added employee (s) on'; ELSIF UPDATING THEN v_action : = 'updated employee (s) on'; ELSIF DELETING THEN v_action : = 'deleted employee (s) on'; END IF; DBMS_OUTPUT.PUT_LINE ( 'User' USER v_action TO_CHAR (SYSDATE, 'YYYY - MM - DD')); END; / - - Before row - level trigger that displays employee number and - salary of an employee that is about to be added, updated, - or deleted in the 'emp'table. - CREATE OR REPLACE TRIGGER emp_sal_trig BEFORE DELETE OR INSERT OR UPDATE ON emp FOR EACH ROW 33
34 DECLARE sal_diff NUMBER; BEGIN IF INSERTING THEN DBMS_OUTPUT.PUT_LINE ( 'Inserting employee' : NEW.empno); DBMS_OUTPUT.PUT_LINE ( '.. New salary :' : NEW.sal); END IF; IF UPDATING THEN sal_diff : = : NEW.sal - : OLD.sal; DBMS_OUTPUT.PUT_LINE ( 'Updating employee' : OLD.empno); DBMS_OUTPUT.PUT_LINE ( '.. Old salary :' : OLD.sal); DBMS_OUTPUT.PUT_LINE ( '.. New salary :' : NEW.sal); DBMS_OUTPUT.PUT_LINE ( '.. Raise :' sal_diff); END IF; IF DELETING THEN DBMS_OUTPUT.PUT_LINE ( 'Deleting employee' : OLD.empno); DBMS_OUTPUT.PUT_LINE ( '.. Old salary :' : OLD.sal); END IF; END; / - - Package specification for the 'emp_admin'package. - CREATE OR REPLACE PACKAGE emp_admin IS FUNCTION get_dept_name ( 34
35 p_deptno NUMBER ) RETURN VARCHAR2; FUNCTION update_emp_sal ( p_empno NUMBER, p_raise NUMBER ) RETURN NUMBER; PROCEDURE hire_emp ( p_empno NUMBER, p_ename VARCHAR2, p_job VARCHAR2, p_sal NUMBER, p_hiredate DATE, p_comm NUMBER, p_mgr NUMBER, p_deptno NUMBER ); PROCEDURE fire_emp ( p_empno NUMBER ); END emp_admin; / - - Package body for the 'emp_admin'package. - CREATE OR REPLACE PACKAGE BODY emp_admin IS 35
36 - - Function that queries the 'dept'table based on the department - number and returns the corresponding department name. - FUNCTION get_dept_name ( p_deptno IN NUMBER ) RETURN VARCHAR2 IS v_dname VARCHAR2 (14); BEGIN SELECT dname INTO v_dname FROM dept WHERE deptno = p_deptno; RETURN v_dname; EXCEPTION WHEN NO_DATA_FOUND THEN DBMS_OUTPUT.PUT_LINE ( 'Invalid department number' p_deptno); RETURN ''; END; - - Function that updates an employee 's salary based on the - employee number and salary increment / decrement passed - as IN parameters. Upon successful completion the function - returns the new updated salary. - FUNCTION update_emp_sal ( p_empno IN NUMBER, p_raise IN NUMBER 36
37 ) RETURN NUMBER IS v_sal NUMBER : = 0; BEGIN SELECT sal INTO v_sal FROM emp WHERE empno = p_empno; v_sal : = v_sal + p_raise; UPDATE emp SET sal = v_sal WHERE empno = p_empno; RETURN v_sal; EXCEPTION WHEN NO_DATA_FOUND THEN DBMS_OUTPUT.PUT_LINE ( 'Employee' p_empno 'not found'); RETURN -1; WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE ( 'The following is SQLERRM :'); DBMS_OUTPUT.PUT_LINE (SQLERRM); DBMS_OUTPUT.PUT_LINE ( 'The following is SQLCODE :'); DBMS_OUTPUT.PUT_LINE (SQLCODE); RETURN -1; END; - - Procedure that inserts a new employee record into the 'emp'table. - PROCEDURE hire_emp ( p_empno NUMBER, p_ename VARCHAR2, p_job VARCHAR2, 37
38 p_sal NUMBER, p_hiredate DATE, p_comm NUMBER, p_mgr NUMBER, p_deptno NUMBER ) AS BEGIN INSERT INTO emp (empno, ename, job, sal, hiredate, comm, mgr, deptno) VALUES (p_empno, p_ename, p_job, p_sal, p_hiredate, p_comm, p_mgr, p_deptno); END; - - Procedure that deletes an employee record from the 'emp'table based - on the employee number. - PROCEDURE fire_emp ( p_empno NUMBER ) AS BEGIN DELETE FROM emp WHERE empno = p_empno; END; END; / COMMIT; 38
39 다음항목보다는 SQL 명령의기본을설명합니다 새테이블만들기 테이블과테이블의모든열이름과형식을지정하면새테이블을만들수있습니다. 이번예제에서는테이블을정의하는데필요한최소한의정보로짧은 emp 테이블을만듭니다. CREATE TABLE emp ( empno NUMBER (4), ename VARCHAR2 (10), job VARCHAR2 (9) mgr NUMBER (4), hiredate DATE, sal NUMBER (7,2), comm NUMBER (7,2), deptno NUMBER (2) ); 명령을여러줄에 PSQL 입력하실수있습니다. PSQL 은세미콜론으로끝날때까지그명령은 계속하는것으로인식합니다. SQL 명령은공백문자 ( 즉공백, 탭, 줄바꿈 ) 를자유롭게사용할수있습니다. 즉, 위에언급한명령과는다른형태로입력할수있다는것을의미합니다. 모든내용을 1 줄에입력하는수도있습니다. 2 개의하이픈 ("--") 은코멘트를시작합니다. 입력을발견했을때는줄끝까지무시됩니다. SQL 은키워드와식별자에대해대소문자를구별하지않습니다. 그러나식별자를인용부호로둘러싸있을경우대소문자를구분합니다.( 위와는다르게 ) VARCHAR2 (10) 는 10 문자의텍스트를저장할수있는데이터형식을지정합니다. NUMBER (7,2) 은정확도가 7 스케일이 2 인고정소수점입니다. NUMBER (4) 는정확도가 4, 스케일 0 의 정수입니다. Postgres Plus Advanced Server 는표준 SQL 데이터형식, INTEGER, SMALLINT, NUMBER, REAL, DOUBLE PRECISION, CHAR, VARCHAR2, DATE 과 TIMESTAMP 를지원합니다. 이데이터형식 동의어도지원합니다. 39
40 테이블이더이상필요하지않거나다른것을새롭게하고싶다면다음명령을사용하여제거할 수있습니다. DROP TABLE tablename; 테이블에행을삽입 다음과같이, INSERT 문을사용하여테이블에행을삽입합니다. INSERT INTO emp VALUES (7369, 'SMITH', 'CLERK', 7902, '17 - DEC - 80 ', 800, NULL, 20); 모든데이터형식중하나라고하면이해할수있는입력형식을사용하고있다는것을명심하십시오. 일반적으로단순한숫자가아닌상수는이예와같이작은따옴표 ( ') 로입력해야합니다. DATE 형식승인은실제로매우유연합니다. 그러나이연습에서는애매함이없는형식에집착하는것입니다. 위의구문은열순서를기억할필요가있습니다. 다음구문은열목록을명시적으로부여할수 있습니다. INSERT INTO emp (empno, ename, job, mgr, hiredate, sal, comm, deptno) VALUES (7499, 'ALLEN', 'SALESMAN', 7698, '20 - FEB - 81 ', 1600,300,30); 목록에있는줄은원하는순서대로지정할수있습니다. 또일부열을생략할수있습니다. 예를들어수수료를모르면다음과같이할수있습니다. INSERT INTO emp (empno, ename, job, mgr, hiredate, sal, deptno) VALUES (7369, 'SMITH', 'CLERK', 7902, '17 - DEC - 80 ', 800,20); 많은개발자들은절대적인순서에의존하는것보다열목록을명시적으로지정하는방법을즐겨 사용합니다 테이블의쿼리 테이블에서데이터를뽑아내기위해테이블에쿼리를합니다. 이를위해 SQL SELECT 문이 사용됩니다. 이문장은선택목록 ( 반환되는열목록부분 ) 과테이블목록 ( 데이터를검색할 40
41 테이블의목록부분 ) 및선택적조건 ( 제한을지정하는부분 ) 으로나눌수있습니다. 예를들면, emp 테이블의모든직원의모든열을추출하려면다음과같은쿼리를합니다. SELECT * FROM emp; 여기서선택목록에서 "*" 은 " 모든 과 열 " 의약어입니다. 이쿼리의결과는다음과같습니다. empno ename job mgr hiredate sal comm deptno SMITH CLERK DEC :00: ALLEN SALESMAN FEB :00: WARD SALESMAN FEB :00: JONES MANAGER APR :00: MARTIN SALESMAN SEP :00: BLAKE MANAGER MAY :00: CLARK MANAGER JUN :00: SCOTT ANALYST APR :00: KING PRESIDENT 17 - NOV :00: TURNER SALESMAN SEP :00: ADAMS CLERK MAY :00: JAMES CLERK DEC :00: FORD ANALYST DEC :00: MILLER CLERK JAN :00: (14 rows) 선택목록에서원하는형식을사용하실수있습니다. 예를들면다음과같습니다. SELECT ename, sal, sal * 24 AS yearly_salary, deptno FROM emp; 41
42 ename sal yearly_salary deptno SMITH ALLEN WARD JONES MARTIN BLAKE CLARK SCOTT KING TURNER ADAMS JAMES FORD MILLER (14 rows) AS 절을사용하여출력열다시분류부분에주의하시기바랍니다 (AS 어구는생략할수 있습니다.) 쿼리는필요한내용이무엇인지지정 WHERE 절을추가하여쿼리에지정할수있습니다. WHERE 행에는논리 (True 값 ) 식을갖고, 이계산식이진정한하는행만반환합니다. 자주사용하는논리연산자 (AND, OR, NOT) 을사용할수있습니다. 예를들어, 다음은부서번호가 20 에서월급이 1000 달러가넘는직원데이터를추출합니다. SELECT ename, sal, deptno FROM emp WHERE deptno = 20 AND sal> 1000; ename sal deptno
43 JONES SCOTT ADAMS FORD (4 rows) 쿼리의결과를정렬하여반환하도록지정할수있습니다. SELECT ename, sal, deptno FROM emp ORDER BY ename; ename sal deptno ADAMS ALLEN BLAKE CLARK FORD JAMES JONES KING MARTIN MILLER SCOTT SMITH TURNER WARD (14 rows) 쿼리결과에서중복행을제외하도록지정할수있습니다. 43
44 SELECT DISTINCT job FROM emp; job ANALYST CLERK MANAGER PRESIDENT SALESMAN (5 rows) 다음절에서하나의쿼리에여러테이블에서행을획득하는방법을설명합니다 테이블간의결합 여기까지의쿼리들은한번에 1 개의테이블에만액세스할수있었습니다. 쿼리들은한번에 여러테이블에접근하는것도가능하고, 동시에테이블의여러행에작업을수행할경우, 같은 테이블에액세스할수있습니다. 동시에같은테이블이나여러테이블의여러행에액세스하는 것은결합쿼리입니다. 예를들면, 관련부서의이름과위치를직원데이터와함께표시할 경우입니다. 이를위해서는 emp 테이블에각행의 deptno 열과, dept 테이블의모든행 deptno 열의를비교하고두값이일치하는행의조합을선택하여야합니다. 이것은다음과같은쿼리를 통해수행할수있습니다. SELECT emp.ename, emp.sal, dept.deptno, dept.dname, dept.loc FROM emp, dept WHERE emp.deptno = dept.deptno; ename sal deptno dname loc MILLER ACCOUNTING NEW YORK CLARK ACCOUNTING NEW YORK KING ACCOUNTING NEW YORK 44
45 SCOTT RESEARCH DALLAS JONES RESEARCH DALLAS SMITH RESEARCH DALLAS ADAMS RESEARCH DALLAS FORD RESEARCH DALLAS WARD SALES CHICAGO TURNER SALES CHICAGO ALLEN SALES CHICAGO BLAKE SALES CHICAGO MARTIN SALES CHICAGO JAMES SALES CHICAGO (14 rows) 이결과에서두개의결과를알수있습니다. 부서번호 40 에대한결과행은없습니다. emp 테이블에는부서번호 40 과일치하는 항목이아니라결합시 dept 테이블에서일치하지않는부분은무시되기때문입니다. 이것이어떻게만들어지는지를쉽게알아봅니다. 출력열목록 * 을사용하거나다음과같이일부테이블이름을지정하지않는것보다, 명시적으로테이블이름을사용하는것이바람직합니다. SELECT ename, sal, dept.deptno, dname, loc FROM emp, dept WHERE emp.deptno = dept.deptno; 열은각각다른이름 (deptno 줄은중복되므로열이름을테이블이름으로한정해야 됩니다 ) 이므로, 해석기는자동으로어떤테이블의열또는확인할수있습니다. 그러나결합 쿼리는열이름을테이블이름으로정규화하는것이좋다. 이러한결합쿼리는다음과같이다른형태로나타내는수도있습니다. SELECT emp.ename, emp.sal, dept.deptno, dept.dname, dept.loc FROM emp INNER JOIN dept ON emp.deptno = dept.deptno; 이문법은실제경우보다일반적으로사용되는것은아니지만이후주제의이해를돕기위해 보여지고있습니다. 45
46 이러한결합결과를모두보면부서번호 40 에속한직원은없으며, 결과적으로부서번호 40 의 기록이표시되지않는다는것을알수있습니다. 여기에일치하는직원이없는데도우리는부서 번호 40 의기록을얻을수있게될것입니다. 실행하고싶은쿼리는, dept 테이블을검사하고, 각행에대해 emp 줄에일치하는지확인합니다. 일치하지않는행이있으면, emp 테이블의열 부분을어떻게 " 빈값 " 을대신하려고합니다. 이러한쿼리를외부조인이라고합니다 ( 지금까지 의 join 은내부 join 입니다.) 다음과같은명령입니다. SELECT emp.ename, emp.sal, dept.deptno, dept.dname, dept.loc FROM dept LEFT OUTER JOIN emp ON emp.deptno = dept.deptno; ename sal deptno dname loc MILLER ACCOUNTING NEW YORK CLARK ACCOUNTING NEW YORK KING ACCOUNTING NEW YORK SCOTT RESEARCH DALLAS JONES RESEARCH DALLAS SMITH RESEARCH DALLAS ADAMS RESEARCH DALLAS FORD RESEARCH DALLAS WARD SALES CHICAGO TURNER SALES CHICAGO ALLEN SALES CHICAGO BLAKE SALES CHICAGO MARTIN SALES CHICAGO JAMES SALES CHICAGO 40 OPERATIONS BOSTON (15 rows) 46
47 이쿼리를왼쪽외부조인이라고합니다. 결합연산자의왼쪽에지정한테이블의각행에최소한한번기록되고반면에오른쪽테이블은왼쪽테이블행과일치하는것만이기록되기때문입니다. 오른쪽의테이블과일치하지않는왼쪽테이블줄을출력시오른쪽테이블의열은비어 (null) 로대체합니다. 외부조인을표현하는구문으로 WHERE 절에결합조건으로외부조인연산자 "(+)" 를사용하는 방법도있습니다. 외부조인연산자는테이블의열이름다음에넣습니다. 일치하지않는행이 있는경우해당테이블의열이름은 null 값으로바뀝니다. 즉, dept 테이블행에대해 emp 테이블에일치하는행이없으면 Postgres Plus Advanced Server 는 emp 열이포함선택 목록적으로 null 값을반환합니다. 위왼쪽외부조인예제는다음과같이다시작성할수 있습니다. SELECT emp.ename, emp.sal, dept.deptno, dept.dname, dept.loc FROM dept, emp WHERE emp.deptno (+) = dept.deptno; ename sal deptno dname loc MILLER ACCOUNTING NEW YORK CLARK ACCOUNTING NEW YORK KING ACCOUNTING NEW YORK SCOTT RESEARCH DALLAS JONES RESEARCH DALLAS SMITH RESEARCH DALLAS ADAMS RESEARCH DALLAS FORD RESEARCH DALLAS WARD SALES CHICAGO TURNER SALES CHICAGO ALLEN SALES CHICAGO BLAKE SALES CHICAGO MARTIN SALES CHICAGO JAMES SALES CHICAGO 47
48 40 OPERATIONS BOSTON (15 rows) 테이블을자신에게결합시킬수있습니다. 이것은자기결합이라고합니다. 예를들어, 각 직원의이름과함께직원관리자의이름도만회하는것을생각해볼수있습니다. 만일 그렇다면, emp 행 mgr 열과다른모든 emp 행 empno 행을비교해야합니다. SELECT e1.ename 'works for' e2.ename AS "Employees and their Managers"FROM emp e1, emp e2 WHERE e1.mgr = e2.empno; Employees and their Managers FORD works for JONES SCOTT works for JONES WARD works for BLAKE TURNER works for BLAKE MARTIN works for BLAKE JAMES works for BLAKE ALLEN works for BLAKE MILLER works for CLARK ADAMS works for SCOTT CLARK works for KING BLAKE works for KING JONES works for KING SMITH works for FORD (13 rows) 여기서는선택목록과결합조건속에서직원정보를표현하는 emp 테이블에 e1 라는레이블이붙어있습니다. 또한, 관리자의직원정보를표현하는 emp 테이블에 e2 라는레이블이붙어있습니다. 일의간단하게하기위하여다른쿼리에서도이러한별칭을사용할수있습니다. 다음은예제입니다. 48
49 SELECT e.ename, e.mgr, d.deptno, d.dname, d.loc FROM emp e, dept d WHERE e.deptno = d.deptno; ename mgr deptno dname loc MILLER ACCOUNTING NEW YORK CLARK ACCOUNTING NEW YORK KING 10 ACCOUNTING NEW YORK SCOTT RESEARCH DALLAS JONES RESEARCH DALLAS SMITH RESEARCH DALLAS ADAMS RESEARCH DALLAS FORD RESEARCH DALLAS WARD SALES CHICAGO TURNER SALES CHICAGO ALLEN SALES CHICAGO BLAKE SALES CHICAGO MARTIN SALES CHICAGO JAMES SALES CHICAGO (14 rows) 이러한형태의요약은상당히잘이루어집니다 집계함수 다른대부분의관계형데이터베이스제품뿐만아니라 Postgres Plus Advanced Server 은집계함수를지원합니다. 집계함수는여러행에서 1 개의결과를계산합니다. 예를들면, 행집합에대해 COUNT ( 총계 ), SUM ( 총수 ), AVG ( 평균 ), MAX ( 최대 ), MIN ( 최소 ) 와같은연산을수행집계가있습니다. 49
50 예를들어, 다음쿼리에서모든직원의봉급에서가장높은월급과가장낮은월급을찾을수 있습니다. SELECT MAX (sal) highest_salary, MIN (sal) lowest_salary FROM emp; highest_salary lowest_salary (1 row) 가장임금이높은직원의이름을알고싶다면다음과같은쿼리를실행할수도있습니다. SELECT ename FROM emp WHERE sal = MAX (sal); ERROR : aggregates not allowed in WHERE clause 그러나 MAX 집계함수를 WHERE 절에사용할수없기때문에이명령이작동하지않습니다 (WHERE 절에어떤행을집계처리에전달할것인가를결정하는것이며, 따라서집계함수를계산하기전으로평가되어야하는것은당연하다. 이때문에제한이있습니다 ). 하지만쿼리를다시작성하면의도한결과를얻을수있습니다. 여기에는다음과같은서브쿼리를사용합니다. SELECT ename FROM emp WHERE sal = (SELECT MAX (sal) FROM emp); ename KING (1 row) 서브쿼리는외부의쿼리에별도로결과를얻는독립적인연산입니다. 또 GROUP BY 절과결합한통합은아주유용합니다. 예를들어, 다음쿼리에서부서별로가장 높은급여를결정할수있습니다. SELECT deptno, MAX (sal) FROM emp GROUP BY deptno; 50
51 deptno max (3 rows) 여기에는부서별로 1 행의출력이있습니다. 각각의집계결과는각부서에맞는테이블행전체에대한계산결과입니다. 다음과같이, HAVING 어구를사용하여그룹화된행을구별할수있습니다. SELECT deptno, MAX (sal) FROM emp GROUP BY deptno HAVING AVG (sal)> 2000; deptno max (2 rows) 이쿼리는평균월급이 2000 달러가넘는부서만을출력합니다. 마지막으로, 다음쿼리는애널리스트의평균월급이 2000 달러가넘는부서에서애널리스트의 가장높은급료만을출력합니다. SELECT deptno, MAX (sal) FROM emp WHERE job = 'ANALYST'GROUP BY deptno HAVING AVG (sal)> 2000; deptno max (1 row) 51
52 WHERE 절과 HAVING 절에미묘한차이가있습니다. WHERE 절은그룹이나집계를계산하기 전에입을선택합니다. 한편 HAVING 절은그룹과집계를계산하면, 그룹화된행을선택합니다. 앞의예제에서는애널리스트의직원전용입니다. 그중에서, 애널리스트를부서별로그룹화하고, 애널리스트의평균월급이 2000 달러이상그룹만을마지막결과합니다. 그결과, 부서번호 20 그룹에만적용되며그중가장높은애널리스트의월급은 3000 달러입니다 업데이트 UPDATE 명령을사용하여기존행의열값을업데이트할수있습니다. 예를들면, 다음명령은 관리자모두에대해 10% 절감을하기전과후를보여줍니다. SELECT ename, sal FROM emp WHERE job = 'MANAGER'; ename sal JONES BLAKE CLARK (3 rows) UPDATE emp SET sal = sal * 1.1 WHERE job = 'MANAGER'; SELECT ename, sal FROM emp WHERE job = 'MANAGER'; ename sal JONES BLAKE
53 CLARK (3 rows) 삭제 DELETE 명령을사용하여테이블에서행을삭제할수있습니다. 예를들면, 다음명령은부서 번호 20 의모든직원을제거하기전과후를보여줍니다. SELECT ename, deptno FROM emp; ename deptno SMITH 20 ALLEN 30 WARD 30 JONES 20 MARTIN 30 BLAKE 30 CLARK 10 SCOTT 20 KING 10 TURNER 30 ADAMS 20 JAMES 30 FORD 20 MILLER 10 (14 rows) 53
54 DELETE FROM emp WHERE deptno = 20; SELECT ename, deptno FROM emp; ename deptno ALLEN 30 WARD 30 MARTIN 30 BLAKE 30 CLARK 10 KING 10 TURNER 30 JAMES 30 MILLER 10 아래와같이 WHERE 구없이 DELETE 명령문이주어지는것을주의해주십시오. 이명령문은 주어진그것을떠나완전히비어있는모든행을지울것입니다. 그시스템은이것을하기전에 확정을요구되지않을것입니다. 2.2 고급제반기능 이전장에서는 Postgres Plus Advanced Server 에서 SQL 을사용하여데이터를저장하거나접속할 기본사항을설명했습니다. 이장에서는관리를단순화하고, 데이터손실및손상을방지하는 SQL 의고급기능에대해설명합니다 뷰 우선다음 SELECT 명령을보십시오. SELECT ename, sal, sal * 24 AS yearly_salary, deptno FROM emp; 54
55 ename sal yearly_salary deptno SMITH ALLEN WARD JONES MARTIN BLAKE CLARK SCOTT KING TURNER ADAMS JAMES FORD MILLER (14 rows) 이것을반복되는쿼리일경우, 아래에서보이는뷰를생성할때마다전체 SELECT 명령을다시 타이핑하는것없이쿼리의속기방식을사용할수있습니다. CREATE VIEW employee_pay AS SELECT ename, sal, sal * 24 AS yearly_salary, deptno FROM emp; employee_pay 뷰는쿼리로인해일반테이블처럼사용할수있습니다. SELECT * FROM employee_pay; ename sal yearly_salary deptno 55
56 SMITH ALLEN WARD JONES MARTIN BLAKE CLARK SCOTT KING TURNER ADAMS JAMES FORD MILLER (14 rows) 뷰의사용자의자유로운측면은좋은 SQL 데이터베이스를디자인하데중요한측면이다. 테이블 구조의세부정보를캡슐화하므로애플리케이션업데이트를통해테이블구조가바뀌었다 하더라도일관된인터페이스 - 페이스를유지할수있습니다. 의견의자유를사용하여 SQL 데이터베이스를만드는좋은디자인의핵심측면이다. 뷰는실제테이블에사용할수있는대부분의경우에사용할수있습니다. 뷰에대한보기를 만드는것은일반적입니다 외래키 모든직원을유요한부서에소속하기를웝합니다. 이것을데이터참조무결성유지보수라고 합니다. 가장간단한데이터베이스는 dept 테이블에일치하는행이있는지여부를먼저 확인하고, emp 테이블에새직원레코드를삽입하거나거부하도록구현해야합니다. 이방법에는 56
57 많은문제가있어매우불편합니다. Postgres Plus Advanced Server 에서는이것을좀더쉽게얻을 수있습니다. 여기서는제 장의 emp 테이블에외래키제약조건을추가하도록변경합니다. 수정된 emp 테이블은다음과같습니다. CREATE TABLE emp ( empno NUMBER (4) NOT NULL CONSTRAINT emp_pk PRIMARY KEY, ename VARCHAR2 (10), job VARCHAR2 (9) mgr NUMBER (4), hiredate DATE, sal NUMBER (7,2), comm NUMBER (7,2), deptno NUMBER (2) CONSTRAINT emp_ref_dept_fk REFERENCES dept (deptno) ); 샘플 emp 테이블에다음 INSERT 명령을실행하면외래키제약조건 emp_ref_dept_fk 는부서 번호 50 가 dept 테이블에있는지확인합니다. 그러나없기때문에명령이거부됩니다. INSERT INTO emp VALUES (8000, 'JONES', 'CLERK', 7902, '17 - AUG - 07 ', 1200, NULL, 50); ERROR : insert or update on table "emp"violates foreign key constraint "emp_ref_dept_fk" DETAIL : Key (deptno) = (50) is not present in table "dept" 외부키의기능으로응용프로그램을훌륭하게조율되었습니다. 외래키를올바르게사용하면 틀림없이데이터베이스응용프로그램의질을향상시킬수있으므로프로그램의향상에몰두하고 있습니다 ROWNUM 가짜열 57
58 ROWNUM 은가짜열입니다. 쿼리에서의순서에따라각행에고유오름차순숫자가지정됩니다. 따라서처음에복구하는줄은 ROWNUM 로 1 가할당됩니다. 2 번째줄은 2 에지정되며 다음처럼나타납니다. 이기능은다음과같이쿼리에서복구행수를제한하는데사용할수있습니다. SELECT empno, ename, job FROM emp WHERE ROWNUM <5; empno ename job SMITH CLERK 7499 ALLEN SALESMAN 7521 WARD SALESMAN 7566 JONES MANAGER (4 rows) ROWNUM 값은결과를정렬하기전에각행에할당됩니다. 따라서 ORDER BY 절이지정되면 결과는정렬됩니다. ROWNUM 값은다음과같이반드시오름차순으로하지않습니다. SELECT ROWNUM, empno, ename, job FROM emp WHERE ROWNUM <5 ORDER BY ename; rownum empno ename job ALLEN SALESMAN JONES MANAGER SMITH CLERK WARD SALESMAN (4 rows) 다음은 jobhist 테이블의각행에일련번호를추가하는방법을보여줍니다. 먼저 seqno 라는새 열을테이블에추가합니다. 그리고, UPDATE 명령 seqno 에 ROWNUM 을설정합니다. 58
59 ALTER TABLE jobhist ADD seqno NUMBER (3); UPDATE jobhist SET seqno = ROWNUM; 다음 SELECT 명령새로운 seqno 열의값을표시합니다. SELECT seqno, empno, TO_CHAR (startdate, 'DD - MON - YY') AS start, job FROM jobhist; seqno empno start job DEC - 80 CLERK FEB - 81 SALESMAN FEB - 81 SALESMAN APR - 81 MANAGER SEP - 81 SALESMAN MAY - 81 MANAGER JUN - 81 MANAGER APR - 87 CLERK APR - 88 CLERK MAY - 90 ANALYST NOV - 81 PRESIDENT SEP - 81 SALESMAN MAY - 87 CLERK DEC - 81 CLERK JAN - 83 CLERK DEC - 81 ANALYST JAN - 82 CLERK (17 rows) 59
60 2.2.4 동의어 동의어는 SQL 문장에서데이터베이스개체를다른이름으로참조하는데사용되는 ID 입니다. 동의어를만들수있는데이터베이스개체유형은테이블, 뷰, 시퀀스, 다른동의어입니다. 동의어에는공용동의어와개인동의어의 2 종류가있습니다. 공용동의어는데이터베이스에서널리사용할수있고데이터베이스클러스터의모든사용자가볼수있습니다. 공용동의어는어떤스키마에도속하지않습니다. 한편개인동의어는특정스키마에속합니다. 현재 Postgres Plus Advanced Server 에서는공용동의어만을지원합니다 공용동의어만들기 CREATE PUBLIC SYNONYM 명령공용동의어를만들수있습니다. 공용동의어는기존의 동의어로사용되지않은식별자를지정해야합니다. 다음은명령의예입니다. CREATE PUBLIC SYNONYM personnel FOR enterprisedb.emp; 이로써 DDL 과 DML 의두 SQL 문장에서 personnel 동의어를사용하여 enterprisedb 스키마의 emp 테이블을볼수있습니다. INSERT INTO personnel VALUES (8142, 'ANDERSON', 'CLERK', 7902, '17 - DEC - 06 ', 1300, NULL, 20); SELECT * FROM personnel; empno ename job mgr hiredate sal comm deptno SMITH CLERK DEC :00: ALLEN SALESMAN FEB :00: WARD SALESMAN FEB :00: JONES MANAGER APR :00:
61 7654 MARTIN SALESMAN SEP :00: BLAKE MANAGER MAY :00: CLARK MANAGER JUN :00: SCOTT ANALYST APR :00: KING PRESIDENT 17 - NOV :00: TURNER SALESMAN SEP :00: ADAMS CLERK MAY :00: JAMES CLERK DEC :00: FORD ANALYST DEC :00: MILLER CLERK JAN :00: ANDERSON CLERK DEC :00: (15 rows) 자세한내용은 CREATE PUBLIC SYNONYM 명령을참조하십시오 공용동의어삭제 DROP PUBLIC SYNONYM 명령공용동의어를제거할수있습니다. 다음은방금만든 personnel 동의어를삭제합니다. DROP PUBLIC SYNONYM personnel; 자세한내용은 DROP PUBLIC SYNONYM 명령을참조하십시오 공용동의어네임스페이스 공용동의어는동일한데이터베이스의다른동의어와같은이름을지정할수없습니다. 즉, 공용 동의어는기존스키마테이블, 뷰및기타데이터베이스개체와같은이름을사용할수있습니다. 따라서다음절에서설명한대로, 검색경로에있는다른객체에동일한이름을사용하는경우, 예상치못한사건을겪지않도록공용동의어의이름을신중하게결정해야합니다 공용동의어의이름확인및검색경로 61
62 이름은 SQL 명령에사용되는개체를정확하게파악하기위한것입니다. 개체가스키마이름으로 확정되면, 개체는스키마이름으로한정하는것이바람직합니다. 그러나개체가자격이되지 않는경우객체의위치를확인하기위해일련의작업을수행합니다. 자격이되지않는개체는 SQL 명령에지정된경우, 먼저현재의검색경로에사용자가액세스할 수있는스키마를확인합니다. 그래도그개체가없을경우에만이름이공용동의어인지 데이터베이스에서확인합니다. 그것이동의어인경우공용동의어로확인됩니다. 즉, SQL 명령에사용을위해정의된공용동의어는있지만현재검색경로를통해사용자가 액세스할수있는스키마에같은이름의개체가존재하는경우지정된이름은공개동의어는 검색경로의개체로이름해결할수있습니다 공용동의어및권한 모든사용자가공용동의어를만들수있습니다. 공용동의어를만드는데특별한권한이필요하지않습니다. 또한, 모든사용자가 SQL 명령에서공용동의어를볼수있습니다. 그러나 SQL 명령을실행하면, 동의어로견장붙은데이터베이스개체에대해현재사용자의권한을확인합니다. 사용자가개체에적절한권한을가지고있지않은경우 SQL 명령이실패합니다 계층쿼리 계층쿼리는친자관계를형성하는데이터를기반으로계층적으로결과행을반환쿼리입니다. 계층구조는전형적인트리구조로표현됩니다. 트리는상호연결된노드로구성됩니다. 각노드는끝노드이거나자식노드와연결합니다. 또한각노드는부모가없는첫번째노드 ( 루트노드라고부른다 ) 을제외하고는 1 개의부모노드와연결합니다. 각트리는반드시 1 개의루트노드를갖습니다. 자식노드가없는노드 ( 끝노드 ) 를리프노드라고합니다. 트리는항상적어도 1 개의리프노드를갖습니다. 예를들면, 트리가 1 개의노드로만구성되는경우노드는루트노드이며, 리프노드이다. 계층쿼리는결과행은여러트리노드를표현합니다. 주의 : 1 개의줄이여러트리에존재하고결과사이에여러번나오는경우가있습니다. 쿼리계층관계는결과에친자관계를형성하는 CONNECT BY 어구로표현됩니다. SELECT 명령에사용되는 CONNECT BY 어구및관련어구문맥은다음과같습니다. SELECT select_list FROM table_expression [WHERE...] [START WITH start_expression] 62
63 CONNECT BY (PRIOR p arent_expr = child_expr child_expr = PRIOR parent_expr) [ORDER SIBLINGS BY column1 [ASC DESC] [, column2 [ASC DESC]... [GROUP BY...] [HAVING...] [other...] select_list 결과행을여러표현식입니다. table_expression 결과행을검색하는다른테이블이나 뷰를. other 는다른 SELECT 명령에서지원되는어구입니다. 계층쿼리에관계있는어구, START WITH, CONNECT BY, ORDER SIBLINGS BY 는다음의항목에서설명합니다 친자관계의정의 결과행친자관계, CONNECT BY 어구에의해결정됩니다. CONNECT BY 절은 Equal 연산자 (=) 로비교되는 2 개로구성해야합니다. 또한, 이 2 개의식중하나전에 PRIOR 키워드를 지정해야합니다. 모든결과행에대해다음과같이자식노드를결정합니다. 1. 결과행에대해 parent_expr 을평가합니다. 2. table_expression 에서파생된다른결과행에대해 child_expr 을평가합니다. 3. parent_expr = child_expr 의경우 child_expr 에평가된줄은 parent_expr 에평가된행 ( 부모 노드 ) 의자식노드는것입니다. 4. table_expression 에서파생된나머지모든결과행에대해평가를반복합니다. 3 단계의 요구에응하는모든행이지정된부모노드의자식노드입니다. 주의 : 행이자식노드를결정하기위한평가는 WHERE 절이 table_expression 에적용되기전에 모든결과행에대해실행됩니다. 이제위의단계에자식노드로결정한각노드를부모노드로, 이평가를차례로반복하여트리 구조를완성하겠습니다. 더이상자식노드가있는노드가없는경우등급이종료됩니다. 자식 노드가없는노드 ( 끝노드 ) 가리프노드입니다. 63
64 CONNECT BY 절을포함하는 SELECT 명령은일반적으로 START WITH 어구를포함합니다. START WITH 절은루트노드가될행을결정합니다. 즉, 위의단계에서처음으로부모노드가 될행을결정합니다. 이에대해서는다음절에서더설명합니다 루트노드선택 START WITH 절은 table_expression 에서얻어진결과줄에루트노드로사용하는행위를결정합니다. table_expression 에서파생되는모든결과행을즉 start_expression 의평가가 " 진정한 " 인줄은트리의루트노드가될수있습니다. 트리를형성할수있는횟수는루트노드의수와같습니다. 결과적으로, START WITH 어구가생략되면 table_expression 에서파생되는모든결과행을자체적으로트리의루트노드입니다 예제응용프로그램에서트리만들기 샘플응용프로그램 emp 테이블을생각해볼수있습니다. emp 테이블줄은 mgr 열 ( 관리자의직원 ID 를포함 ) 기준으로계층구조를형성합니다. 각직원은많아 1 명의관리자가있습니다. KING 은이회사사장이기때문에관리자가없습니다. 따라서 KING 의 mgr 열은 null 입니다. 또한한직원이여러직원의관리자가될수있습니다. 이관계는아래그림과같이전형적인트리구조, 계층조직을형성합니다. 그림 2 직원계층조직 이관계를기반으로하는계층쿼리를실행하려면 SELECT 명령에 CONNECT BY PRIOR empno = mgr 절을추가합니다. 예를들면, 직원 ID 7839 사장 KING 을생각하면 mgr 열이 7839 직원은 KING 의직속부하입니다. 해당직원은 JONES, BLAKE, CLARK 입니다. ( 그들은 KING 자식 64
65 노드입니다.) 마찬가지로직원 JONES 을생각하면 mgr 열이 7566 과다른직원은 JONES 자식 노드입니다. 이예에서는 SCOTT 과 FORD. 조직도상위 KING 이고, 이트리에서루트노드는 1 입니다. STAR T WITH mgr IS NULL 어구를 지정하기위한첫번째루트노드로 KING 선택할수있습니다. 완전한 SELECT 명령은다음과같습니다. SELECT ename, empno, mgr FROM emp START WITH mgr IS NULL CONNECT BY PRIOR empno = mgr; 쿼리출력은루트에서리프까지왼쪽에서오른쪽으로각분기를표시합니다. 다음은이쿼리의결과입니다. ename empno mgr KING 7839 JONES SCOTT ADAMS FORD SMITH BLAKE ALLEN WARD MARTIN TURNER JAMES CLARK
66 MILLER (14 rows) 노드수준 LEVEL 은 SELECT 명령에사용할수있는가짜열입니다. 결과의각행에대해 LEVEL 는 0 이 아니다. 노드계층의깊이를나타내는숫자를반환합니다. 루트노드 LEVEL 은 1 입니다. 루트 노드아래의하위 LEVEL 은 2 입니다. 다음처럼나옵니다. 다음쿼리는, LEVEL 가짜열을추가하여위의쿼리를수정합니다. 또한 LEVEL 값을통해직원이름이들여쓰기되어각줄의계층의깊이가강조되고있습니다. SELECT LEVEL, LPAD ( '', 2 * (LEVEL - 1)) ename "employee", empno, mgr FROM emp START WITH mgr IS NULL CONNECT BY PRIOR empno = mgr; 다음은쿼리의결과입니다. level employee empno mgr KING JONES SCOTT ADAMS FORD SMITH BLAKE ALLEN WARD MARTIN TURNER
67 3 JAMES CLARK MILLER (14 rows) 형제노드정렬 일반적으로부모가있고동일한노드수준에있는노드들을형제노드라고합니다. 예를들면, 위의출력은직원 ALLEN, WARD, MARTIN, TURNER, JAMES 이형제노드입니다. 이들은레벨 3 에있어부모노드가 BLAKE 입니다. JONES, BLAKE, CLARK 도형제노드입니다. 이들은 2 단계에있고, 부모노드가 KING. ORDER SIBLINGS BY 절을사용하여선택된열의값형제노드를오름차순또는내림차순으로 정렬할수있습니다. 이것은계층쿼리에서만사용할수있는 ORDER BY 절이특별한 경우입니다. ORDER SIBLINGS BY ename ASC 어구를추가하여위의쿼리을더수정합니다. SELECT LEVEL, LPAD ( '', 2 * (LEVEL - 1)) ename "employee", empno, mgr FROM emp START WITH mgr IS NULL CONNECT BY PRIOR empno = mgr ORDER SIBLINGS BY ename ASC; 출력은형제노드이름으로오름차순으로정렬되도록수정합니다. 부모노드 KING 의밑의형제노드 BLAKE, CLARK, JONES 는알파벳순서로나열되어있습니다. 부모노드 BLAKE 의밑의형제노드 ALLEN, JAMES, MARTIN, TURNER, WARD 도알파벳순서로나열되어있습니다. 기타도마찬가지입니다. level employee empno mgr KING BLAKE
68 3 ALLEN JAMES MARTIN TURNER WARD CLARK MILLER JONES FORD SMITH SCOTT ADAMS (14 rows) 마지막예제에서는 WHERE 절을추가하여더많은 3 개의루트노드를지정합니다. 노드트리가구성되면 WHERE 절에의해트리노드가강화되고, 결과가나타납니다. SELECT LEVEL, LPAD ( '', 2 * (LEVEL - 1)) ename "employee", empno, mgr FROM emp WHERE mgr IN (7839, 7782, 7902, 7788) START WITH ename IN ( 'BLAKE', 'CLARK', 'JONES') CONNECT BY PRIOR empno = mgr ORDER SIBLINGS BY ename ASC; 이쿼리의결과는 3 개의루트노드 (Level 1) 이표시됩니다. BLAKE, CLARK, JONES 입니다. 또한 WHERE 절에조건을충족하지않는부분은기록에서삭제됩니다. level employee empno mgr BLAKE CLARK
69 2 MILLER JONES SMITH ADAMS (6 rows) 제 3 장 SQL 언어 이장에서는 Oracle 과호환되는 Postgres Plus Advanced Server SQL 언어를설명합니다. 이 장에서설명하는 SQL 구문, 명령, 데이터타입, 함수등은 Postgres Plus Advanced Server 와 Oracle 모두에서사용할수있습니다. Oracle 과호환되지않는 " Postgres Plus Advanced Server SQL " 의다른사양은 Postgres Plus documentation 에설명되어있습니다. 따라서이설명서에있지않은특정기능은 Postgres Plus documentation 에있는구문과명령을사용하여설명될수있습니다. 이장은다음항목으로구성됩니다. Postgres Plus Advanced Server SQL 구문및언어요소에대한일반적인설명 데이터형 SQL 명령개요 내장함수 3.1 SQL 구문 이장에서는 SQL 의일반적인문법을설명합니다. 이단원의내용은데이터정의및변경을 위해 SQL 명령을적용하는방법에대해자세히설명하는이후의장을이해하는데기초가됩니다 어휘구성 SQL 입력은명령으로이루어집니다. 명령은토큰으로구성되며마지막은세미콜론 ( ";") 으로 끝납니다. 입력스트림종료역시명령을끝내고어떤토큰을사용할수있는지특정명령구문에 따라다릅니다. 토큰은키워드, 식별자, 인용부호로묶인식별자, 리터럴 ( 또는상수 ), 또는특수문자기호입니다. 토큰은공백 ( 스페이스, 탭, 줄바꿈 ) 으로구분되지만, 모호함이없는경우 ( 일반적으로특수문자가다른토큰형식과인접하여있는경우 ) 필요없습니다. 69
70 또한입력된 SQL 에주석이있어도상관없습니다. 코멘트는토큰이아니지만, 그효과는공백과 동일합니다. 예를들면, 다음은 ( 문법적으로 ) 올바른 SQL 입력입니다. SELECT * FROM MY_TABLE; UPDATE MY_TABLE SET A = 5; INSERT INTO MY_TABLE VALUES (3, 'hi there'); 이경우는 1 줄에 1 개의명령을설명하는 3 개의명령을지속하고있습니다 ( 반드시 1 개의 명령을 1 줄로쓸필요는없습니다. 1 줄에여러명령을입력하는것도가능하며, 1 개의명령을 여러줄에작성할수있습니다 ). SQL 구문은어떤토큰이명령을확인하고, 어느것이피연산자또는매개변수인지식별하는것에관해서는그다지일관성있지않습니다. 처음몇토큰은일반적으로명령이름입니다. 따라서위의예제에서 "SELECT", "UPDATE", "INSERT" 명령에대한일반적인설명입니다. 그러나, 예를들어, UPDATE 명령은 SET 토큰이특정위치에항상기술되어야하고, INSERT 명령의특별한경우, 명령을완결하려면 VALUES 토큰이필요합니다. 각명령의정확한구문규칙은 3.3 장에서설명되어있습니다 식별자와키워드 위의예제에나오는 SELECT, UPDATE 또는 VALUES 같은토큰은키워드의예제입니다. 키워드는 SQL 언어에서고정된의미가있는단어입니다. MY_TABLE 토큰및 A 토큰은식별자의예입니다. 이들이사용되는명령은테이블, 열, 다른데이터베이스객체의이름을식별합니다. 따라서단순히 " 이름 " 이라고도합니다. 키워드와식별자는동일한어휘구조를갖고있으므로언어를알지못하면토큰이식별자또는키워드인지를잘모를수있습니다. SQL 식별자와키워드는문자 (a-z 또는 A-Z) 로시작해야합니다. 식별자또는키워드내에서 문자다음으로문자, 밑줄, 숫자 (0-9), 달러기호 ($), 숫자기호 (#) 를사용할수있습니다. 식별자및키워드이름은대소문자를구분하지않습니다. 따라서 UPDATE MY_TABLE SET A = 5; 는다음문장과동일합니다. update my_table SeT a = 5; 규약에서는키워드를대문자로, 이름을소문자로씁니다. 예를들면다음과같습니다. 70
71 UPDATE my_table SET a = 5; 식별자는부수적인종류가있습니다. 구분식별자또는따옴표 ( 인용부호 ) 가내장된식별자입니다. 이식별자의문자는큰따옴표 (") 로묶어표시합니다. 구분된식별자는항상식별자이고, 키워드가아닙니다. 그래서 "select" 는 "select" 라는이름의열또는테이블을조회하는데사용할수있습니다. 반면에, 인용부호를붙이지않은 select 는키워드로이해되기때문에테이블또는열이름이예상되는부분에서는문법상에러가발생합니다. 인용부호를붙인식별자는다음예제와같이쓸수있습니다.. UPDATE "my_table"set "a"= 5; 인용부호를붙인식별자는문자코드 0 을제외하고, 모든문자를사용할수있습니다. ( 큰따옴표를포함시킬경우에는인용부호를 2 개입력 ). 이것은평소사용할수없는공백이나앰퍼샌드 (&) 가포함된테이블및열이름을만들수있습니다. 이경우에도길이제약이적용됩니다. 인용부호가붙지않는이름은항상소문자로해석되지만식별자를인용해서대소문자를구분합니다. 예를들면, 식별자 FOO, foo "foo" 는 Postgres Plus Advanced Server 에서는동일한것으로해석되지만 "Foo" 와 "FOO" 는이들 3 개와또한서로다른것으로해석됩니다. (Postgres Plus Advanced Server 가인용부호가붙지않은이름을소문자로해석하는것은 Oracle 호환성부분이아닙니다. Oracle 에서인용부호가붙지않는이름은대문자로해석하므로 Oracle 에서 foo 는 "FOO" 와동일하며, "foo" 는다릅니다. 만약이식가능한애플리케이션을쓰고싶다면, 특정이름에항상따옴표를사용하거나아예인용부호를붙이지않는것이좋습니다 ) 상수 Postgres Plus Advanced Server 에는문자열과숫자라는암묵적인형의상수가있습니다. 상수는 명시적인타입으로지정할수도있고, 이경우시스템을통해보다정확한표현과효율적인 작업이가능합니다. 이들의다른방법은나중에설명합니다 문자열 SQL 에서문자열은단일인용부호 ( ') 로둘러싸모든일련의문자입니다. 예를들면, 'This is a string' 입니다. 문자열에있는단일인용부호작성방법은연속적으로단일인용부호를 2 번작성하는것입니다. 예를들면, 'Dianne' 'shorse' 입니다. 큰따옴표 ( ") 와동일하지않은사항에유의하십시오 숫자상수 71
72 숫자상수는다음의일반적인형태로받아들입니다. digits digits [digits] [e [+ -] digits] [digits]. digits [e [+ -] digits] digits e [+ -] digits 여기서 digits 는 1 개또는그이상의 10 진수숫자 (0 ~ 9) 입니다. 소수점을사용하려면적어도 1 개의숫자를소수점전이나후에두어야합니다. 지수상징 e 표를붙이는형식을사용하는경우에는 e 후에적어도 1 개의숫자를두어야합니다. 공백이나다른문자는상수속에포함시킬수없습니다. + 혹은 - 기호를앞에붙이는것은, 상수로간주되지않음을주의하세요. 이기호는상수에적용되는연산자로간주됩니다. 다음은유효한숫자상수의몇가지예입니다 e e - 3 소수점도지수도포함되지않은숫자상수의경우우선값이 INTEGER 형 (32 비트 ) 을충족하면 INTEGER 형식으로간주됩니다. 그렇지않으면 BIGINT 형 (64 비트 ) 에적합하면 BIGINT 형식으로간주됩니다. 둘다아니면, NUMBER 형식으로간주됩니다. 상수를소수점또는지수또는둘모두를포함하는경우에는항상첫째로 NUMBER 형식으로간주됩니다. 숫자상수에처음으로부여되는데이터형은형식확인알고리즘의시작점에불과합니다. 대부분의경우, 상수는상황에따라자동으로올바른형식이할당됩니다. 필요하면이후의장에서 설명된것처럼, 캐스팅하여숫자가데이터형으로해석되도록시행할수있습니다 다른형식의상수 임의의형식의상수는다음표기법을사용하여입력될수있습니다. CAST ( 'string' AS type) 72
73 문자열텍스트는 type 으로불리는형식의입력변환루틴으로전달됩니다. 결과는지정된형식의상수입니다. 명시적인타입캐스팅은상수가어떤형식이되어야할지에대해모호함이없는경우 ( 예를들면상수가직접테이블열에할당되었을경우 ), 생략해도무방합니다. 이경우자동으로형식이강제됩니다. CAST 는임의의식의런타임형식변환을지정하는데에도사용할수있습니다 코멘트 코멘트는이중대시기호 (--) 로시작하는모든문자의행, 행의말미까지포함합니다. 예를들면 다음과같습니다. -- This is a standard SQL comment 이외에도 C 언어양식의블록코멘트를사용할수있습니다. / * multiline comment * block * / 코멘트는 / * 로시작하며 * / 로끝납니다. 코멘트는이후구문분석전에입력스트림에서삭제되고, 공백으로적절히대체합니다. 3.2 자료형 다음표는범용의내장된데이터형을나타냅니다. 표 3-1 데이터형 명칭이명설명 BLOB LONG RAW, RAW (n) 이진데이터 BOOLEAN 논리값 (True / False) CHAR [(n) CHARACTER [(n) n 문자의고정길이문자열 CLOB LONG, LONG VARCHAR 긴문자열 DATE TIMESTAMP (0) 날짜와시간 DOUBLE PRECISION FLOAT, 배정밀도부동소수점 FLOAT (25) - FLOAT (53) 73
74 INTEGER INT, BINARY_INTEGER 4 바이트부호있는정수 NUMBER DEC, DECIMAL, NUMERIC 선택할수있는소수자리의 정확한수치 NUMBER (p [, s) DEC (p [, s), DECIMAL (p [, s), 최대정밀숫자 P, 선택가능한 스케일 s NUMERIC (p [, s) REAL FLOAT (1) - FLOAT (24) 단정밀도부동소수점 TIMESTAMP [(p) VARCHAR2 (n) CH AR VARYING (n),character VARYING (n),varchar (n) 날짜와시간에포함된선택 가능한초소수점이하의정밀도 p 가변길이문자열 ( 최대길이 n 자 ) 다음장에서는각데이터형을자세히설명합니다 숫자데이터형 숫자데이터형은 4 바이트정수, 4 바이트및 8 바이트부동소수점및고정된정밀소수점이 있습니다. 다음의표에서사용가능한형식을열거합니다. 3-2 숫자데이터형 모델명 저장크기 설명 범위 INTEGER 4 바이트 일반적으로사용하는정수 - 2,147,483,648 에서 +2,147,483,647 NUMBER 가변길이 사용자지정정밀도, 정확 최대 1000 자리 NUMBER (p [, s) 가변길이최대정밀숫자 p, 선택가능한 스케일 s 최대 1000 자리 REAL 4 바이트가변정밀도, 부정확 6 자리정밀도 DOUBLE PRECISION 8 바이트가변정밀도, 부정확 15 자리정밀도 다음절에서데이터형에대해자세히설명합니다. 74
75 정수데이터형 INTEGER 형은다양한범위의정수즉, 소수점이없는수를유지합니다. 허용범위를벗어난값을 저장하려고하면에러가발생합니다 임의의정확도를가진수 NUMBER 형은최대 1000 자리의정밀도로값을저장할수있고, 정확한계산을할수있습니다. 통화금액및기타정확도가요구되는수량을저장할때특히이형을추천합니다. 그러나, NUMBER 형은다음절에서설명하는부동소수점데이터유형에비해아주낮습니다. 다음설명은이와같은용어를사용합니다. NUMBER 의 scale 은소수점의오른쪽자릿수를말합니다. NUMBER 의정확도는숫자전체자릿수입니다. 즉, 소수점의양측자리수의합계입니다. 따라서 라는수치의정확도는 6, scale 은 4 입니다. 정수는 0 의 scale 을갖는다고간주됩니다. NUMBER 형의 scale 및정밀도는모두설정할수있습니다. 열의데이터형을 NUMBER 로 선언하려면다음구문을사용합니다. NUMBER (precision, scale) 정확도는양수, 스케일은 0 또는양수여야합니다. 그밖에 NUMBER (precision) 는스케일이 0 인것을선택합니다. NUMBER 위와같이정확도또는 scale 을지정하지않은경우, 구현되는한계정확도까지어떠한정확도또는스케일의값을저장할수있는열이생성됩니다. 이러한열은어떤특정한스케일에대해서입력을강요하는것은아니지만, 선언한스케일을가진 NUMBER 열이입력값의스케일을강요합니다. ( 표준 SQL 은기본적으로스케일 0 을요구하고있어정수에대한정확도를강제하고있습니다. 최대이식성을위해, 항상정확도와스케일을명시적으로설정해야합니다 ). 정확도나값의스케일이선언된정확도또는열의스케일보다큰경우, 시스템은값을 반올림합니다. 선언된한계치를충족시키기위해값이반올림할수없는경우, 에러가발생합니다 부동소수점데이터형 75
76 REAL 과 DOUBLE PRECISION 형은부정확한가변정밀숫자데이터형입니다. 실제로, 이 데이터형은사용하는프로세서, 운영체제및컴파일러로지원되어, 일반적으로 ( 각각단정밀도 및배정밀도 ) 이진부동소수점연산에서 IEEE 표준 754 를구현한것입니다. 부정확은내부형으로정확하게변환되지않은값, 그리고근사치로저장되는값을의미합니다. 그래서저장하는값과출력되는값에약간의차이가있습니다. 이러한에러를처리하고계산을통해어떻게전달할것인가, 수학및컴퓨터과학전반에관한것으로, 다음사항을제외하고더이상은설명되지않습니다. ( 금액과같은 ) 정확한저장과계산이필요할때는, 대신 NUMBER 데이터형을사용하세요. 이데이터형에서무언가중요한건에대해복잡한계산을필요로할때, 특히 ( 무한대또는 언더플로와같은 ) 경계선에서어떤종류의행동에대해신뢰를설정해야하는경우구현을 신중하게검증해야합니다. 2 개의부동소수점값의동일성비교는예상대로또는예상대로되지않을때도있습니다. 대부분의플랫폼에서 REAL 은최소 6 자리의정밀도를가지고적어도 1E E +37 범위의값입니다. DOUBLE PRECISION 은최소 15 자리의정밀도를가진약 1E 에서 1E +308 범위의값입니다. 너무크고너무작은값은에러의원인이됩니다. 입력값의정밀도가높은팔경우반올림을할수있습니다. 제로에한없이가까운값으로, 게다가영과는다른것으로간주되지않는수치는언더플로에러가발생할수있습니다. 또한, Postgres Plus Advanced Server 는부정확한숫자를규정하는표준 SQL 의 FLOAT 와 FLOAT (p) 를지원합니다. 여기서 p 는 2 진수자릿수에서최소허용하는정밀도를지정합니다. Postgres Plus Advanced Server 는 FLOAT (1) 에서 FLOAT (24) 까지 REAL 형을지정한것으로취급하고, FLOAT (25) 에서 FLOAT (53) 까지 DOUBLE PRECISION 를지정한것으로취급합니다. 허용오차 p 이외의값은에러가발생합니다. 정확도를지정하지않는 FLOAT 는 DOUBLE PRECISION 로해석됩니다 문자형식 다음은 Postgres Plus Advanced Server 에서사용할수있는범용문자형식을보여줍니다. 표 3-3 문자형식 CHAR [(n) CLOB 모델명 설명 고정길이, 공백매움 1GB 까지가변길이 76
77 VARCHAR2 (n) 상한을갖는가변길이 2 개주요문자데이터형은 CHAR (n) 와 VARCHAR2 (n) 입니다. 여기서 n 은양의정수입니다. 이데이터형은 2 개모두 n 문자길이의문자열을저장할수있습니다. CHAR 형으로 n 이생략되면기본값은 1 입니다. 보다긴문자열을이러한형의열로저장하려할때, 초과하는문자가모두공백인경우를제외하고, 최대길이로잘립니다. 만일선언한길이보다문자열이짧은경우, CHAR 값은공백으로채웁니다. VARCHAR2 값은보다짧은문자열로저장됩니다. 명시적으로값을 VARCHAR2 (n) 또는 CHAR (n) 으로변환하는경우, 지정된길이를초과하면 에러발생없이 n 자로잘립니다. ( 이것은표준 SQL 의사양입니다.) CHAR 형의값은지정길이 n 까지공백으로채우고, 그대로저장및표시됩니다. 그러나채워진공백은의미적으로중요하지않은것으로처리됩니다. 2 개의 CHAR 값을비교할때마지막공백은무시됩니다. 또한 CHAR 값을다른문자열로변환하기위해서는삭제됩니다. VARCHAR2 형의값에서마지막공백은의미적으로중요한요소이므로주의해야한다. 3 번째문자데이터형은 CLOB 입니다. 이것은긴문자열을저장하는데사용됩니다. 길이제한을 지정하지않는것을제외하고, CLOB 는의미적으로 VARCHAR2 와같습니다. 일반적으로, 최대 글자의길이가얼마가될지모를경우, VARCHAR2 아니라 CLOB 을사용합니다. CLOB 형으로저장할수있는가장긴문자크기는약 1GB 입니다. 이러한 3 가지종류의데이터용량사양은문자열이 127 바이트보다작을때원래문자열에 1 을더합니다. 문자열이 127 이상인경우, 4 바이트를원래의문자열에더한다. CHAR 일경우에는, 채워넣는데저장할곳이필요하다. 긴문자열은시스템에서자동적으로축소됩니다. 따라서디스크의하드웨어사양은줄어들수도있습니다. 긴값은또한더짧은값에대한빠른액세스를방해하지않도록배경테이블에저장됩니다. 데이터베이스의문자집합은텍스트값을저장하기위해사용하는문자집합을결정합니다 이진데이터형 BLOB 데이터형은이진문자열을저장할수있습니다. 표 3-4 이진문자열데이터형 모델명저장크기설명 77
78 BLOB 이진문자열이 127 바이트보다작은경우, 실제이진문자열길이에 1 바이트를더한다. 127 바이트보다큰경우, 4 바이트를더한다. 가변길이이진문자열 이진문자열은 octet ( 바이트 ) 의연속입니다. 이진문자열이문자열과다른점은다음의 2 가지입니다. 1 번째는이진문자열은 0 octet 과다른 " 출력할수없는 " octet ( 보통 32 에서 126 까지의범위를벗어나는바이트 ) 을저장할수있습니다. 2 번째는이진문자열을계산하면실제바이트가처리되는반면문자열인코딩및프로세싱은로케일설정에따른다는것입니다 날짜 / 시간데이터형 다음의날짜 / 시간데이터형에대한설명은테이블을작성하거나변경할 때 edb_redwood_date 설정매개변수가 true 로설정되어있다고가정합니다. Postgres Plus Advanced Server 에서는다음표에제시된날짜 / 시간데이터형을지원합니다. 표 3-5 날짜 / 시간데이터형 모델명 저장 설명 가장멀리 가장멀리 정확도 크기 과거 미래 DATE 8 바이트날짜와시간 4713 BC AD 1 초 TIMESTAMP [(p) 8 바이트날짜와시간 4713 BC AD 1 μ 초 데이터정의언어 (DDL) 명령, CREATE TABLE 또는 ALTER TABLE 에서열의 데이터형으로 DATE 를사용하는경우시간테이블정의를데이터베이스에저장할 때 DATE 은 TIMESTAMP (0) 으로변환됩니다. 따라서시간도날짜와함께열에저장됩니다. SPL 내의선언부분에변수의데이터형으로프로시저와함수에매개변수의데이터형으로또는 함수의반환데이터형으로, DATE 를사용하는경우항상 TIMESTAMP (0) 으로변환됩니다. 따라서 시간을처리할수있습니다. TIMESTAMP 에서는초필드에보유되는값의소수자릿수를지정하는정밀도값인 옵션 p 를취할수있습니다. P 의허용범위는 0 부터 6 까지입니다. 기본적으로 6 입니다. TIMESTAMP 값을배정밀도부동소수점숫자로저장하는경우 ( 현재는기본 ), 효과적인정확도의한계는 6 보다더작은지도모릅니다. TIMESTAMP 값은 자정을기준으로한경과시간 ( 초 ) 으로저장됩니다. 마이크로초의정확도는 에서몇년이내의날짜가높지만, 정확도는날짜가 ( 부터 ) 멀어질수록하락합니다. TIMESTAMP 값이 8 78
79 바이트정수 ( 컴파일시옵션지정 ) 로저장되는경우에는마이크로초정확도는모든범위의값을 사용할수있습니다. 그러나 8 바이트 TIMESTAMP 에서는위에서제시된 4713 BC 에서 AD 까지의날짜범위보다제한이있습니다 날짜 / 시간입력 날짜와시간입력은 ISO 8601 SQL 호환형식, Oracle 기본서식 dd - MON yy, 다른날짜를 정확하게표현하는형식을수용한다. 그러나잘못해석되는것을피하기위해 TO_DATE 함수를 사용하는것이좋습니다. 제 장을참조하십시오. 텍스트문자열처럼날짜와시간리터럴은작은따옴표로묶어야합니다. 다음표준 SQL 구문 사용할수있습니다. type 'value' type 은 DATE 또는 TIMESTAMP 중하나입니다. value 는날짜 / 시간문자열입니다 날짜 다음의표는날짜입력이가능한서식의일부를보여줍니다. 모두 1999 년 1 월 8 일입니다. 표 3-6 날짜입력 예 January 8, Jan 08 Jan Jan Jan 99 Jan 날짜값은 DATE 또는 TIMESTAMP 형식의열과변수에할당할수있습니다. 날짜값과시간값이 추가되지않으면, 시, 분, 초필드에 0 이설정됩니다. 79
80 시간 다음은 DATE 또는 TIMESTAMP 형식의시간예제를보여줍니다. 표 3-7 시간입력 예 설명 04:05: ISO :05:06 ISO :05 ISO ISO :05 AM 04:05 와같다. AM 은값에영향을주지 않습니다. 04:05 PM 16:05 와같다. 시간입력은 12 이하여야 합니다 타임스탬프 TIMESTAMP 형식에유효한입력은날짜와시간의세트로구성됩니다. 날짜부분은표 3-6 날짜 입력에예제와같은형식입니다. 시간부분은표 3-7 시간입력에예제와같은형식입니다. 다음은 Oracle 의기본형식을따르는타임스탬프의예입니다 JAN :05:06 다음은 ISO 8601 표준형식을따르는타임스탬프의예입니다 :05: 날짜 / 시간출력 날짜와시간의기본출력형식은 Redwood date style 로불리는 Oracle 호환서식 (dd - MON - yy) 이나 ISO 8601 형식 (yyyy - mm - dd) 입니다. 이형식은데이터베이스의애플리케이션인터페이스따라달라질수있습니다. SQL Interactive 같이 JDBC 를사용하는애플리케이션에서는항상 ISO 8601 형식의날짜가제시됩니다. PSQL 와같은다른애플리케이션에서는 Oracle 호환형식의날짜로제시됩니다. 다음은 Oracle 호환과 ISO 8601 의 2 개의출력형식의예를보여줍니다. 표 3-8 날짜 / 시간출력형식 80
81 설명 예 Oracle 호환 31 - DEC :37:16 ISO 8601 / 표준 SQL :37: 내부자료 Postgres Plus Advanced Server 는모든날짜와시간계산에율리우스일을사용하고 있습니다. 이것은 1 년이 일이라고추정하고기원전 4713 년부터 미래까지모든날짜를정확하게예측하거나계산하는우수한특성을가지고있습니다 논리값데이터형 Postgres Plus Advanced Server 는표준 SQL 의 BOOLEAN 형식이 제공됩니다. BOOLEAN 은 "true( 참 )" 혹은 "false( 거짓 )" 라는 2 가지값중하나를취할수 있습니다. 제 3 의상황인, "unknown" 은 SQL 의 null 값으로표시됩니다. 표 3-9 논리값데이터형 모델명저장크기설명 BOOLEAN 1 바이트논리값 (True / False) "true( 참 )" 인상황에대한효과적인리터럴값은 TRUE 입니다. "false( 거짓 )" 상황에대한효과적인 리터럴값은 FALSE 입니다. 참고 : BOOLEAN 형은 SPL 프로그램에서변수선언에서만사용할수있습니다. 테이블열의 데이터유형을정의하기위해서는사용할수없습니다. 3.3 SQL 명령 이장에서는 Postgres Plus Advanced Server 에서지원하는 Oracle 호환 SQL 명령을 설명합니다. 이장의 SQL 명령은 Oracle 데이터베이스와 Postgres Plus Advanced Server 데이터베이스에서작동합니다. 다음사항에유의하십시오. 81
82 Postgres Plus Advanced Server 는여기에서열거되지않은명령을지원합니다. 그명령은 Oracle 과호환되지않습니다. 또는 Oracle SQL 명령과유사하거나동일한기능을제공하지만구문이다릅니다. 이장에서는 SQL 명령이유효한모든구문, 옵션및기능을필수적으로설명하지않습니다. Oracle 과호환되지않는구문, 옵션및기능은명령설명에서생략합니다. Postgres Plus documentation set 에서는 Oracle 과호환되지않는명령의사양도설명하고있습니다 ALTER INDEX 이름 ALTER INDEX - 인덱스정의를변경한다 개요 ALTER INDEX name RENAME TO new_name 설명 ALTER INDEX 는기존의인덱스의정의를변경합니다. RENAME 구문은인덱스의이름을 변경합니다. 저장된데이터에는영향을주지않습니다. 매개변수 name 수정할기존인덱스이름 ( 스키마로수식된이름도가능 ). new_name 인덱스의새로운이름입니다. 예 기존의인덱스의이름을바꿉니다. 82
83 ALTER INDEX name_idx RENAME TO empname_idx; 관련항목 CREATE INDEX, DROP INDEX ALTER ROLE 이름 ALTER ROLE - 데이터베이스역할을변경한다 개요 ALTER ROLE name IDENTIFIED BY password 설명 ALTER ROLE 는역할의패스워드를변경합니다. 슈퍼유저또는 CREATEROLE 권한이있는사용자만이이명령을사용할수있습니다. 수정할역할에 SUPERUSER 속성이있는경우에는, 슈퍼유저만이명령을사용할수있습니다. 역할에 LOGIN 속성이없는경우, 패스워드는의미가없습니다. 매개변수 name 패스워드를변경하는역할의이름입니다. password 역할의새패스워드입니다. 주석 구성원자격변경은 GRANT 와 REVOKE 를사용하십시오. 예 83
84 역할의패스워드를변경합니다. ALTER ROLE admins IDENTIFIED BY xyrp35z; 관련항목 CREATE ROLE, DROP ROLE, GRANT, REVOKE, SET ROLE ALTER SEQUENCE 이름 ALTER SEQUENCE 시퀀스생성기의정의를변경한다 개요 ALTER SEQUENCE name [INCREMENT BY increment] [MINVALUE minvalue] [MAXVALUE m axvalue] [CACHE cache NOCACHE] [CYCLE] 설명 ALTER SEQUENCE 는기존시퀀스생성기의매개변수를변경합니다. ALTER SEQUENCE 로지정되지 않은매개변수는이전설정이유지됩니다. 매개변수 name 변경될시퀀스의이름 ( 스키마로수식된이름도가능 ). increment INCREMENT BY increment 어구는선택사항입니다. 양수값은오름차순시퀀스, 음수값은 내림차순시퀀스를만듭니다. 지정하지않은경우, 이전값이유지됩니다. minvalue 84
85 MINVALUE minvalue 는시퀀스생성기가생성하는최소값을결정합니다. 지정하지않으면, 현재의 최소값을유지합니다. NO MINVALUE 가지정된경우, 오름차순때는 1 내림차순때는 이 기본입니다. NO MINVALUE 키워드는 Oracle 과의호환성이없습니다. maxvalue MAXVALUE maxvalue 는시퀀스생성기가생성하는최대값을결정합니다. 지정하지않으면, 현재의 최대값이유지됩니다. NO MAXVALUE 를지정하면오름차순때는 내림차순때는 -1 이 기본입니다. NO MAXVALUE 키워드는 Oracle 과의호환성이없습니다. cache CACHE cache 어구를사용하면접속을가속화하기위해시퀀스번호를미리할당하고메모리에 저장할수있습니다. 최소값은 1 입니다. ( 한번에발생하는값이 1 단지이기때문에캐시가없는 상태가됩니다. 즉, NOCACHE) 지정이없는경우, 이전캐시값이유지됩니다. CYCLE CYCLE 옵션을사용하면시퀀스가한계 ( 오름차순의경우 maxvalue 내림차순의경우 minvalue) 에이르렀을때그순서를회전시킬수있습니다. 한계에이르렀을때, 다음생성되는번호는오름차순경우 minvalue 내림차순의경우 maxvalue 입니다. 지정이없는경우, 이전설정이유지됩니다. NO CYCLE 키워드를지정하면, 시퀀스의한계에도달한후에회전되지않습니다. NO CYCLE 키워드는 Oracle 과의호환성이없습니다. 주석 동일한시퀀스로번호를취득하는트랜잭션의동시차단을방지하기위해, ALTER SEQUENCE 를 롤백하지않습니다. ALTER SEQUENCE 변경사항은즉시적용되며취소할수없습니다. ALTER SEQUENCE 는백엔드의 NEXTVAL 결과에대해서는신속하게효력을발휘하지않습니다. 이 백엔드는미리할당된 ( 캐시된 ) 시퀀스값을가지고있으며, 이값이모두다떨어진후변경된 시퀀스를만드는매개변수를검색할수있습니다. 현재의백엔드는즉각변경됩니다. 예 serial 이라는시퀀스의증가량과캐시값을수정합니다. ALTER SEQUENCE serial INCREMENT BY 2 CACHE 5; 관련항목 85
86 CREATE SEQUENCE, DROP SEQUENCE ALTER SESSION 이름 ALTER SESSION - 런타임매개변수를변경한다 개요 ALTER SESSION SET name = value 설명 ALTER SESSION 명령은런타임설정매개변수를변경합니다. ALTER SESSION 은현재세션에서사용되는값에만영향을줍니다. 이매개변수의일부는 Oracle 호환을위해서만사용되고 Postgres Plus Advanced Server 런타임에는아무런영향을미치지않습니다. 다른매개변수는 Postgres Plus Advanced Server 데이터베이스서버에대응하는런타임설정매개변수를변경합니다. 매개변수 name 설정가능한런타임매개변수의이름입니다. 사용할수있는매개변수는다음과같습니다. value 매개변수의새로운값입니다. 설정매개변수 ALTER SESSION 명령을사용하여, 다음의설정매개변수를변경할수있습니다. NLS_DATE_FORMAT (string) 날짜및시각형식을지정합니다. 이것은애매한날짜입력값에대한규칙이됩니다. Postgres Plus Advanced Server 에서의 datestyle 런타임설정매개변수도마찬가지입니다. NLS_LANGUAGE (string) 86
87 표시되는메시지의언어를설정합니다. Postgres Plus Advanced Server 에서의 lc_messages 매개변수도마찬가지입니다. NLS_LENGTH_SEMANTICS (string) BYTE 또는 CHAR 중하나를선택할수있습니다. 기본값은 BYTE 입니다. 이 매개변수는 Oracle 호환을위해서만제공되며, Postgres Plus Advanced Server 에서는아무런 영향을미치지않습니다. OPTIMIZER_MODE (string) 쿼리시기본 Optimizer 모드를설정합니다. ALL_ROWS, CHOOSE, FIRST_ROWS, FIRST_ROWS_10, FI RST_ROWS_100, FIRST_ROWS_1000 을지정할수 있습니다. 기본값은 CHOOSE 입니다. 자세한내용은 3.4 장을참조하십시오. QUERY_REWRITE_ENABLED (string) TRUE, FALSE, FORCE 를지정할수있습니다. 기본값은 FALSE 입니다. 이 매개변수는 Oracle 호환을위해서만제공되며, Postgres Plus Advanced Server 에서는아무런 영향을미치지않습니다. QUERY_REWRITE_ INTEGRITY (string) ENFORCED, TRUSTED, STALE_TOLERATED 을지정할수있습니다. 기본값은 ENFORCED 입니다. 이 매개변수는 Oracle 호환을위해서만제공되며, Postgres Plus Advanced Server 에서는아무런 영향을미치지않습니다. 예 UTF - 8 인코딩에서영어 (US) 언어를설정합니다. 이예제에서값, en_us.utf 8 은 Postgres Plus Advanced Server 에지정된형식입니다. 이형식은 Oracle 호환이없으므로주의하세요. ALTER SESSION SET NLS_LANGUAGE = 'en_us.utf - 8'; 날짜형식을지정합니다. ALTER SESSION SET NLS_DATE_FORMAT = 'dd / mm / yyyy'; ALTER TABLE 87
88 이름 ALTER TABLE - 테이블정의를변경한다 개요 ALTER TABLE name action [...] ALTER TABLE name RENAME COLUMN column TO new_column ALTER TABLE name RENAME TO new_name 여기서 action 은다음중하나입니다. ADD column type [column_constraint [...] DROP COLUMN column ADD table_constraint DROP CONSTRAINT constraint_name [CASCADE] 설명 ALTER TABLE 은기존테이블정의를변경합니다. 이명령은다음과같은서브폼 (subform) 이 있습니다. ADD column type 이구문을사용하면 CREATE TABLE 과같은구문을사용하여새열을테이블에추가할수 있습니다. DROP COLUMN 이구문을사용하면테이블에서열을삭제할수있습니다. 삭제할열을포함하는인덱스및 테이블제약도자동으로삭제됩니다. ADD table_constraint 이구문을사용하면 CREATE TABLE 과같은구문을사용하여새로운제약을테이블에추가할수 있습니다. DROP CONSTRAINT 88
89 이구문을사용하면테이블에지정된제약을제거할수있습니다. 현재, 테이블제약은유일한 이름을요구하지않습니다. 따라서지정된이름과일치하는여러제약이있을수있습니다. 이 경우일치하는모든제약이삭제됩니다. RENAME RENAME 구문을사용하면테이블 ( 또는인덱스, 시퀀스또는뷰 ) 이름이나테이블의개별열 이름을변경할수있습니다. 저장된데이터에는영향을미치지않습니다. ALTER TABLE 명령을사용하려면변경할테이블을소유하고있어야합니다. 매개변수 name 변경될기존테이블의이름 ( 스키마로수식된이름도가능 ) 입니다. column 신규또는기존열의이름입니다. new_column 기존열의새로운이름입니다. new_name 테이블의새이름입니다. type 새로운열의데이터형입니다. table_constraint 테이블의새로운테이블제약입니다. constraint_name 삭제할기존제약의이름입니다. CASCADE 89
90 삭제된제약에의존하는객체를자동으로삭제합니다. 주석 ADD COLUMN 으로열을추가했을때, 테이블의기존행에추가된행은모두 기본값 (DEFAULT 가지정되지않은경우 null) 으로초기화됩니다. null 이아닌기본값이있는열을추가하려면테이블전체의갱신이필요합니다. 테이블이거대한 경우, 이작업에많은시간을소모할수있습니다. 또일시적으로 2 배의디스크공간이 필요합니다. CHECK 또는 NOT NULL 제약조건을추가할때는기존행이제약을준수하는지확인하기위해 테이블검사가필요합니다. DROP COLUMN 구문은열을물리적으로제거하지않고 SQL 운영을비가시화시킵니다. 이명령을실행하면테이블에삽입하거나갱신하면삭제된열에는 null 값이포함되어있습니다. 따라서열삭제는신속하게수행할수있습니다. 그러나삭제된열이차지했던공간이아직회수되지않아테이블디스크크기가즉시줄어들지않습니다. 이공간은이후기존행을갱신하는시기에수거합니다. 시스템카탈로그테이블의내용은어떠한부분변경이허용되지않습니다. 유효한매개변수에대한자세한설명은 CREATE TABLE 을참조하십시오. 예 VARCHAR2 형의열을테이블에추가합니다. ALTER TABLE emp ADD address VARCHAR2 (30); 테이블에서열을삭제합니다. ALTER TABLE emp DROP COLUMN address; 기존열이름을변경합니다. ALTER TABLE emp RENAME COLUMN address TO city; 기존테이블의이름을변경합니다. ALTER TABLE emp RENAME TO employee; 90
91 테이블에 check 제약을부여합니다. ALTER TABLE emp ADD CONSTRAINT sal_chk CHECK (sal> 500); 테이블에서 check 제약조건을삭제합니다. ALTER TABLE emp DROP CONSTRAINT sal_chk; 관련항목 CREATE TABLE, DROP TABLE ALTER TABLESPACE 이름 ALTER TABLESPACE - 테이블스페이스정의를변경합니다. 개요 ALTER TABLESPACE name RENAME TO newname 설명 ALTER TABLESPACE 테이블스페이스의정의를변경합니다. 매개변수 name 기존테이블스페이스의이름입니다. newname 새테이블스페이스의이름입니다. pg_ 로시작하는이름은시스템테이블스페이스를위해 예약되어사용할수없습니다. 예 empspace 테이블스페이스를 employee_space 라는이름으로변경합니다. 91
92 ALTER TABLESPACE empspace RENAME TO employee_space; 관련항목 DROP TABLESPACE ALTER USER 이름 ALTER USER 데이터베이스사용자계정을변경한다 개요 ALTER USER name IDENTIFIED BY password 설명 ALTER USER 는 Postgres Plus Advanced Server 사용자계정의패스워드를 변경합니다. 데이터베이스슈퍼유저또는 CREATEROLE 권한이있는사용자가이드명령을사용할 수있습니다. 일반사용자도자신의패스워드를변경하기위해이명령을사용할수있습니다. 매개변수 name 패스워드를변경할사용자의이름입니다. password 이계정에대한새패스워드입니다. 예 사용자의패스워드를변경합니다. ALTER USER john IDENTIFIED BY xyz; 관련항목 92
93 CREATE USER, DROP USER COMMENT 이름 COMMENT - 객체의코멘트를정의하거나변경한다 개요 COMMENT ON ( TABLE table_name COLUMN table_name. c olumn_name ) IS 'text' 설명 COMMENT 는데이터베이스객체에대한코멘트를저장합니다. 코멘트를변경하려면동일한객체에대해새로운 COMMENT 명령을실행하세요. 각객체에저장할수있는코멘트문자열은 1 개뿐입니다. 코멘트를제거하려면, 텍스트부분에빈문자열 ( 중간에공백없이단일따옴표를 2 번연속사용 ) 를작성하십시오. 객체가삭제되었을때, 코멘트는자동으로삭제됩니다. 매개변수 table_name 코멘트를추가하는테이블의이름입니다. 테이블이름은스키마수식이가능합니다. table_name. column_name 코멘트를추가하는 table_name 테이블의열이름입니다. 테이블이름은스키마수식이 가능합니다. text 새로운코멘트입니다. 주석 93
94 현재코멘트는보안메커니즘이존재하지않습니다. 데이터베이스에연결하는사용자는누구든지데이터베이스에있는객체의코멘트를볼수있습니다 ( 단, 소유하지않는객체에대한코멘트를변경할수있는것은슈퍼유저뿐입니다.) 따라서코멘트는보안에중요한정보를제공하지않습니다. 예 emp 테이블에코멘트처리합니다. COMMENT ON TABLE emp IS 'Current employee information'; emp 테이블 empno 열에코멘트처리합니다. COMMENT ON COLUMN emp.empno IS 'Employee identification number'; 이와같은코멘트를삭제합니다. COMMENT ON TABLE emp IS ''; COMMENT ON COLUMN emp.empno IS ''; COMMIT 이름 COMMIT - 현재트랜잭션을커밋합니다 개요 COMMIT [WORK] 설명 COMMIT 은현재트랜잭션을커밋합니다. 트랜잭션으로생긴모든변경사항이다른사람에게 가시화되고, 크래쉬가발생해도일관성이보장됩니다. 매개변수 WORK 선택적키워드입니다. 아무효과가없습니다. 94
95 주석 트랜잭션을중단하려면 ROLLBACK 을사용하십시오. 트랜잭션외부에서 COMMIT 을발행하는것은특별한문제가발생하지않습니다. SPL 프로그램안에 COMMIT 은지원되지않습니다. 예 현재 transaction 을커밋하고, 모든변경사항을유지합니다. COMMIT; 관련항목 ROLLBACK, ROLLBACK TO SAVEPOINT, SAVEPOINT CREATE DATABASE 이름 CREATE DATABASE - 새로운데이터베이스를생성합니다 개요 CREATE DATABASE name 설명 CREATE DATABASE 는새로운데이터베이스를생성합니다. 데이터베이스를생성하려면, 슈퍼유저또는특별한 CREATEDB 권한이있는사용자여야 합니다. 일반적으로데이터베이스생성자가새데이터베이스소유자가됩니다. CREATEDB 권한을 보유하는비슈퍼유저는그들이소유하는데이터베이스만생성할수있습니다. 새데이터베이스는표준시스템데이터베이스 template1 을복제하여생성됩니다. 매개변수 95
96 name 생성할데이터베이스의이름입니다. 주석 CREATE DATABASE 는트랜잭션블록내부에서실행할수없습니다. 대부분의경우 "could not initialize database directory" 이라는행이포함된에러는데이터 디렉토리의권한부족, 디스크공간부족등의파일시스템에대한문제와관련된것입니다. 예 새데이터베이스를생성합니다. CREATE DATABASE employees; CREATE DATABASE LINK 이름 CREATE DATABASE LINK - 새로운데이터베이스링크를생성합니다 개요 CREATE [PUBLIC] DATABASE LINK name CONNECT TO username IDENTIFIED BY 'password' USING (libpq 'host = hostname port = portnum dbname = database' [oci] '/ / hostname / database') 설명 CREATE DATABASE LINK 는새로운데이터베이스링크를만듭니다. 데이터베이스링크는 DELETE, INSERT, SELECT, UPDATE 명령내에서원격데이터베이스의테이블또는뷰를참조할수있는객체입니다. 데이터베이스링크는 SQL 를추가함으로써참조될수있습니다. dblink 는데이터베이스링크의이름입니다. 데이터베이스링크에는 public 또는 private 이있습니다. public 데이터베이스링크는모든 사용자가사용할수있습니다. private 데이터베이스링크는데이터베이스링크소유자만사용할 96
97 수있습니다. PUBLIC 옵션을사용하면 public 데이터베이스링크를만듭니다. 이옵션을생략하면 private 데이터베이스링크가생성됩니다. CREATE DATABASE LINK 명령을실행하면, 데이터베이스링크이름과지정된속성이 Postgres Plus Advanced Server 의 pg_catalog.edb_dblink 라는시스템테이블에저장됩니다. 데이터베이스링크를사용하는경우에는데이터베이스링크를정의하는 edb_dblink 엔트리가있는데이터베이스를로컬데이터베이스라고합니다. 그리고 edb_dblink 엔트리에서정의한속성을가진대상서버및데이터베이스를원격데이터베이스라고합니다. 데이터베이스링크에대한참조를포함하는 SQL 명령은로컬데이터베이스에연결할때 dblink 를포함하는 SQL 명령은원격데이터베이스에대한적절한인증과 접속을실행하여, 테이블및뷰에액세스할수있도록합니다. 매개변수 PUBLIC 모든사용자가사용할수있는 public 데이터베이스링크를만듭니다. 이매개변수가생략된경우, private 데이터베이스링크가되어, 데이터베이스링크소유자만사용할수있습니다. name 생성하는데이터베이스링크의이름입니다. username 원격데이터베이스에접속할때의사용자이름입니다. password username 의패스워드입니다. libpq 원격 Postgres Plus Advanced Server 데이터베이스의접속을지정합니다. oci 원격 Oracle 데이터베이스의접속을지정합니다. 매개변수가생략되면기본값입니다. hostname 97
98 원격데이터베이스서버의이름이나 IP 주소입니다. portnum 원격데이터베이스서버에접속할수있는포트번호입니다. database 원격데이터베이스의이름입니다. 주석 원격 Oracle 데이터베이스에데이터베이스링크를참조하는 SQL 명령이실행되는경우, 서버는 디스크상의 Oracle 이설치되어있는위치를알필요가있습니다. Oracle 설치가올바른 Home 디렉토리로설정되어 Postgres Plus Advanced Server 가시작하도록하는 2 가지방법이있습니다. 환경변수 ORACLE_HOME 이올바른디렉토리로설정되어있을수있습니다. 이것이기본 Oracle 환경변수설정입니다. postgresql.conf 의환경설정변수 oracle_home 은 Postgres Plus Advanced Server 를파일시스템내의올바른 Oracle Home 디렉토리로설정되도록지시합니다. oracle_home 에대한정보는 장을참조하세요. 예 다음예제는다음과같이가정합니다. Postgres Plus Advanced Server 샘플애플리케이션의 emp 테이블의복사본을 Oracle 데이터베이스에서만듭니다. 두번째샘플애플리케이션이있는 Postgres Plus Advanced Server 클러스터는포트번호 5443 에서접속을수용합니다. oralink 라는 public 데이터베이스링크를생성합니다. Oracle 데이터베이스의이름은 xe, IP 주소는 , 포트번호는 1521 입니다. 또한 Oracle 데이터베이스에접속하기위한사용자이름은 edb, 패스워드는 password 입니다. CREATE PUBLIC DATABASE LINK oralink CONNECT TO edb IDENTIFIED BY 'password'using '/ / /xe'; oralink 라는데이터베이스링크를사용하여 Oracle 데이터베이스의 emp 테이블에서 SELECT 명령을실행합니다. SELECT * FROM oralink; 98
99 empno ename job mgr hiredate sal comm deptno SMITH CLERK DEC :00: ALLEN SALESMAN FEB :00: WARD SALESMAN FEB :00: JONES MANAGER APR :00: MARTIN SALESMAN SEP :00: BLAKE MANAGER MAY :00: CLARK MANAGER JUN :00: SCOTT ANALYST APR :00: KING PRESIDENT 17 - NOV :00: TURNER SALESMAN SEP :00: ADAMS CLERK MAY :00: JAMES CLERK DEC :00: FORD ANALYST DEC :00: MILLER CLERK JAN :00: (14 rows) edblink 라는 private 데이터베이스링크를만듭니다. Postgres Plus Advanced Server 데이터베이스이름은 edb, 위치는 localhost, 링크할수있는포트번호는 5443 입니다. 또한 Postgres Plus Advanced Server 데이터베이스에접속하기위한사용자이름은 enterprisedb, 패스워드는 password 입니다. CREATE DATABASE LINK edblink CONNECT TO enterprisedb IDENTIFIED BY 'password' USING libpq 'host = localhost port = 5443 dbname = edb'; 로컬 edb_dblink 의시스템테이블에서데이터베이스링크 oralink 과 edblink 의속성을 표시합니다. SELECT lnkname, lnkuser, lnkconnstr FROM pg_catalog.edb_dblink; lnkname lnkuser lnkconnstr oralink edb / / /xe edblink enterprisedb host = localhost port = 5443 dbname = edb (2 rows) 99
100 Oracle 데이터베이스의 emp 테이블과 Postgres Plus Advanced Server 데이터베이스의 dept 테이블을조인합니다. SELECT d.deptno, d.dname, e.empno, e.ename, e.job, e.sal, e.comm FROM oralink e, edblink d WHERE e.deptno = d.deptno ORDER BY 1, 3; deptno dname empno ename job sal comm ACCOUNTING 7782 CLARK MANAGER ACCOUNTING 7839 KING PRESIDENT ACCOUNTING 7934 MILLER CLERK RESEARCH 7369 SMITH CLERK RESEARCH 7566 JONES MANAGER RESEARCH 7788 SCOTT ANALYST RESEARCH 7876 ADAMS CLERK RESEARCH 7902 FORD ANALYST SALES 7499 ALLEN SALESMAN SALES 7521 WARD SALESMAN SALES 7654 MARTIN SALESMAN SALES 7698 BLAKE MANAGER SALES 7844 TURNER SALESMAN SALES 7900 JAMES CLERK 950 (14 rows) 관련항목 DROP DATABASE LINK CREATE DIRECTORY 이름 CREATE DIRECTORY - 파일시스템디렉토리경로로별칭을생성합니다. 개요 CREATE DIRECTORY name AS 'pathname' 100
101 설명 CREATE DIRECTORY 명령은파일시스템디렉토리경로로별칭을만듭니다. UTL_FILE 패키지프로그램에적절한매개변수로별칭이지정된경우에는운영체제의파일은다른이름에해당하는디렉토리에생성되거나, 또는그디렉토리에접근할수있습니다. UTL_FILE 패키지에대한자세한내용은 7.4 장을참조하십시오. 매개변수 name 디렉토리경로별칭입니다. pathname 별칭과관련된디렉토리의절대경로입니다. CREATE DIRECTORY 명령은운영체제의디렉토리를 생성하지않습니다. 실제디렉토리는적절한운영체제의명령을사용하여독립적으로생성되어야 합니다. 주석 UTL_FILE 패키지가디렉토리에파일을만들거나디렉토리의파일을읽을수있다면, 운영체제의 사용자 ID enterprisedb 는해당디렉토리에적절한읽기 / 쓰기권한이있어야합니다. 디렉토리경로별칭을삭제하려면 pg_catalog.edb_dir 시스템카탈로그테이블에서직접 삭제되어야합니다. 이작업은슈퍼유저가수행해야합니다. edb_dir 는 Oracle 과호환되지않는 것에주의하세요. 디렉토리경로별칭을삭제해도해당파일시스템의실제디렉토리는제거되지않습니다. 실제 디렉토리는적절한운영체제명령으로제거해야합니다. Linux 시스템에서디렉토리이름의구분기호는슬래시 (/) 입니다. Windows 시스템에서디렉토리이름구분기호는슬래시 (/) 또는 2 개의백슬래시 (\\) 로지정할수있습니다. 예 Linux 의디렉토리 / tmp / empdir 에 empdir 라는별칭을만듭니다. CREATE DIRECTORY empdir AS '/ tmp / empdir'; 101
102 Windows 의디렉토리 C : \ TEMP \ EMPDIR 에 empdir 라는별칭을만듭니다. CREATE DIRECTORY empdir AS 'C : \ TEMP / EMPDIR'; 모든디렉토리경로별칭을표시합니다. SELECT * FROM pg_catalog.edb_dir; dirname dirpath empdir C : / TEMP / EMPDIR (1 row) 디렉토리경로별칭 empdir 를삭제합니다. DELETE FROM pg_catalog.edb_dir WHERE dirname = 'empdir'; CREATE FUNCTION 이름 CREATE FUNCTION - 새로운함수를정의한합니다 개요 CREATE [OR REPLACE] FUNCTION name [(argname [IN IN OUT OUT] argtype [DEFAULT value] [,...])] RETURN rettype [AUTHID (DEFINER CURRENT_USER)] (IS AS) [declaration] [...] BEGIN statement; [...] [EXCEPTION (WHEN exception [OR exception] [...] THEN statement; [...]) [...] ] END [name] 102
103 설명 CREATE FUNCTION 은새로운함수를정의합니다. CREATE OR REPLACE FUNCTION 은새로운 함수를만들거나기존정의를대체합니다. 스키마이름이포함된경우, 함수는지정된스키마에서생성됩니다. 스키마이름이없으면, 함수는현재스키마에서생성됩니다. 같은스키마에서동일한인수데이터형의기존함수의이름은새로운함수의이름으로사용할수없습니다. 그러나다른인수데이터형을갖는함수의경우, 이름이중복되어도 ( 이것을오버로딩이라합니다 ). ( 함수오버로딩은 Postgres Plus Advanced Server 기능입니다. 저장된함수의오버로딩은 Oracle 과호환하지않습니다.) 기존의함수정의를갱신하려면, CREATE OR REPLACE FUNCTION 을사용하십시오. 이방법은함수이름과인수형을변경할수없다는것을기억하십시오 ( 이렇게하면새로다른함수가생성됩니다 ). 또한 CREATE OR REPLACE FUNCTION 는기존함수의반환형을변경할수없습니다. 반환형을변경하려면, 해당함수를삭제하고다시만들어야합니다. 함수를만든사용자가해당함수의소유자입니다. 함수에대한자세한정보는 장을참조하십시오. 매개변수 name 생성하는함수의이름 ( 스키마로수식된이름도가능 ) 입니다. argname 인수의이름입니다. 인수는함수본문안에이름에서참조될수있습니다. IN IN OUT OUT 인수모드입니다. IN 은입력전용의인수임을선언합니다. 이것이 기본값입니다. IN OUT 는인수가값을받고, 반환하는것을허용합니다. OUT 은출력전용의 인수임을선언합니다. argtype 함수의인수데이터형입니다. 기본데이터형또는테이블컬럼에대한참조를사용할수있습니다. 모든기본데이터형에길이를지정하지않습니다. 예를들면, VARCHAR2 (10) 이아닌 VARCHAR2 로지정합니다. 103
104 컬럼은 tablename. columnname % TYPE 을작성하여참조됩니다. 이것을사용하면테이블 정의가변경되더라도함수가영향을받지않도록하는데유용합니다. DEFAULT value 함수를호출할때인수가전달되지않으면입력인수로기본값이사용됩니다. 인수의모드가 IN OUT 또는 OUT 인경우, DEFAULT 를지정하지않습니다. rettype 함수에서반환하는데이터형입니다. argtype 처럼, rettype 에도길이를지정하지않습니다. DEFINER CURRENT_USER 함수에서참조하는데이터베이스객체에대한액세스권한을결정하기위해기능의소유자권한 (DEFINER) 를사용하는지, 함수를실행하여현재사용자의권한 (CURRENT_USER) 를사용하는지지정합니다. 또한, DEFINER 에서는자격이되지않는데이터베이스객체를참조하기위해기능소유자의검색경로를사용합니다. 한편 CURRENT_USER 에서는함수를실행하여현재사용자의검색경로를사용합니다. DEFINER 가기본입니다. declaration 변수, 형, REF CURSOR 선언입니다. statement SPL 프로그램문장입니다. DECLARE - BEGIN - END 블록은 SPL 문장으로간주된다는점에 유의하시기바랍니다. 따라서함수내부에중첩된블록이있을수있습니다. exception NO_DATA_FOUND, OTHERS 와같은예외상황의이름입니다. 주석 Postgres Plus Advanced Server 는함수오버로딩을허용합니다. 즉, 인수형이다른경우에여러 함수에같은이름을사용할수있습니다. 예 104
105 emp_comp 함수는 2 개의입력인수와 1 개의반환값을취합니다. 다음 SELECT 명령함수를 사용하는방법을설명합니다. CREATE OR REPLACE FUNCTION emp_comp ( p_sal NUMBER, p_comm NUMBER ) RETURN NUMBER IS BEGIN RETURN (p_sal + NVL (p_comm, 0)) * 24; END; SELECT ename "Name", sal "Salary"comm "Commission"emp_comp (sal, comm) "Total Compensation"FROM emp; Name Salary Commission Total Compensation SMITH ALLEN WARD JONES MARTIN BLAKE CLARK SCOTT KING TURNER ADAMS JAMES FORD MILLER (14 rows) sal_range 함수는월급이지정된범위에있는종업원의수를반환합니다. 다음함수호출은첫 번째 2 개의호출에기본인수를사용합니다. CREATE OR REPLACE FUNCTION sal_range ( p_sal_min NUMBER DEFAULT 0, p_sal_max NUMBER DEFAULT
106 ) RETURN INTEGER IS v_count INTEGER; BEGIN SELECT COUNT (*) INTO v_count FROM emp WHERE sal BETWEEN p_sal_min AND p_sal_max; RETURN v_count; END; BEGIN DBMS_OUTPUT.PUT_LINE ( 'Number of employees with a salary :' sal_range); DBMS_OUTPUT.PUT_LINE ( 'Number of employees with a salary of at least' '$ :' sal_range ( )); DBMS_OUTPUT.PUT_LINE ( 'Number of employees with a salary between' '$ and $ :' sal_range ( , )); END; Number of employees with a salary : 14 Number of employees with a salary of at least $ : 6 Number of employees with a salary between $ and $ : 5 관련항목 DROP FUNCTION CREATE INDEX 이름 CREATE INDEX - 새인덱스를정의한다 개요 CREATE [UNIQUE] INDEX name ON table ((column (expression))) [TABLESPACE tablespace] 106
107 설명 CREATE INDEX 는지정한테이블에서 name 인덱스를만듭니다. 인덱스는주로데이터베이스의 성능향상을위해사용됩니다 ( 그러나인덱스를잘못사용하면성능이저하될수있습니다 ). 인덱스키필드는열이름, 또는괄호로둘러싸인표현식으로지정됩니다. 여러열에대한 인덱스를만들때는여러필드를지정할수있습니다. 인덱스필드로테이블행의 1 개이상열값을계산하는방식을지정할수있습니다. 이기능은원본데이터에대한변환값을기준으로하는데이터에대한빠른액세스하는수단으로사용할수있습니다. 예를들면, UPPER (col) 의계산에따른인덱스는인덱스를사용하기위해 WHERE UPPER (col) = 'JIM' 어구를허용합니다. Postgres Plus Advanced Server 는 B - tree 인덱스메소드를제공합니다. B - tree 인덱스메소드는 Lehman - Yao high - concurrency B trees 를구현한것입니다. 기본적으로인덱스는 IS NULL 어구를사용하지않습니다. 인덱스의정의에사용되는모든함수와연산자는 " 불변 "(immutable) 해야합니다. 즉, 결과는입력인수에의존하고 ( 다른테이블의내용또는현재시간과같은 ) 외부의영향을받을수없습니다. 이제약은인덱스작업이충분히정의되어있는것을확인할수있습니다. 인덱스식에서사용자정의함수를사용하려면, 함수를생성할때 immutable 옵션을붙이는것을잊지마세요. 매개변수 UNIQUE 인덱스 ( 이미데이터가있는상황에서 ) 를만들때, 테이블에각각의시간데이터를추가할때 테이블의값이중복되지않았는지확인합니다. 데이터를삽입하거나갱신할때는중복엔트리의 결과가나오면서, 에러가발생합니다. name 생성되는인덱스의이름입니다. 스키마이름을여기에포함시킬수없습니다. 인덱스는항상부모 테이블과같은스키마에서생성됩니다. table 인덱스되는생성테이블의이름 ( 스키마로수식된이름도가능 ) 입니다. 107
108 column 테이블의열이름입니다. expression 테이블에 1 개이상의열을기본으로하는식입니다. 보통, 식은구문에서보여준대로괄호로 묶어야합니다. 그러나식이함수호출형식으로되어있는경우에는괄호를생략할수있습니다. tablespace 인덱스를생성하는테이블스페이스입니다. 지정되지않은경우 default_tablespace 을사용합니다. default_tablespace 가빈문자열이면, 데이터베이스의기본테이블스페이스를사용합니다. 주석 여러열에대한인덱스로지정할수있는필드는 32 개입니다. 예 emp 테이블의 ename 열에 B - tree 인덱스를만듭니다. CREATE INDEX name_idx ON emp (ename); index_tblspc 테이블스페이스내에위와같은인덱스를만듭니다. CREATE INDEX name_idx ON emp (ename) TABLESPACE index_tblspc; 관련항목 ALTER INDEX, DROP INDEX CREATE PACKAGE 이름 CREATE PACKAGE - 새로운패키지사양을정의합니다 개요 CREATE [OR REPLACE] PACKAGE name [AUTHID (DEFINER CURRENT_USER)] 108
109 (IS AS) [declaration] [...] [(PROCEDURE proc_name [(argname [IN IN OUT OUT] argtype [DEFAULT value] [,...])]; FUNCTION func_name [(argname [IN IN OUT OUT] argtype [DEFAULT value] [,...])] RETURN rettype; ) ] [...] END [name] 설명 CREATE PACKAGE 는새로운패키지사양을정의합니다. CREATE OR REPLACE PACKAGE 는새로운패키지사양을만들거나또는기존사양을대체합니다. 스키마이름이포함되어있는경우, 패키지는지정된스키마에서생성됩니다. 스키마이름이없는경우, 패키지는현재스키마에서생성됩니다. CREATE OR REPLACE PACKAGE 를사용하여기존패키지정의를갱신하려는의도가있지않는한, 새로운패키지의이름은동일한스키마의기존패키지의이름과일치하지않아야합니다. 프로시저를생성하는사용자가패키지의소유자입니다. 패키지에대한자세한내용은 6 장을참조하십시오. 매개변수 name 생성하는패키지의이름 ( 스키마로수식된이름도가능 ). DEFINER CURRENT_USER 패키지에서참조하는데이터베이스객체에대한액세스권한을결정하기위해패키지의소유자 권한 (DEFINER) 을사용할지, 패키지의프로그램을실행하여현재사용자의권한 (CURRENT_USER) 을사용것인가를결정합니다. 또한, DEFINER 는자격이되지않는데이터베이스 109
110 객체를참조하는패키지소유자의검색경로를사용합니다. 한편 CURRENT_USER 에서는 패키지의프로그램을실행하여현재사용자의검색경로를사용합니다. DEFINER 가기본입니다. declaration public 변수, 형, 커서, REF CURSOR 선언입니다. proc_name public 프로시저의이름입니다. argname 인수의이름입니다. IN IN OUT OUT 인수모드입니다. argtype 프로그램의인수데이터형입니다. DEFAULT value 입력인수에대한기본값입니다. func_name public 함수의이름입니다. rettype 반환값의데이터형입니다. 예 empinfo 패키지사양은다음의 3 개의 public 요소가포함되어있습니다. public 변수, public 프로시저, public 함수입니다. 이예제에있는패키지의본문은 CREATE PACKAGE BODY 명령을 참조하십시오. CREATE OR REPLACE PACKAGE empinfo 110
111 IS emp_name VARCHAR2 (10); PROCEDURE get_name ( p_empno NUMBER ); FUNCTION display_counter RETURN INTEGER; END; 관련항목 CREATE PACKAGE BODY, DROP PACKAGE CREATE PACKAGE BODY 이름 CREATE PACKAGE BODY - 새로운패키지본문을정의합니다. 개요 CREATE [OR REPLACE] PACKAGE BODY name (IS AS) [declaration] [...] [(PROCEDURE pro c_name [(argname [IN IN OUT OUT] argtype [DEFAULT value] [,...])] (IS AS) program_body END [proc_name]; FUNCTION func_name [(argname [IN IN OUT OUT] argtype [DEFAULT value] [,...])] RETURN rettype (IS AS) program_body END [func_name]; ) ] [...] 111
112 [BEGIN END [name] statement; [...] 설명 CREATE PACKAGE BODY 은새로운패키지본문을정의합니다. CREATE OR REPLACE PACKAGE BODY 는새로운패키지본문을만들거나기존패키지의본문대체중하나를 수행합니다. 스키마이름이포함되어있는경우, 패키지본문은지정된스키마에서생성됩니다. 스키마이름이없는경우, 현재의스키마에서생성됩니다. 새로운패키지본문의이름은동일한스키마의기존패키지사양과일치해야합니다. 그러나 CREATE OR REPLACE PACKAGE BODY 을사용하여기존패키지본문의정의를변경하려는의도가있지않는한, 새패키지본문의이름은동일한스키마의기존패키지본문의이름과일치하지않아야합니다. 패키지본문에대한자세한내용은제 장과제 장을참조하십시오. 매개변수 name 생성하는패키지본문의이름 ( 스키마로수식된이름도가능 ). declaration 전용변수, 형, 커서, REF CURSOR 선언입니다. proc_name public 프로시저또는 private 프로시저의이름입니다. proc_name 가동일한이름의패키지 사양에정의되어있는경우 public 프로시저입니다. 정의되지않은경우, private 프로시저입니다. argname 인수의이름입니다. IN IN OUT OUT 인수모드입니다. argtype 112
113 프로그램의인수데이터형입니다. DEFAULT value 입력인수에대한기본값입니다. program_body 함수또는프로시저의본문을구성하는선언및 SPL 문장입니다. func_name public 함수혹은 private 함수의이름입니다. func_name 이동일한이름의패키지사양에 정의되어있는경우 public 함수입니다. 정의되지않은경우, private 함수입니다. rettype 반환값의데이터형입니다. statement SPL 프로그램문장입니다. 패키지초기화부분의문장은처음한번만실행됩니다. 예 다음은 empinfo 패키지의본문입니다. CREATE OR REPLACE PACKAGE BODY empinfo IS v_counter INTEGER; PROCEDURE get_name ( p_empno NUMBER ) IS BEGIN SELECT ename INTO emp_name FROM emp WHERE empno = p_empno; v_counter : = v_counter + 1; END; FUNCTION display_counter RETURN INTEGER IS 113
114 BEGIN RETURN v_counter; END; BEGIN v_counter : = 0; DBMS_OUTPUT.PUT_LINE ( 'Initialized counter'); END; 다음예제는 empinfo 패키지프로시저와함수를실행하여 public 변수를표시합니다. BEGIN empinfo.get_name (7369); DBMS_OUTPUT.PUT_LINE ( 'Employee Name :' empinfo.emp_name); DBMS_OUTPUT.PUT_LINE ( 'Number of queries :' empinfo.display_counter); END; Initialized counter Employee Name : SMITH Number of queries : 1 BEGIN empinfo.get_name (7900); DBMS_OUTPUT.PUT_LINE ( 'Employee Name :' empinfo.emp_name); DBMS_OUTPUT.PUT_LINE ( 'Number of queries :' empinfo.display_counter); END; Employee Name : JAMES Number of queries : 2 관련항목 CREATE PACKAGE, DROP PACKAGE CREATE PROCEDURE 이름 CREATE PROCEDURE - 새로운저장프로시저를정의한다 개요 114
115 CREATE [OR REPLACE] PROCEDURE name [(argname [IN IN OUT OUT] arg type [DEFAULT value] [,...])] [AUTHID (DEFINER CURRENT_USER)] (IS AS) [declaration] [...] BEGIN statement; [...] [EXCEPTION (WHEN exception [OR exception] [...] THEN statement; [...]) [...] ] END [name] 설명 CREATE PROCEDURE 는새로운저장프로시저를정의합니다. CREATE OR REPLACE PROCEDURE 는새로운프로시저를만들거나또는기존프로시저를대체합니다. 스키마이름이포함된경우, 프로시저는지정된스키마에서생성됩니다. 스키마이름이없으면프로시저는현재스키마에서생성됩니다. CREATE OR REPLACE PROCEDURE 를사용하여기존프로시저의정의를변경하려는의도가있지않은한, 새로운프로시저의이름은동일한스키마의기존프로시저의이름과일치하지않아야합니다., 프로시저를만든사용자가프로시저의소유자가됩니다. 프로시저에대한자세한내용은제 장을참조하십시오. 매개변수 name 생성하는프로시저의이름 ( 스키마로수식된이름도가능 ). argname 인수의이름입니다. 인수는프로시저본문에있는이름에서참조됩니다. IN IN OUT OUT 115
116 인수모드입니다. IN 은인수가입력전용의인수임을선언합니다. 이것이기본값입니다. IN OUT 은 인수가값을반환하고, 취득할수있음을허용합니다. OUT 은출력전용의인수임을지정합니다. argtype 프로시저의인수데이터형입니다. 인수데이터형은기본데이터형, 또는기존의컬럼이될수도 있습니다. 모든기본데이터형에길이를지정하지않습니다. 예를들면, VARCHAR2 (10) 이아닌 VARCHAR2 로지정합니다. 컬럼은 tablename. columnname % TYPE 으로참조됩니다. 이것을사용하면테이블정의가변경 되더라도프로시저가영향을받지않도록하는데유용할수있습니다. DEFAULT value 프로시저를호출할때인수가전달되지않으면입력인수로기본값이사용됩니다. 인수의모드가 IN OUT 또는 OUT 의경우 DEFAULT 가지정되지않습니다. DEFINER CURRENT_USER 프로시저에서참조하는데이터베이스객체에대한액세스권한을결정하기위해프로시저소유자의권한 (DEFINER) 를사용하는지, 프로시저를실행하여현재사용자의권한 (CURRENT_USER) 를사용하는지지정합니다. 또한, DEFINER 는자격이되지않는데이터베이스객체를참조하도록프로시저소유자의검색경로를사용합니다. 한편 CURRENT_USER 에서는프로시저를실행하여현재사용자의검색경로를사용합니다. DEFINER 가기본입니다. declaration 변수, 형, REF CURSOR 선언입니다. statement SPL 프로그램문장입니다. DECLARE - BEGIN - END 블록은 SPL 문장으로간주된다는점에 유의하시기바랍니다. 따라서함수본문에중첩된블록이있을수있습니다. exception NO_DATA_FOUND, OTHERS 와같은예외조건명입니다. 예 다음프로시저는 emp 테이블의직원을표시합니다. 116
117 CREATE OR REPLACE PROCEDURE list_emp IS v_empno NUMBER (4); v_ename VARCHAR2 (10); CURSOR emp_cur IS SELECT empno, ename FROM emp ORDER BY empno; BEGIN OPEN emp_cur; DBMS_OUTPUT.PUT_LINE ( 'EMPNO ENAME'); DBMS_OUTPUT.PUT_LINE (' '); LOOP FETCH emp_cur INTO v_empno, v_ename; EXIT WHEN emp_cur % NOTFOUND; DBMS_OUTPUT.PUT_LINE (v_empno '' v_ename); END LOOP; CLOSE emp_cur; END; EXEC list_emp; EMPNO ENAME SMITH 7499 ALLEN 7521 WARD 7566 JONES 7654 MARTIN 7698 BLAKE 7782 CLARK 7788 SCOTT 7839 KING 7844 TURNER 7876 ADAMS 7900 JAMES 7902 FORD 7934 MILLER 117
118 다음프로시저는직원번호, 이름및직업을반환하는인수모드의 IN OUT 과 OUT 을사용합니다. 첫째로지정된직원번호를바탕으로검색합니다. 찾을수없는경우, 지정된 이름을바탕으로다시찾습니다. 익명의블록은프로시저를호출합니다. CREATE OR REPLACE PROCEDURE emp_job ( p_empno IN OUT emp.empno % TYPE, p_ename IN OUT emp.ename % TYPE, p_job OUT emp.job % TYPE ) IS v_empno emp.empno % TYPE; v_ename emp.ename % TYPE; v_job emp.job % TYPE; BEGIN SELECT ename, job INTO v_ename, v_job FROM emp WHERE empno = p_empno; p_ename : = v_ename; p_job : = v_job; DBMS_OUTPUT.PUT_LINE ( 'Found employee #' p_empno); EXCEPTION WHEN NO_DATA_FOUND THEN BEGIN SELECT empno, job INTO v_empno, v_job FROM emp WHERE ename = p_ename; p_empno : = v_empno; p_job : = v_job; DBMS_OUTPUT.PUT_LINE ( 'Found employee' p_ename); EXCEPTION WHEN NO_DATA_FOUND THEN DBMS_OUTPUT.PUT_LINE ( 'Could not find an employee with' 'number' p_empno 'nor name,' p_ename); p_empno : = NULL; p_ename : = NULL; p_job : = NULL; END; END; DECLARE v_empno emp.empno % TYPE; v_ename emp.ename % TYPE; 118
119 v_job emp.job % TYPE; BEGIN v_empno : = 0; v_ename : = 'CLARK'; emp_job (v_empno, v_ename, v_job); DBMS_OUTPUT.PUT_LINE ( 'Employee No :' v_empno); DBMS_OUTPUT.PUT_LINE ( 'Name :' v_ename); DBMS_OUTPUT.PUT_LINE ( 'Job :' v_job); END; Found employee CLARK Employee No : 7782 Name : CLARK Job : MANAGER 관련항목 DROP PROCEDURE CREATE PUBLIC SYNONYM 이름 CREATE PUBLIC SYNONYM - 새로운 public 동의어를정의한다 개요 CREATE [OR REPLACE] PUBLIC SYNONYM name FOR object 설명 CREATE PUBLIC SYNONYM 데이터베이스객체에대한 public 동의어를정의합니다. 동의어는 객체를참조하는데사용할수있는또다른이름입니다. public 동의어는데이터베이스에서널리 사용할수있습니다. 데이터베이스클러스터의모든사용자가참조할수있습니다. CREATE OR REPLACE PUBLIC SYNONYM 도마찬가지입니다. 하지만같은이름의 public 동의어가 있는경우대체됩니다. 119
120 일반적으로데이터베이스객체는 SQL 문장에서적절히참조되도록스키마이름으로완전히 수식되는경우에, 동의어가유용합니다. 객체에정의된동의어는수식되지않은, 하나의이름으로 간편하게참조합니다. public 동의어에대한자세한내용은제 장을참조하십시오. 매개변수 name 생성된 public 동의어의이름입니다. object public 동의어가생성하는데이터베이스객체의이름 ( 스키마로수식한이름가능 ). 데이터베이스 객체는테이블, 뷰, 시퀀스, 다른동의어가될수있습니다. 주석 모든사용자가 public 동의어를만들수있습니다. 특별한권한이필요하지않습니다. public 동의어는모든사용자에의해모든 SQL 문장에서참조될수있습니다. 그러나, 동의어가 참조하는데이터베이스객체에적절한권한이있는사용자의경우에만, SQL 문실행이 성공합니다. public 동의어는스키마의구성원이아니지만, database - wide 이름입니다. public 동의어는존재하지않는객체에대해서도만들수있습니다. public 동의어에서참조하는데이터베이스객체에대한액세스여부는현재사용자의권한으로 결정됩니다. 따라서 public 동의어사용자는참조데이터베이스객체에적절한권한을갖고 있어야합니다. 예 스키마이름 enterprisedb 의 emp 테이블에대한 public 동의어 personnel 을생성합니다. CREATE PUBLIC SYNONYM personnel FOR enterprisedb.emp; 관련항목 DROP PUBLIC SYNONYM 120
121 CREATE ROLE 이름 CREATE ROLE - 새로운데이터베이스역할을정의한다 개요 CREATE ROLE name [IDENTIFIED BY password] 설명 CREATE ROLE 은 Postgres Plus Advanced Server 데이터베이스클러스터에새역할을추가합니다. 역할은자신의데이터베이스객체를소유할수있고데이터베이스권한을가지는엔티티입니다. 역할은용도에따라 " 사용자 ", " 그룹 ", 혹은둘모두생각할수있습니다. 새로정의된역할은 LOGIN 속성이없습니다. 따라서세션을시작하는데사용될수없습니다. LOGIN 권한을부여하려면 ALTER ROLE 명령을사용하십시오. CREATE ROLE 명령을사용하려면 CREATEROLE 권한이있거나해당데이터베이스의슈퍼유저이어야합니다. IDENTIFIED BY 절이지정된경우, CREATE ROLE 커멘드는새로생성되는역할과동일한이름의 스키마를생성합니다. 새로만든역할이스키마의소유자입니다. 역할은데이터베이스클러스터수준에서정의되므로클러스터의모든데이터베이스에서사용되는 것에주의하십시오. 매개변수 name 새역할의이름입니다. IDENTIFIED BY password 역할의패스워드를설정합니다. ( 패스워드는 LOGIN 속성을가진역할에만의미가있지만, 이 특성이없는역할을정의할수있습니다.) 패스워드인증을실시할예정이없는경우, 이옵션을 생략할수있습니다. 주석 121
122 역할의속성을 변경하려면 ALTER ROLE, 역할을삭제하려면 DROP ROLE 을사용하십시오. CREATE ROLE 에지정 된모든속성은나중에 ALTER ROLE 명령으로변경할수있습니다. 그룹으로사용되고있는역할의구성원추가및삭제에대한권장 방법은 GRANT 와 REVOKE 를사용하는것입니다. 역할이름과패스워드는최대 63 자까지입니다. 예 admins 라는패스워드가있는역할 ( 그리고스키마 ) 를생성합니다. CREATE ROLE admins IDENTIFIED BY Rt498zb; 관련항목 ALTER ROLE, DROP ROLE, GRANT, REVOKE, SET ROLE CREATE SCHEMA 이름 CREATE SCHEMA - 새로운스키마를정의한다 개요 CREATE SCHEMA AUTHORIZATION username schema_element [...] 설명 CREATE SCHEMA 는 1 개이상의객체가포함된 username 이소유한새로운스키마를생성합니다. 스키마와객체는 1 개의트랜잭션에서생성되기때문에모든객체가생성되거나, 또는스키마를가진모든객체를만드는데실패하는것입니다. (Oracle 에서새스키마는만들어지지않습니다. username 과스키마는사전에존재해야합니다.) 스키마는기본적으로네임스페이스입니다. 스키마는명명된객체 ( 테이블, 뷰등 ) 가포함됩니다. 이러한객체의이름은다른스키마에존재하는다른객체의이름과중복해도상관없습니다. 명명된객체는스키마이름을접두어로이름을 " 한정 " 하거나필요한스키마를포함하는검색경로를설정하여사용할수있습니다. 한정되지않은객체는현재의스키마 (CURRENT_SCHEMA 122
123 함수가결정되는검색경로의시작부분 ) 에서생성됩니다.)( 검색경로의개념과 CURRENT_SCHEMA 함수는 Oracle 과호환하지않습니다.) CREATE SCHEMA 은스키마에서객체를생성하려면하위명령을추가할수있습니다. 하위 명령은기본적으로스키마를만든후발행되는다른명령과동일하게취급됩니다. 그러나생성된 모든객체는지정한사용자가소유한다는점에서다릅니다. 매개변수 username 새로운스키마를소유한사용자의이름입니다. 스키마이름도 username 과같습니다. 슈퍼유저만이자신이외의사용자가소유하는스키마를생성할수있습니다. ( 오라클호환성주석 : Postgres Plus Advanced Server 에서역할, username 은존재해야합니다. 그러나스키마는존재하지않습니다. Oracle 에서는모두존재해야합니다.) schema_element 스키마에서생성된객체를정의하는 SQL 구문입니다. CREATE SCHEMA 내에서는 CREATE TABLE, CREATE VIEW, GRANT 를어구로사용할수있습니다. 다른종류의객체는스키마를생성한후 별도의명령을사용하면만들수있습니다. 주석 스키마를만들려면, 실행하는사용자가현재데이터베이스에서 CREATE 권한을가져야합니다. ( 물론, 슈퍼에게는이러한제약이없습니다.) Postgres Plus Advanced Server 는여기에나열된형식이외에도 CREATE SCHEMA 명령이형식이 있습니다. 그러나, 그들은 Oracle 과호환되지않습니다. 예 CREATE SCHEMA AUTHORIZATION enterprisedb CREATE TABLE empjobs (ename VARCHAR2 (10), job VARCHAR2 (9)) CREATE VIEW managers AS SELECT ename FROM empjobs WHERE job = 'MANAGER' GRANT SELECT ON managers TO PUBLIC; CREATE SEQUENCE 이름 123
124 CREATE SEQUENCE - 새로운시퀀스생성기를정의합니다 개요 CREATE SEQUENCE name [INCREMENT BY increment] [(NOMINVALUE MINVALUE minvalue)] [(NOMAXVALUE MAXVALUE maxvalue)] [START WITH start] [CACHE cache NOCACHE] [CYCLE] 설명 CREATE SEQUENCE 는새로운시퀀스번호생성기를만듭니다. 특히, 새로운 name 이라는이름을 가진 1 개의행을지닌특수한테이블을만들고초기화합니다. 생성기는이명령을실행하는 사용자가소유합니다. 스키마이름이부여된경우, 시퀀스는지정된스키마에서생성됩니다. 스키마이름이없으면 시퀀스는현재스키마에서생성됩니다. 시퀀스이름은동일한스키마의다른시퀀스, 테이블, 인덱스, 뷰의이름과달라야합니다. 시퀀스를만든후, NEXTVAL, CURRVAL 함수를사용하여시퀀스를조작합니다. 이함수는단원 에기재되어있습니다. 매개변수 name 생성하는시퀀스의이름 ( 스키마로수식된이름도가능 ). increment INCREMENT BY increment 어구는현재시퀀스값에서새로운시퀀스값을만들때값의 증가량을설정합니다. 이어구는선택사항입니다. 양수가지정되면오름차순시퀀스, 음수가 지정되면내림차순시퀀스를만듭니다. 지정하지않은경우기본값은 1 입니다. NOMINVALUE MINVALUE minvalue MINVALUE minvalue 절은시퀀스가생성하는최소값을지정합니다. 이어구는선택사항입니다. 이어구가지정되지않은경우, 혹은키워드인 NOMINVALUE 가지정되면기본값이사용됩니다. 시퀀스의기본최소값은오름차순때는 1 내림차순때는 입니다. NOMAXVALUE MAXVALUE maxvalue 124
125 MAXVALUE maxvalue 절은시퀀스의최대값을결정합니다. 이어구는선택사항입니다. 이 어구가지정되지않은경우, 혹은키워드인 NOMAXVALUE 가지정되면기본값이사용됩니다. 시퀀스의기본최소값은오름차순때는 내림차순때는 -1 입니다. start START WITH start 어구를사용하면임의의숫자에서시퀀스번호를시작할수있습니다. 이 어구는선택사항입니다. 기본적으로, 시퀀스의시작값은오름차순경우 minvalue, 내림차순의 경우 maxvalue 입니다. cache CACHE cache 옵션은미리할당하고메모리에저장할시퀀스번호를지정합니다. 이에따라 액세스를빠르게할수있습니다. 최소값은 1 입니다 ( 한번에 1 개의값만이생성됩니다. 즉, NOCACHE) 이것이기본입니다. CYCLE CYCLE 옵션을사용하면시퀀스가한계 ( 오름차순의경우 maxvalue, 내림차순의경우 minvalue) 에 이르렀을때그시퀀스를회전시킬수있습니다. 한계에도달했을때다음생성되는번호는 오름차순의경우 minvalue, 내림차순의경우 maxvalue 입니다. CYCLE 이생략되면 ( 디폴트 ), 시퀀스가한계에도달한후에 NEXTVAL 를호출하면에러가 발생합니다. NO CYCLE 키워드는기본설정을검색하는데사용됩니다. 다만, 이옵션은 Oracle 과 호환되지않습니다. 주석 시퀀스는 big integer 연산을기반으로합니다. 따라서 8 바이트정수범위 ( 과 사이 ) 를초과하는것은불가능합니다. 비교적오래된플랫폼은 8 바이트정수를지원하는컴파일러가없을수도있습니다. 이경우시퀀스는보통 INTEGER 연산을사용합니다. ( 이경우에, 범위는, 에서 ). cache 를 1 보다큰값으로설정하고시퀀스객체를여러세션에서동시에사용하면의외의결과를가져올가능성이있습니다. 각세션은시퀀스객체에엑세스하는동안에연속시퀀스값을할당하고캐시합니다. 그리고캐시하는숫자에따라시퀀스객체의마지막값을증가시킵니다. 이경우, 해당세션내에서 NEXTVAL 의다음 cache -1 사용은시퀀스객체의변경없이미리할당한시퀀스값을반환합니다. 세션에할당되어사용되지않은시퀀스번호는세션이끝날때삭제되기때문에결과적으로시퀀스에 " 구멍 " 이생깁니다. 125
126 더욱이, 여러세션에서별도의시퀀스값이할당되는것이보장되지만, 모든세션이고려될때, 시퀀스범위외의값이생성될수있습니다. 예를들면, cache 가 10 인경우를생각해볼수있습니다. 세션 A 는 1 에서 10 까지를확보해 NEXTVAL = 1 을반환합니다. 세션 B 에서는세션 A 가 NEXTVAL = 2 를생성하기전에 11 에서 20 을확보하고, NEXTVAL = 11 을반환합니다. 따라서 cache 를 1 로설정하면 NEXTVAL 값이순서대로생성되는것에문제가없지만, cache 를 1 보다큰값으로설정하면, NEXTVAL 값이모두다르게되고, 순서대로생성할수없습니다. 또한 last value 는 NEXTVAL 의반환여부에관계없이어느세션을통해서나확보되는마지막값입니다. 예 101 으로시작되는 serial 이라는오름차순시퀀스를만듭니다. CREATE SEQUENCE serial START WITH 101; 이시퀀스에서다음번호를선택합니다. SELECT serial.nextval FROM DUAL; nextval (1 row) NOCACHE 옵션과함께 supplier_seq 라는시퀀스를만듭니다. CREATE SEQUENCE supplier_seq MINVALUE 1 START WITH 1 INCREMENT BY 1 NOCACHE; 이시퀀스에서다음번호를선택합니다. SELECT supplier_seq.nextval FROM DUAL; nextval (1 row) 126
127 관련항목 ALTER SEQUENCE, DROP SEQUENCE CREATE TABLE 이름 CREATE TABLE - 새로운테이블을정의한다 개요 CREATE [GLOBAL TEMPORARY] TABLE table_name ( (column_name data_type [DEFAULT default_expr] [column_constraint [...]] table_constraint) [...] ) [ON COMMIT (PRESERVE ROWS DELETE ROWS)] [TABLESPACE tablespace] column_constraint 이있는구문입니다. [CONSTRAINT constraint_name] (NOT NULL NULL UNIQUE [USING INDEX TABLESPACE tablespace] PRIMARY KEY [USING INDEX TABLESPACE tablespace] CHECK (expression) REFERENCES reftable [(refcolumn) [ON DELETE act ion]) [DEFERRABLE NOT DEFERRABLE] [INITIALLY DEFERRED INITIALLY IMMEDIATE] 그리고 table_constraint 구문입니다. [CONSTRAINT constraint_name] (UNIQUE (column_name [...]) [USING INDEX TABLESPACE tablespace] PRIMARY KEY (column_name [...]) [USING INDEX TABLESPACE tablespace] CHECK (expression) 127
128 FOREIGN KEY (column_name [...]) REFERENCES reftable [(refcolumn [...])] [ON DELETE action]) [DEFERRABLE NOT DEFERRABLE] [INITIALLY DEFERRED INITIALLY IMMEDIATE] 설명 CREATE TABLE 은현재데이터베이스에빈테이블을만듭니다. 이테이블은이명령을실행한 사용자가소유합니다. 스키마이름이주어진경우 ( 예 : CREATE TABLE myschema. mytable...), 테이블은지정된스키마에서생성됩니다. 스키마이름이없으면테이블은현재스키마에서생성됩니다. 또한특별한스키마에존재하는임시테이블을만들때스키마이름이주어지지않을수있습니다. 테이블이름은같은스키마의다른테이블, 시퀀스, 인덱스, 뷰의이름과달라야합니다. 또한 CREATE TABLE 은테이블의 1 행에상응하는복합데이터형을자동적으로 생성합니다. 따라서테이블은같은스키마의기존데이터형과같은이름을가질수없습니다. 테이블은 1600 개이상의열을가질수없습니다. ( 실제로는튜플길이제약때문에보유할수 있는열수는더적습니다.) 제약어구는제약 ( 또는테스트 ) 을지정합니다. 삽입, 갱신작업을충족시키기위한새로운행또는 갱신된행의제약을지정합니다. 제약어구는선택사항입니다. 제약은테이블에서각종유효값 집합을정의할때유용한 SQL 객체입니다. 제약의정의는테이블제약및열제약이라는 2 가지종류가있습니다. 열제약은열정의의일부로정의됩니다. 테이블제약정의는특정열과연관되어있지않고여러열을포함할수있습니다. 또한모든열제약은테이블제약으로작성할수있습니다. 열제약은 1 개의열에만영향을주는제약때문에, 간편한작성법에불과합니다. 매개변수 GLOBAL TEMPORARY 이매개변수를지정하면테이블은임시테이블로생성됩니다. 임시테이블은세션이끝난시점에또는현재트랜잭션의끝 ( 아래의 ON COMMIT 참조 ) 에자동으로삭제됩니다. 임시테이블이있으면이름이같은기존의영구테이블은스키마로수식된이름으로참조되지않는한, 현재세션에서는비가시화됩니다. 또한임시테이블은현재세션밖에서비가시화됩니다. ( 이임시 128
129 테이블의정보는 Oracle 과호환되지않습니다.) 임시테이블에서생성되는인덱스도모두 자동으로일시적인것입니다. table_name 생성하는테이블의이름 ( 스키마로수식된이름도가능 ). column_name 새테이블에서만들어진열의이름입니다. data_type 열데이터형입니다. 여기에는배열지정자를포함할수있습니다. Postgres Plus Advanced Server 에서지원하는데이터형정보에대한자세한내용은제 3.2 장을참조하십시오. DEFAULT default_expr DEFAULT 어구내에열정의를지정하면해당열에기본데이터값이할당됩니다. 값은변수가 없는식입니다. ( 서브쿼리및현재테이블의다른열에대한교차참조는허용되지 않습니다 ). 기본식의데이터형은열의데이터형과일치해야합니다. 기본식은모든삽입작업에서해당열에값을지정하지않은경우에사용됩니다. 열에기본값이 없으면기본값은 null 입니다. CONSTRAINT constraint_name 선택적열제약조건, 테이블제약조건의이름입니다. 지정되지않는경우시스템이이름을 생성합니다. NOT NULL 해당열이 null 값을갖지않도록지정합니다. NULL 해당열이 null 값을가질수를있도록지정합니다. 이것이기본값입니다. 이어구는비표준 SQL 데이터베이스와의호환성을위해서만제공됩니다. 새로운 애플리케이션에서이것을사용하는것은권장하지않습니다. 129
130 UNIQUE - 열제약 UNIQUE (column_name [...]) - 테이블제약 UNIQUE 제약조건은테이블의 1 개이상의열또는그룹이고유한값만갖도록 지정합니다. 고유테이블제약동작은고유성열제약과같지만보다여러부분에걸쳐기능을 가지고있습니다. 고유제약조건에서, null 값은동일한것으로간주되지않습니다.. 각각의고유한테이블제약은테이블의다른고유제약조건이나주키제약조건에의해명명된 열집합은서로다른이름을지닌열의집합을지정해야합니다 ( 같은이름을지정하면, 같은 제약이 2 회열거됩니다 ). PRIMARY KEY - 열제약 PRIMARY KEY (column_name [...]) - 테이블제약 주키제약조건은테이블의 1 열또는 1 이상의열이고유한값 ( 중복되지않은값 ), 비 null 값만갖도록지정합니다. 기술적으로, PRIMARY KEY 는단순한 UNIQUE 와 NOT NULL 조합입니다. 그러나주키는다른테이블이고유한행식별자로서인식하기때문에, 열집합을주키로지정하는것은스키마설계에관한메타데이터또한제공하는것을의미합니다. 열제약또는테이블제약에관계없이 1 개의테이블에사용할수있는주키는 1 개뿐입니다. 주키제약은동일한테이블에정의된모든고유제약으로, 지정된열집합과는다른이름으로 열집합을지정해야합니다. CHECK (expression) CHECK 절은삽입및갱신작업을위한새로운행또는변경하는행위를충족시키는 Boolean 형의결과를반환하는식입니다. 표현식이 true 또는 unknown 이면성공입니다. 행삽입, 갱신작업의결과, 식이 false 가될경우, 에러예외가생성되고, 삽입및갱신이데이터베이스를변경하지않습니다. 열제약으로지정된 check 제약은해당열의값만참조할수있어야합니다. 한편테이블제약에서나오는식은여러열을참조할수수도있습니다. 현재, CHECK 식은서브쿼리와현재행의열이외의값을포함할수없습니다. REFERENCES reftable [(refcolumn)] [ON DELETE action] - 열제약 FOREIGN KEY (column [...]) REFERENCES reftable [(refcolumn [...])] [ON DELETE actio n] - 테이블제약 130
131 이어구는외래키제약조건을지정합니다. 외래키제약조건은새테이블에서 1 개또는 1 개이상의열집합이참조된테이블의행의열값과일치하는값이있어야함을요구합니다. refcolumn 가생략되는경우, reftable 의주키를사용합니다. 참조된열은참조된테이블에서고유제약이나주키제약을가진열이어야합니다. 또한, 참조된열데이터가변경된경우에는이테이블의열데이터에문제가발생합니다. ON DELETE 절은참조된테이블의행이삭제되면, 실행할동작을지정합니다. 제약이지연될지라도 참조동작은지연될수없습니다. 각어구에대해다음작업을지정할수있습니다. CASCADE 삭제된행을참조하고있는부분은모두삭제합니다. 또한참조하는열의값을참조되는열의 새로운값으로갱신합니다. SET NULL 참조하는열을 null 로설정합니다. 참조된열이자주변경되는경우, 외래키열을인덱스에추가하고, 외래키열과관련된참조 동작을보다효율적으로실행할수있도록하는것이좋습니다. DEFERRABLE NOT DEFERRABLE 제약조건을지연시킬수있는지여부를제어합니다. 지연할수없는제약은각명령후즉시검사됩니다. 지연가능한제약검사는 ( SET CONSTRAINTS 명령을사용하여 ) 트랜잭션이끝날때까지지연시킬수있습니다. NOT DEFERRABLE 이기본입니다. 현재, 외래키제약만이이어구를허용합니다. 다른제약은지연시킬수없습니다. INITIALLY IMMEDIATE INITIALLY DEFERRED 제약이지연되는경우, 이어구는제약검사의기본시간을지정합니다. 제약이 INITIALLY IMMEDIATE 의경우, 각문장을실행한후에검사합니다. 이것이기본입니다. 제약이 INITIALLY DEFERRED 인경우, 트랜잭션이끝날때만검사됩니다. 제약검사시간은 SET CONSTRAINTS 명령을사용하여변경할수있습니다. ON COMMIT ON COMMIT 을사용하여트랜잭션블록의종료시점에서임시테이블의동작을제어할수 있습니다. 다음 2 가지옵션이있습니다. 131
132 PRESERVE ROWS 트랜잭션의종료시점에서특별한동작이실행되지않습니다. 이것이기본 동작입니다. ( 이것은 Oracle 과호환되지않습니다. Oracle 의기본동작은 DELETE ROWS 입니다.) DELETE ROWS 임시테이블의모든행은각트랜잭션블록의끝에서삭제됩니다. 기본적으로커밋때마다 자동으로 TRUNCATE 가실행됩니다. TABLESPACE tablespace tablespace 는새테이블이만들어지는테이블스페이스의이름입니다. 지정되지않은경우, default_tablespace 를사용합니다. default_tablespace 가공문자열이면, 데이터베이스의기본 테이블스페이스를사용합니다. USING INDEX TABLESPACE tablespace 이어구를사용하면, UNIQUE 또는 PRIMARY KEY 제약과관련된인덱스를만들테이블스페이스를선택할수있습니다. 지정되지않은경우, default_tablespace 를사용합니다. default_tablespace 이공문자열인경우, 데이터베이스의기본테이블스페이스를사용합니다. 주석 Postgres Plus Advanced Server 는자동으로각고유제약과주키제약에대한인덱스를만들고 그고유성을보장합니다. 따라서주키열에명시적인인덱스를생성할필요가없습니다 ( 자세한 내용은 CREATE INDEX 를참조하십시오 ). 예 dept 테이블과 emp 테이블을만듭니다. CREATE TABLE dept ( deptno NUMBER (2) NOT NULL CONSTRAINT dept_pk PRIMARY KEY, dname VARCHAR2 (14), loc VARCHAR2 (13) ); CREATE TABLE emp ( empno NUMBER (4) NOT NULL CONSTRAINT emp_pk PRIMARY KEY, ename VARCHAR2 (10), 132
133 job VARCHAR2 (9) mgr NUMBER (4), hiredate DATE, sal NUMBER (7,2), comm NUMBER (7,2), deptno NUMBER (2) CONSTRAINT emp_ref_dept_fk REFERENCES dept (deptno) ); dept 테이블에고유테이블제약을정의합니다. 고유테이블제약은테이블의 1 개또는 복수열을정의할수있습니다. CREATE TABLE dept ( deptno NUMBER (2) NOT NULL CONSTRAINT dept_pk PRIMARY KEY, dname VARCHAR2 (14) CONSTRAINT dept_dname_uq UNIQUE, loc VARCHAR2 (13) ); 검사열제약조건을정의합니다. CREATE TABLE emp ( empno NUMBER (4) NOT NULL CONSTRAINT emp_pk PRIMARY KEY, ename VARCHAR2 (10), job VARCHAR2 (9) mgr NUMBER (4), hiredate DATE, sal NUMBER (7,2) CONSTRAINT emp_sal_ck CHECK (sal> 0) comm NUMBER (7,2), deptno NUMBER (2) CONSTRAINT emp_ref_dept_fk REFERENCES dept (deptno) ); 검사테이블제약조건을정의합니다. CREATE TABLE emp ( empno NUMBER (4) NOT NULL CONSTRAINT emp_pk PRIMARY KEY, ename VARCHAR2 (10), job VARCHAR2 (9) mgr NUMBER (4), hiredate DATE, 133
134 sal NUMBER (7,2), comm NUMBER (7,2), deptno NUMBER (2) CONSTRAINT emp_ref_dept_fk REFERENCES dept (deptno), CONSTRAINT new_emp_ck CHECK (ename IS NOT NULL AND empno> 7000) ); jobhist 테이블에주키테이블제약을정의합니다. 주키테이블제약은테이블의 1 개또는 복수열을정의할수있습니다. CREATE TABLE jobhist ( empno NUMBER (4) NOT NULL, startdate DATE NOT NULL, enddate DATE, job VARCHAR2 (9) sal NUMBER (7,2), comm NUMBER (7,2), deptno NUMBER (2), chgdesc VARCHAR2 (80), CONSTRAINT jobhist_pk PRIMARY KEY (empno, startdate) ); 다음은 job 열의기본값으로리터럴상수를지정합니다. 또 hiredate 열의기본값은행이 삽입된날짜입니다. CREATE TABLE emp ( empno NUMBER (4) NOT NULL CONSTRAINT emp_pk PRIMARY KEY, ename VARCHAR2 (10), job VARCHAR2 (9) DEFAULT 'SALESMAN', mgr NUMBER (4), hiredate DATE DEFAULT SYSDATE, sal NUMBER (7,2), comm NUMBER (7,2), deptno NUMBER (2) CONSTRAINT emp_ref_dept_fk REFERENCES dept (deptno) ); diskvol1 테이블스페이스에 dept 테이블을만듭니다. CREATE TABLE dept ( 134
135 deptno NUMBER (2) NOT NULL CONSTRAINT dept_pk PRIMARY KEY, dname VARCHAR2 (14), loc VARCHAR2 (13) ) TABLESPACE diskvol1; 관련항목 ALTER TABLE, DROP TABLE CREATE TABLE AS 이름 CREATE TABLE AS - 쿼리결과에따라새로운테이블을정의합니다 개요 CREATE [GLOBAL TEMPORARY] TABLE table_name [(column_name [...])] [ON COMMIT (PRESERVE ROWS DELETE ROWS)] [TABLESPACE tablespace] AS query 설명 CREATE TABLE AS 는테이블을만들고 SELECT 명령에의해산출된데이터를테이블에 저장합니다. 테이블의열은 SELECT 출력열과연관된이름과데이터형을가지고있습니다. ( 단, 새로운열이름을명시한목록을전달하면열이름을오버라이드할수있습니다.) CREATE TABLE AS 는뷰를생성하는것과비슷하지만실제로는전혀다릅니다. CREATE TABLE AS 는새로운테이블을만들고새로운테이블의내용을초기화하기위해한번만쿼리를평가합니다. 그이후쿼리의원본테이블에대한변경사항은새테이블에반영되지않습니다. 반대로, 뷰는쿼리가실행될때마다, 정의된 SELECT 문을다시평가합니다. 매개변수 GLOBAL TEMPORARY 135
136 이것이지정되면, 테이블은임시테이블로생성됩니다. 자세한 내용은 CREATE TABLE 을참조하십시오. table_name 생성할테이블의이름 ( 스키마로수식된이름도가능 ). column_name 새테이블의열이름입니다. 열이름을지정하지않으면, 쿼리의출력열이름을사용합니다. query 쿼리문입니다. ( 즉, SELECT 명령입니다.) 사용가능한구문정보는 SELECT 를참조하십시오. 관련항목 CREATE TABLE, SELECT CREATE TRIGGER 이름 CREATE TRIGGER - 새로운트리거를정의합니다 개요 CREATE [OR REPLACE] TRIGGER name (BEFORE AFTER) (INSERT UPDATE DELETE) [OR (INSERT UPDATE DELETE)] [...] ON table [FOR EACH ROW] [DECLARE declaration; [...] BEGIN statement; [...] [EXCEPTION (WHEN exception [OR exception] [...] THEN 136
137 ] END statement; [...]) [...] 설명 CREATE TRIGGER 는새로운트리거를정의합니다. CREATE OR REPLACE TRIGGER 은새로운 트리거를만들거나기존의트리거를대체합니다. CREATE OR REPLACE TRIGGER 를사용하여기존의트리거의정의를변경하려는목적이없는한, 새로운트리거이름은동일한테이블에정의된기존트리거의이름과일치하지않아야합니다. 트리거는트리거링이벤트가정의된테이블과같은스키마에서생성됩니다. 트리거에대한자세한정보는 5 장을참조하십시오. 매개변수 name 생성하는트리거의이름입니다. BEFORE AFTER 트리거를트리거링이벤트실행전에또는후에발행할것인지결정합니다. INSERT UPDATE DELETE 트리거링이벤트를정의합니다. table 트리거링이벤트가발생하는테이블의이름입니다. FOR EACH ROW 이매개변수는트리거프로시저를트리거링이벤트에의해영향을받는각행에대해 1 회발행하거나또는 SQL 문장마다 1 회발행할지여부를지정합니다. 지정된경우, 트리거는영향을받는각행에대해 1 회발생합니다. ( 낮은레벨의트리거 ) 지정하지않는경우, 트리거는 SQL 문장마다 1 회발행합니다. 137
138 declaration 변수, 형, R EF CURSOR 선언입니다. statement SPL 프로그램문장입니다. DECLARE - BEGIN - END 블록은 SPL 문장으로간주된다는점에 유의하시기바랍니다. 따라서트리거내부에중첩된블록이있을수있습니다. exception NO_DATA_FOUND, OTHERS 등예외상황의이름입니다. 예 다음은 SQL 문장단위로실행하는트리거입니다. 트리거링문장이실행된후에트리거가 발행됩니다. (emp 테이블에 INSERT, UPDATE, DELETE 가실행될때마다발행합니다.) CREATE OR REPLACE TRIGGER user_audit_trig AFTER INSERT OR UPDATE OR DELETE ON emp DECLARE v_action VARCHAR2 (24); BEGIN IF INSERTING THEN v_action : = 'added employee (s) on'; ELSIF UPDATING THEN v_action : = 'updated employee (s) on'; ELSIF DELETING THEN v_action : = 'deleted employee (s) on'; END IF; DBMS_OUTPUT.PUT_LINE ( 'User' USER v_action TO_CHAR (SYSDATE, 'YYYY - MM - DD')); END; 다음은낮은레벨의트리거입니다. emp 테이블의각행에 INSERT, UPDATE, DELETE 를실행하기 전에트리거가발행됩니다. CREATE OR REPLACE TRIGGER emp_sal_trig BEFORE DELETE OR INSERT OR UPDATE ON emp FOR EACH ROW 138
139 DECLARE sal_diff NUMBER; BEGIN IF INSERTING THEN DBMS_OUTPUT.PUT_LINE ( 'Inserting employee' : NEW.empno); DBMS_OUTPUT.PUT_LINE ( '.. New salary :' : NEW.sal); END IF; IF UPDATING THEN sal_diff : = : NEW.sal - : OLD.sal; DBMS_OUTPUT.PUT_LINE ( 'Updating employee' : OLD.empno); DBMS_OUTPUT.PUT_LINE ( '.. Old salary :' : OLD.sal); DBMS_OUTPUT.PUT_LINE ( '.. New salary :' : NEW.sal); DBMS_OUTPUT.PUT_LINE ( '.. Raise :' sal_diff); END IF; IF DELETING THEN DBMS_OUTPUT.PUT_LINE ( 'Deleting employee' : OLD.empno); DBMS_OUTPUT.PUT_LINE ( '.. Old salary :' : OLD.sal); END IF; END; 관련항목 DROP TRIGGER CREATE USER 이름 CREATE USER - 새로운데이터베이스사용자계정을정의합니다 개요 CREATE USER name IDENTIFIED BY password 설명 CREATE USER 는 Postgres Plus Advanced Server 데이터베이스클러스터에새로운사용자를 추가합니다. CREATE USER 명령을사용하려면데이터베이스의슈퍼유저여야합니다. 139
140 CREATE USER 를사용하면새사용자와동일한이름의스키마를만듭니다. 새로만든사용자가 스키마의소유자입니다. 사용자가자격이되지않는이름을가진객체를만들때, 객체가이 스키마에서생성됩니다. 매개변수 name 사용자의이름입니다. password 사용자의패스워드를설정합니다. 패스워드는 ALTER USER 를사용하여나중에변경할수 있습니다. 주석 사용자이름과패스워드는최대 63 자까지입니다. 예 john 이라는사용자를만듭니다. CREATE USER john IDENTIFIED BY abc; 관련항목 ALTER USER, DROP USER CREATE VIEW 이름 CREATE VIEW - 새로운뷰를정의합니다 개요 CREATE [OR REPLACE] VIEW name [(column_name [...])] AS query 140
141 설명 CREATE VIEW 는쿼리에따른뷰를정의합니다. 뷰는실체로존재하는것은아닙니다. 대신, 쿼리에서뷰를참조때마다지정된쿼리가실행됩니다. CREATE OR RE PLACE VIEW 도비슷하지만, 같은이름을가진뷰가이미존재하는경우, 해당 뷰를대체합니다. 스키마이름이주어진경우 ( 예 : CREATE VIEW myschema.myview...), 뷰는지정된스키마에서 생성됩니다. 스키마이름이주어지지않은경우, 뷰는현재스키마에서생성됩니다. 뷰이름은 동일한스키마의다른뷰, 테이블, 시퀀스, 인덱스와다른이름이어야합니다. 매개변수 name 생성하는뷰의이름 ( 스키마로수식된이름도가능 ). column_name 뷰의열이름으로사용하는이름의목록입니다. 이매개변수는선택사항입니다. 생략되는경우, 쿼리에서유래한이름이사용됩니다. query 뷰의열과행을제공하는 SELECT 문장입니다. 유효한쿼리구문에대한자세한정보는 SELECT 를참조하십시오. 주석 현재, 뷰는읽기전용입니다. 시스템은뷰에삽입, 갱신, 삭제를허용하지않습니다. 그러나뷰에삽입등의다른테이블을처리하는데갱신룰을만드는것으로, 갱신할수있는뷰와같은효과를얻을수있습니다. 자세한내용은 Postgres Plus documentation set 의 CREATE RULE 명령을참조하십시오. 뷰가참조하는테이블에액세스할수있는지여부는뷰소유자의권한으로결정됩니다. 그러나 뷰에서호출되는함수는뷰를사용하여쿼리에서직접호출되는경우와마찬가지로 취급됩니다. 따라서뷰사용자는뷰에서사용되는모든함수를호출할권한이있어야합니다. 141
142 예 deptno 30 의모든직원으로구성된뷰를만듭니다. CREATE VIEW dept_30 AS SELECT * FROM emp WHERE deptno = 30; 관련항목 DROP VIEW DELETE 이름 DELETE - 테이블에서행을삭제합니다 개요 DELETE [optimizer_hint] FROM tabl e [@ dblink] [WHERE condition] [RETURNING return_expression [...] (INTO (record variable [...]) BULK COLLECT INTO collection [...])] 설명 DELETE 는지정된테이블에서 WHERE 절을충족시키는행을제거합니다. WHERE 이없으면, 지정한테이블의모든행을삭제할수있습니다. 따라서결과는유효하지만, 내용이없는빈 테이블이남게됩니다. 주석 : TRUNCATE 명령은테이블에서모든행을제거하는보다빠른매커니즘을제공합니다. DELETE 명령이 SPL 프로그램에서사용되는경우에만 RETURNING INTO (record variable [...]) 어구를지정할수있습니다. 또한 DELETE 명령의결과는 1 행이상을포함해서는안됩니다. 결과가 2 줄이상의경우는예외가발생합니다. 결과가비어있으면, 대상레코드혹은변수는 null 이할당됩니다. DELETE 명령이 SPL 프로그램에서사용되는경우에만 RETURNING BULK COLLECT INTO collection [...] 어구를지정할수있습니다. BULK COLLECT INTO 어구를대상으로여러 collection 이지정된 142
143 경우, 각 collection 은단일의스칼라필드로구성되어야합니다. 즉, collection 가레코드이여서는안됩니다. DELETE 명령의결과행이완전히제거되지않거나여러행을삭제됩니다. 결과의각행에대해평가되는 return_expression 는첫번째요소로시작하는 collection 의요소입니다. collection 에있는기존행은삭제됩니다. 결과가비어있으면, collection 은비어있습니다. 삭제를수행하려면해당테이블에대한 DELETE 권한이있어야합니다. 또한, condition 에대한 값을읽기위해해당값이들어있는모든테이블에대한 SELECT 권한이있어야합니다. 매개변수 optimizer_hint 최적화프로그램의실행계획을선택할때사용하는주석에있는힌트입니다. 최적화힌트에 대한자세한내용은 3.4 장을참조하십시오. table 기존테이블이름 ( 스키마로수식된이름도가능 ). dblink 원격데이터베이스를식별하는데이터베이스링크의이름입니다. 데이터베이스링크에대한 자세한내용은 CREATE DATABASE LINK 명령을참조하십시오. conditi on 삭제여부를결정하는 BOOLEAN 값을반환하는식입니다. return_expression table 1 개이상의열이포함된식입니다. return_expression 에서 table 의열이름이지정된 경우, return_expression 평가후열에할당되는값은삭제된행의값입니다. record return_expression 으로평가한결과가할당되는레코드입니다. return_expression 의첫번째결과가 record 에서첫번째필드에할당됩니다. 2 번째결과가 2 번째필드에할당됩니다. 이하동일합니다. record 의필드수는식의수와동일해야합니다. 또한필드는할당된식과호환성있는형이어야합니다. 143
144 variable return_expression 으로평가한결과가할당되는변수입니다. 1 개이상의 return_expression 과 variable 이지정되면, return_expression 의첫번째결과가첫번째 variable 에할당됩니다. 2 번째결과가 2 번째 variable 에할당됩니다. 이하동일합니다. INTO 에이어지정된변수의수는 RETURNING 에이어지정표현식의수와동일해야합니다. 또한변수는할당된식과호환성있는형이어야합니다. collection return_expression 으로평가한결과에서생성된요소의 collection 입니다. 하나의 collection 은단일필드의 collection 일수도있고, 또는레코드형의 collection 일수있습니다. 또는각 collection 이단일필드로구성된여러 collection 일지도모릅니다. 반환된식의수는모두지정된 collection 의필드수와동일해야합니다. 또한해당 return_expre ssion 과 collection 필드는형태호환성이있어야합니다. 예 Jobhist 테이블에서 empno 가 7900 직원을모두삭제합니다. DELETE FROM jobhist WHERE empno = 7900; jobhist 테이블을비웁니다. DELETE FROM jobhist; 관련항목 TRUNCATE DROP DATABASE LINK 이름 DROP DATABASE LINK - 데이터베이스링크를삭제합니다 개요 DROP [PUBLIC] DATABASE LINK name 144
145 설명 DROP DATABASE LINK 는기존데이터베이스링크를삭제합니다. 이명령을실행하려면, 슈퍼 사용자또는데이터베이스링크의소유자여야합니다. 매개변수 name 삭제되는데이터베이스링크의이름입니다. PUBLIC name 이 public 데이터베이스링크에있다는것을나타냅니다. 예 oralink 라는 public 데이터베이스링크를삭제합니다. DROP PUBLIC DATABASE LINK oralink; edblink 라는 private 데이터베이스링크를삭제합니다. DROP DATABASE LINK edblink; 관련항목 CREATE DATABASE LINK DROP FUNCTION 이름 DROP FUNCTION - 함수를삭제합니다 개요 DROP FUNCTION name [(type [...])] 설명 145
146 DROP FUNCTION 은기존의함수정의를삭제합니다. 이명령을수행하려면, 슈퍼유저또는함수의소유자여야합니다. 인수가적어도 1 개존재하는경우, 함수의인수형은반드시지정해야합니다. ( 이요구사항은 Oracle 과호환되지않습니다. Postgres Plus Advanced Server 는함수명의오버로딩을허용하므로 Postgres Plus Advanced Server 의 DROP FUNCTION 명령은함수서명을요청합니다.) 매개변수 name 기존함수의이름 ( 스키마로수식된이름도가능 ) 입니다. type 함수의인수데이터형입니다. 예 다음의명령은 emp_comp 함수를삭제합니다. DROP FUNCTION emp_comp (NUMBER, NUMBER); 관련항목 CREATE FUNCTION DROP INDEX 이름 DROP INDEX - 인덱스를삭제합니다 개요 DROP INDEX name 설명 146
147 DROP INDEX 는데이터베이스시스템에서기존인덱스를삭제합니다. 이명령을 수행하려면슈퍼유저또는해당인덱스의소유자여야합니다. 해당인덱스에의존하는객체가 있는경우, 에러가발생하고인덱스는삭제되지않습니다. 매개변수 name 삭제할인덱스의이름 ( 스키마로수식된이름도가능 ). 예 다음은 name_idx 인덱스를삭제합니다. DROP INDEX name_idx; 관련항목 ALTER INDEX, CREATE INDEX DROP PACKAGE 이름 DROP PACKAGE - 패키지를제거한다 개요 DROP PACKAGE [BODY] name 설명 DROP PACKAGE 는기존패키지를제거합니다. 이명령을수행하려면슈퍼유저또는패키지의 소유자여야합니다. BODY 가지정된경우, 패키지본문만삭제됩니다. 패키지사양은삭제되지 않습니다. BODY 가생략되면패키지사양과본문모두삭제됩니다. 매개변수 name 147
148 삭제할패키지의이름 ( 스키마로수식된이름도가능 ). 예 이명령은 emp_admin 패키지를삭제합니다. DROP PACKAGE emp_admin; 관련항목 CREATE PACKAGE, CREATE PACKAGE BODY DROP PROCEDURE 이름 DROP PROCEDURE - 프로시저를삭제합니다 개요 DROP PROCEDURE name 설명 DROP PROCEDURE 는기존프로시저를삭제합니다. 이명령을수행하려면슈퍼유저또는그 프로시저의소유자여야합니다. 매개변수 name 기존프로시저의이름 ( 스키마로수식된이름도가능 ) 입니다. 예 이명령은 select_emp 프로시저를삭제합니다. DROP PROCEDURE select_emp; 148
149 관련항목 CREATE PROCEDURE DROP PUBLIC SYNONYM 이름 DR OP PUBLIC SYNONYM - public 동의어를삭제합니다 개요 DROP PUBLIC SYNONYM name 설명 DROP PUBLIC SYNONYM 은기존 public 동의어를삭제합니다. 이명령을수행하려면슈퍼유저 또는 public 동의어의소유자여야합니다. public 동의어에대한자세한내용은제 장을참조하십시오. 매개변수 name 제거할 public 동의어의이름입니다. 예 이명령은 personnel 이라는 public 동의어를삭제합니다. DROP PUBLIC SYNONYM personnel; 관련항목 CREATE PUBLIC SYNONYM DROP ROLE 이름 149
150 DROP ROLE - 데이터베이스역할을제거합니다 개요 DROP ROLE name [CASCADE] 설명 DROP ROLE 은지정된역할을삭제합니다. 슈퍼유저역할을제거하려면, 자신도슈퍼유저여야 합니다. 슈퍼유저이외의역할을제거하려면 CREATEROLE 권한을가져야합니다. 임의의데이터베이스클러스터에서참조하는경우, 역할을삭제할수없습니다. 삭제하려고하면, 에러가발생합니다. 역할을삭제하기전에, 해당역할이소유한모든객체를삭제 ( 또는소유권 변경 ) 해야합니다. 또그역할에부여된권한도거론해야합니다. 하지만역할에포함된역할구성원자격을삭제할필요는없습니다. DROP ROLE 은자동으로 다른역할내에있는대상역할과대상역할에있는다른역할의구성원자격을 취소합니다. 다른역할이삭제되지도않고달리영향을받지도않습니다. 역할이소유하는, 역할과동일한이름의스키마에역할이소유한객체밖에없는경우, CASCADE 옵션을지정할수있습니다. 이경우 DROP ROLE name CASCADE 명령을실행할수있는것은슈퍼유저뿐입니다. 이명령을사용하면특정역할이외에, 역할과동일한이름의스키마와스키마에있는모든객체를삭제할수있습니다. 매개변수 name 삭제할역할의이름입니다. CASCADE 이매개변수가지정된경우, 역할이소유하는, 역할과동일한이름의스키마를 제거합니다. ( 스키마에속해있는, 역할이소유하는객체가모두삭제합니다.) 지정할수있는역할 또는스키마에다른종속관계가없는경우입니다. 예 역할을삭제합니다. DROP ROLE admins; 150
151 관련항목 ALTER ROLE, CREATE ROLE, SET ROLE DROP SEQUENCE 이름 DROP SEQUENCE - 시퀀스를제거합니다 개요 DROP SEQUENCE name [...] 설명 DROP SEQUENCE 는시퀀스번호생성기를삭제합니다. 이명령을 수행하려면슈퍼유저또는시퀀스의소유자여야합니다. 매개변수 name 시퀀스의이름 ( 스키마로수식된이름도가능 ). 예 Serial 이라는시퀀스를삭제합니다. DROP SEQUENCE serial; 관련항목 ALTER SEQUENCE, CREATE SEQUENCE DROP TABLE 이름 DROP TABLE - 테이블을삭제합니다 151
152 개요 DROP TABLE name 설명 DROP TABLE 은데이터베이스에서테이블을삭제합니다. 테이블소유자만이테이블을삭제할수 있습니다. 테이블을삭제하지않고테이블행을비우려면, DELETE 를이용하세요. DROP TABLE 은삭제되는테이블에있는인덱스, 룰, 트리거, 제약을삭제합니다. 매개변수 name 삭제할테이블의이름 ( 스키마로수식된이름도가능 ). 예 emp 테이블을삭제합니다. DROP TABLE emp; 관련항목 ALTER TABLE, CREATE TABLE.3.37 DROP TABLESPACE 이름 DROP TABLESPACE - 테이블스페이스를삭제합니다 개요 DROP TABLESPACE tablespacename 설명 DROP TABLESPACE 시스템에서테이블스페이스를삭제합니다. 152
153 테이블스페이스의소유자또는슈퍼유저만이테이블스페이스를삭제할수있습니다. 테이블스페이스를삭제하기전에모든데이터베이스객체가비어있어야합니다. 현재데이터베이스내의객체가테이블스페이스를사용하지않았다하더라도, 다른데이터베이스의객체가테이블스페이스에있을수있습니다. 매개변수 tablespacename 테이블스페이스의이름입니다. 예 employee_space 테이블스페이스를시스템에서삭제합니다. DROP TABLESPACE employee_space; 관련항목 ALTER TABLESPACE DROP TRIGGER 이름 DROP TRIGGER - 트리거를삭제합니다 개요 DROP TRIGGER name 설명 DROP TRIGGER 는트리거관련테이블에서트리거를삭제합니다. 이명령을수행하려면슈퍼유저 또는트리거가정의된테이블의소유자여야합니다. 매개변수 name 삭제되는트리거의이름입니다. 153
154 예 emp_sal_trig 트리거를삭제합니다. DROP TRIGGER emp_sal_trig; 관련항목 CREATE TRIGGER DROP USER 이름 DROP USER 데이터베이스사용자계정을삭제합니다 개요 DROP USER name [CASCADE] 설명 DROP USER 는지정된사용자를삭제합니다. 슈퍼유저만이슈퍼유저를삭제할수 있습니다. 슈퍼유저이외의사용자를삭제하려면, CREATEROLE 권한을가져야합니다. 데이터베이스클러스터중하나에서참조하는경우사용자를삭제할수없습니다. 삭제하려고 하면에러가발생합니다. 사용자를삭제하기전에, 사용자가소유한모든객체를삭제 ( 또는 소유권변경 ) 해야합니다. 또한사용자에게부여한권한도취소해야합니다. 그러나사용자를포함한역할구성원자격을삭제할필요는없습니다. DROP USER 는자동으로 다른역할내에있는대상역할과대상역할에있는다른역할의구성원자격을 취소합니다. 다른역할이삭제되지도않고달리영향을받지도않습니다. 사용자가소유한, 사용자와동일한이름의스키마에사용자가소유한객체밖에없는경우 CASCADE 옵션을지정할수있습니다. 이경우, DROP USER name CASCADE 명령을실행할수있는것은슈퍼유저뿐입니다. 이명령을사용하면지정된사용자이외에, 사용자와동일한이름의스키마, 스키마에있는모든객체를삭제할수있습니다. 매개변수 name 154
155 삭제할사용자의이름입니다. CASCADE 이매개변수를지정하면, 사용자가소유하는사용자와동일한이름의스키마를 삭제합니다. ( 스키마에속하는사용자가소유하는객체를모두삭제합니다.) 지정할수있는 사용자또는스키마에다른종속관계가없는경우입니다. 예 객체를소유하지않고, 다른객체에대한권한도부여되지않은사용자계정을삭제합니다. DROP USER john; john 이라는사용자계정을삭제합니다. 이사용자는자신이소유한 john 이라는스키마외부 객체에대한권한이부여되지않으며, 외부객체를소유하고있지않습니다. DROP USER john CASCADE; 관련항목 ALTER USER, CREATE USER DROP VIEW 이름 DROP VIEW - 뷰를삭제합니다 개요 DROP VIEW name 설명 DROP VIEW 는기존의뷰를삭제합니다. 이명령을수행하려면, 뷰의소유자여야합니다. 다른 객체가지정된뷰에의존하는경우 ( 뷰의뷰와같은경우 ), 뷰가삭제되지않습니다. 매개변수 name 155
156 삭제할뷰의이름 ( 스키마로수식된이름도가능 ). 예 다음은 dept_30 라는뷰를삭제합니다. DROP VIEW dept_30; 관련항목 CREATE VIEW GRANT 이름 GRANT - 액세스권한을정의합니다 개요 GRANT ((SELECT INSERT UPDATE DELETE REFERENCES) [,...] ALL [PRIVILEGES]) ON tablename TO (username groupname PUBLIC) [...] [WITH GRANT OPTION] GRANT (SELECT ALL [PRIVILEGES]) ON sequencename TO (username groupname PUBLIC) [...] [WITH GRANT OPTION] GRANT (EXECUTE ALL [PRIVILEGES]) ON FUNCTION progname ([[argmode] [argname] argtype] [...]) TO (username groupname PUBLIC) [...] [WITH GRANT OPTION] GRANT (EXECUTE ALL [PRIVILEGES]) 156
157 ON PROCEDURE progname [([[argmode] [argname] argtype] [...])] TO (username groupname PUBLIC) [...] [WITH GRANT OPTION] GRANT (EXECUTE ALL [PRIVILEGES]) ON PACKAGE packagename TO (username groupname PUBLIC) [...] [WITH GRANT OPTION] GRANT role [...] TO (username groupname PUBLIC) [...] [WITH ADMIN OPTION] GRANT (CONNECT RESOURCE DBA) [...] TO (username groupname ) [...] [WITH ADMIN OPTION] 설명 GRANT 명령은기본적으로 2 가지종류가있습니다. 1 개는데이터베이스객체 ( 테이블, 뷰, 시퀀스, 프로그램 ) 에대한권한부여, 다른 1 개는역할의구성원자격을부여합니다. 이들은많은 점에서유사하지만, 설명은별도로설명될만큼차이가있습니다. Postgres Plus Advanced Server 에서는사용자및그룹과같은개념은역할이라는단일종류의엔티티로통합되었습니다. 이본문에서, 사용자는 LOGIN 속성을가진역할입니다. 이역할은세션을생성하고, 애플리케이션에연결하는데사용됩니다. 그룹은 LOGIN 속성이없는역할입니다. 이곳은세션생성및애플리케이션에연결하는데사용되지않습니다. 역할은다른여러역할의구성원이될수있습니다. 그런의미에서, 그룹에속하는사용자의전형적인개념은아직유효합니다. 그러나, 현재는사용자와그룹이일반화되어, 사용자는사용자에속할수도, 그룹은그룹에속할수도, 그룹이사용자에속할수도있습니다. 즉, 역할의일반화된다계층구조를형성할수있습니다. 사용자이름과그룹이름이동일한네임스페이스에공유됩니다. 따라서 GRANT 명령은사용자와그룹을구별할필요가없습니다 데이터베이스객체에대한 GRANT GRANT 명령은데이터베이스객체에대한특정권한을역할에부여하기도합니다. 이미권한이 다른역할에부여된경우에도추가로부여됩니다. 157
158 PUBLIC 키워드는앞으로생성될역할을포함한모든역할에대한권한을나타냅니다. PUBLIC 은모든역할을포함한암시적으로정의된그룹이라생각할수있습니다. private 적인역할은모두역할에직접부여된권한, 역할이현재속한역할에부여된권한, 그리고 PUBLIC 으로부여된권한을합친권한을가지고있습니다. WITH GRANT OPTION 이지정되면, 권한수령자인경우, 다른사람에게그권한을부여할수 있습니다. 그랜트옵션이없는경우, 받는사람은이것을할수없습니다. 그랜트 옵션은 PUBLIC 에부여할수없습니다. 객체의소유자 ( 일반적으로객체를만든사용자 ) 는기본적으로모든권한이있기때문에소유자에게권한을허용할필요는없습니다 ( 단, 객체의소유자가안전을위해자신의권한을취소할수있습니다 ). 객체를삭제하는권리나어떤방법으로객체정의를수정할권한은부여가능한권한이아닙니다. 이러한권한은소유자의고유한것이며권한을주거나취소하는것은불가능합니다. 소유자는객체에대한그랜트옵션을암시적으로보유하고있습니다. 객체의종류에따라, 기본권한으로, 처음부터어떤권한이 PUBLIC 으로부여되는경우가있습니다. 기본적으로테이블에액세스할수없습니다. 또한, 함수, 프로시저, 패키지는기본권한으로 EXECUTE 권한이부여됩니다. 물론객체의소유자는이권한을취소할수있습니다 ( 최대의안전을위해, REVOKE 명령은객체를생성하는같은트랜잭션에서발행합니다. 이렇게하면다른사용자가이객체를사용할윈도우가없습니다.) 구성가능한권한은다음과같습니다. SELECT 지정한테이블, 뷰, 시퀀스의모든열에대한 SELECT 를허용합니다. 시퀀스에대해, 이 권한은 currval 함수의사용을허용합니다. INSERT 지정한테이블에새행의 INSERT 를허용합니다. UPDATE 지정한테이블의모든열에대한 UPDATE 를허용합니다. SELECT... FOR UPDATE 도 (SELECT 권한 외에 ) 이권한을필요로합니다. DELETE 지정한테이블에서행 DELETE 를허용합니다. 158
159 REFERENCES 외래키제약조건을만들려면, 참조하는쪽과참조되는쪽양쪽테이블에대해이권한을갖고 있고있어야합니다. EXECUTE 지정된패키지프로시저, 함수의사용을허용합니다. 패키지에적용할경우, 패키지에포함된 모든 public 프로시저, public 함수, public 변수, 레코드, 커서및기타 public 객체와객체의 사용을허용합니다. EXECUTE 는함수, 프로시저, 패키지에적용할수있는유일한권한입니다. Postgres Plus Advanced Server 에서 EXECUTE 사용권한을부여하는구문은완전히 Oracle 과호환되지않습니다. Postgres Plus Advanced Server 에서 FUNCTION, PROCEDURE, PACKAGE 중하나를프로그램이름앞에붙여야합니다. 한편, Oracle 에서는이것을생략해야합니다. 또한 Postgres Plus Advanced Server 에서는함수이름다음에전체적인함수서명 ( 함수의인수가없으면빈괄호포함 ) 을포함해야합니다. 프로시저에있어서는 1 개이상인수를가진경우전체서명이필요합니다. Oracle 에서는함수와프로시저서명을생략해야합니다. 이것은 Oracle 에서는모든프로그램에서동일한네임스페이스를공유하기때문입니다. 한편 Postgres Plus Advanced Server 에서특정한확장을위해프로그램이름의오버로딩이가능하기때문에, 함수, 프로시저, 패키지가각각의네임스페이스를갖습니다. ALL PRIVILEGES 사용가능한모든권한을동시에부여합니다. 기타명령을실행하는데필요한권한은해당명령참조페이지에기재되어있습니다 역할에대한 GRANT 또다른 GRANT 명령은역할에있는구성원자격을 1 개이상의역할에부여합니다. 이에따라 역할에부여된권한을각구성원에게전달하므로, 역할에있는구성원자격은중요합니다. WITH ADMIN OPTION 이지정된경우, 구성원은역할의구성원자격을다른사람에게부여할수있습니다. 또한마찬가지로역할에서구성원자격을박탈하는것도가능합니다. admin option 없이, 일반사용자는다른사람에대한권한부여및박탈을할수없습니다. 그러나데이터베이스슈퍼유저는모든역할의구성원자격을누구나부여하거나박탈할수있습니다. CREATEROLE 권한을가진역할은슈퍼유저가아닌역할의구성원자격부여, 박탈이가능합니다. 다음은미리정의된 3 가지역할입니다. 159
160 CONNECT CONNECT 역할을부여하는것은 LOGIN 권한을부여하는것과 동일합니다. 부여자는 CREATEROLE 권한이있어야합니다. RESOURCE RESOURCE 역할을부여하는것은부여받는사람의이름과같은이름의스키마에대해 CREATE 권한과 USAGE 권한을부여하는것과동일합니다. 이스키마는명령을실행하기전에존재해야합니다. 부여자는스키마에대해 CREATE 권한과 USAGE 권한을부여할수있는권한이있어야합니다. DBA DBA 역할을부여하는것은받는사람을슈퍼유저로만드는것과동일합니다. 부여자는 슈퍼유저여야합니다. 주석 권한을취소하려면 REVOKE 명령을사용합니다. 객체의소유자도아니고객체에대한권한이없는사용자가객체의권한을 GRANT 하려고해도명령은즉각실패합니다. 어떤권한을갖고있는한, 명령은진행되지만부여할수있는권한은사용자가가진그랜트옵션에대한권한입니다. 그랜트옵션이없는경우, GRANT ALL PRIVILEGES 구문은경고메시지를발행합니다. 한편다른구문은명령에서이름을지정한권한에대한그랜트옵션이없는경우, 경고메시지를발행합니다 ( 대체로여기까지의설명은객체의소유자에대해서도마찬가지로적용됩니다, 그러나소유자는항상전체그랜트옵션을보유하고있는것으로취급하기때문에이런상황은결코발생하지않습니다 ). 데이터베이스슈퍼유저만이객체에대한권한설정에관계없이모든객체에접근할수있다는것에주의해야합니다. 슈퍼유저가갖는권한은 Unix 시스템의 root 권한과비슷합니다. root 뿐만아니라절대적으로필요한경우가아니면, 슈퍼유저로수행하지않는것이현명합니다. 슈퍼유저가 GRANT 와 REVOKE 발행을선택하면, 명령은해당객체의소유자가발행한것처럼실행됩니다. 특히이같은명령에대한권한은객체의소유자에의해부여된것으로나타납니다. ( 역할의구성원자격에대해, 구성원자격이포함된역할자체가부여된것으로나타납니다.) 160
161 GRANT 및 REVOKE 은영향을주는객체의소유자가아닌다른역할을통해수행할수있지만, 객체를소유하는역할의구성원이거나해당객체에대해 WITH GRANT OPTION 권한을가진역할의구성원인경우, 이를수행할수있습니다. 이경우해당권한은객체의실제소유자역할이나 WITH GRANT OPTION 권한을가진역할에의해부여된것으로기록됩니다. 예를들면, t1 테이블이 g1 역할에의해소유되고 u1 이 g1 역할의구성원이라고가정합니다. 이경우 u1 은 t1 의권한을 u2 에게부여할수있습니다. 그러나, 이러한권한은 g1 에의해직접적으로부여되는것으로나타납니다. 나중에 g1 역할의다른구성원이권한을취소할수도있습니다. GRANT 를수행한역할이역할의여러구성원자격경로를통해간접적으로필요한권한을가진 경우, 어떤역할이권한을부여하는역할로기록되는지의내용은지정되지않습니다. 이럴경우 SET ROLE 을사용하여 GRANT 를수행하고자하는역할이되는것이좋습니다. 현재로서는 Postgres Plus Advanced Server 는테이블의각열에대해권한을부여하거나취소할 수없습니다. 이를해결하려면대상으로하는열이있는뷰를만든다음, 이뷰에대한권한을 부여합니다. 예 emp 테이블에데이터를추가할수있는권한을모든사용자에게부여합니다. GRANT INSERT ON emp TO PUBLIC; salesemp 뷰에서사용가능한모든권한을 mary 사용자에게부여합니다. GRANT ALL PRIVILEGES ON salesemp TO mary; 위명령을슈퍼유저와 emp 소유자가실행하면모든권한이부여되지만, 다른사용자가실행하면 해당사용자가가지고있는그랜트옵션이있는권한만부여되는것을주의하십시오. admins 역할의구성원자격을 joe 사용자에게부여합니다. GRANT admins TO joe; CONNECT 권한을 joe 사용자에게부여합니다. GRANT CONNECT TO joe; 관련항목 REVOKE, SET ROLE 161
162 INSERT 이름 IN SERT - 테이블에새행을생성합니다 개요 INSERT INTO table [@ dblink] [(column [...])] (VALUES ((expression DEFAULT) [...]) [RETURNING return_expression [...] (INTO (record variable [...]) BULK COLLECT INTO collection [...])] query) 설명 INSERT 는테이블에새행을삽입시킵니다. 단일행을삽입할뿐아니라쿼리의결과로한번에 1 행이상의행을삽입할수있습니다. 데이터를삽입하는줄은어떤순서로나열되어있을수도있습니다. 대상리스트에제시되지 않은각각의열은기본값을사용하여삽입됩니다. 열에는지정된 기본값이나 null 이들어있습니다. 각열의식이올바른데이터형이아닌경우에는자동으로형변환을수행합니다. INSERT 명령이 SPL 프로그램에서 VALUES 어구와함께사용되는경우에만 RETURNING INTO (record variable [...]) 어구를지정할수있습니다. INSERT 명령이 SPL 프로그램에서사용되는경우에만 RETURNING BULK COLLECT INTO collection [...] 어구를지정할수있습니다. BULK COLLECT INTO 어구를대상으로여러 collection 이지정된경우각 collection 은단순한스칼라필드로구성되어야합니다. 즉, collection 레코드는안됩니다. 삽입된각행에대해평가된 return_expression 은첫번째요소로시작하는 collection 의요소입니다. collection 에있는기존행은삭제됩니다. 결과가비어있으면 collection 은비어있습니다. 162
163 테이블에행을추가하려면해당테이블에 INSERT 권한이있어야합니다. 쿼리를사용하여조회 결과를근거로행을삽입하는경우, 쿼리에서사용되는모든테이블에대해 SELECT 권한이 있어야합니다. 매개변수 table 기존테이블의이름 ( 스키마로수식된이름도가능 ). dblink 원격데이터베이스를식별하는데이터베이스링크의이름입니다. 데이터베이스링크에대한 자세한내용은 CREATE DATABASE LINK 명령을참조하십시오. column table 에있는열이름입니다. expression 해당 column 에할당하는식또는값을지정합니다. DEFAULT 해당 column 에기본값을설정합니다. query 삽입하는행을제공하는질문 (SELECT 문 ) 입니다. 구문에대한설명은 SELECT 를참조하십시오. return_expression table 의 1 개이상의열이포함식입니다. return_expression 에서 table 의열이름이지정된경우, return_expression 평가후열에할당되는값은다음과같이결정됩니다. return_expression 에서지정한열이 INSERT 명령에서값을할당하면, return_expression 평가중, 할당된값이사용됩니다. return_expression 에서지정한열이 INSERT 명령에서값이할당되지않고, 테이블의열 정의에서도열의기본값이설정되지않은경우 return_expression 평가중에, null 이사용됩니다. 163
164 return_expression 에서지정한열이 INSERT 명령에서값이할당되지않고, 테이블의열정의에서 열의기본값이지정된경우 return_e xpression 평가중에기본값이사용됩니다. record return_exp ression 으로평가한결과가할당되는레코드입니다. return_expression 의첫번째결과가 record 에서첫번째필드에할당됩니다. 2 번째결과가 2 번째필드에할당됩니다. 이하동일합니다. record 의필드의수는식의수와동일해야합니다. 또한필드는할당하는식의형식 (type) 과호환되어야합니다. variable return_expression 으로평가한결과가할당되는변수입니다. 1 개이상의 return_expression 과 variable 이지정되면, return_expression 의첫번째결과가첫번째 variable 에할당됩니다. 2 번째결과가 2 번째 variable 에할당됩니다. 이하동일합니다. INTO 에이어제공되는변수의수는 RETURNING 에이어지는표현식의수와동일해야합니다. 또한변수는할당하는식의형식과호환되어야합니다. collection return_expression 으로평가한결과에서생성되는요소의집합 (collection) 입니다. 하나의집합, 즉단일필드집합수도있고, 레코드형식의집합일수도있습니다. 또는각집합이단일필드로구성된여러집합일지도모릅니다. 반환된식의수는모두지정된집합의필드수와동일해야합니다. 또한해당 return_expression 과 collection 필드는형식과호환되어야합니다. 예 emp 테이블에 1 행을삽입합니다. INSERT INTO emp VALUES (8021, 'JOHN', 'SALESMAN', 7698, '22 - FEB - 07 ', 1250,500,30); 이예에서는 comm 열이생략되었습니다. 따라서 comm 열에는기본값 null 이할당됩니다. INSERT INTO emp (empno, ename, job, mgr, hiredate, sal, deptno) VALUES (8022, 'PETERS', 'CLERK', 7698, '03 - DEC - 06 ', 950,30); 이예에서는 hiredate 열과 comm 열에값을지정하는것이아니라 DEFAULT 어구를사용하고 있습니다. INSERT INTO emp VALUES (8023, 'FORD', 'ANALYST', 7566, DEFAULT, 3000, DEFAULT, 20); 164
165 이경우, deptnames 테이블을만들고, dept 테이블의 dname 열에서선택한결과를삽입합니다. CREATE TABLE deptnames ( deptname VARCHAR2 (14) ); INSERT INTO deptnames SELECT dname FROM dept; LOCK 이름 LOCK - 테이블에락을겁니다 개요 LOCK TABLE name [...] IN lockmode MODE [NOWAIT] lockmode 는다음중하나입니다. ROW SHARE ROW EXCLUSIVE SHARE SHARE ROW EXCLUSIVE EXCLUSIVE 설명 LOCK TABLE 테이블수준의락을가져옵니다. 필요하면충돌하는락을해제할때까지기다립니다. NOWAIT 이지정되면, LOCK TABLE 이필요로하는락을얻으려고대기하지않습니다. 이경우즉시락을인식하지못한다면, 명령을중지하고에러를출력합니다. 락은한번취득하면현재트랜잭션이완료될때까지유지됩니다 (UNLOCK TABLE 같은명령은없습니다. 락은항상트랜잭션을종료할때해지됩니다 ). 테이블을참조하는명령을위해자동으로락을거는경우, Postgres Plus Advanced Server 는항상사용가능한가장약한락모드를사용합니다. LOCK TABLE 은보다엄격한락이필요한경우를위해제공됩니다. 예를들면, 격리수준의읽기가커밋된상황에서트랜잭션을수행하는애플리케이션이있고, 트랜잭션내내테이블의데이터를안정적으로안정시킬필요가있는경우를생각해볼수있습니다. 이경우쿼리를실행하기전에테이블전체에 SHARE 락모드를사용합니다. 이렇게하면데이터가동시에변경되는것을방지하고이후테이블의읽기를안정시킬수있습니다. 왜냐하면 SHARE 락모드는쓰기측이얻을 ROW EXCLUSIVE 락과충돌하기때문에, LOCK TABLE name IN SHARE MODE 문은 ROW EXCLUSIVE 모드락을유지하는트랜잭션이커밋되거나롤백되기를기다립니다. 따라서한번락을확보하면, 커밋되지않은 165
166 상태의기록은존재하지않는것입니다. 또한락을해제하기전에다른애플리케이션은 쓰기 (write) 를시작할수없습니다. 직렬화격리수준에서실행되는트랜잭션에서같은효과를얻으려면, 모든데이터의변경된문장을실행하기전에 LOCK TABLE 문을실행해야합니다. 직렬화트랜잭션측데이터의뷰는먼저데이터변경된문장이시작되면고정됩니다. 나중에트랜잭션에서 LOCK TABLE 을실행하면동시쓰기를방지할수있지만, 트랜잭션읽기데이터값이커밋된최신값인것은보장하지않습니다. 이러한트랜잭션에서테이블데이터를변경하려면, SHARE 모드가아닌 SHARE ROW EXCLUSIVE 락모드를사용해야합니다. 이에따라한번에한트랜잭션만이실행될수있습니다. SHARE ROW EXCLUSIVE 를사용하지않으면교착상태가발생할수있습니다. 2 개의트랜잭션이모두, SHARE 모드를보유하고있으면서실제변경하는데필요한 ROW EXCLUSIVE 모드를확인할수없는상태가될가능성이있기때문입니다 ( 트랜잭션자신이소유하고있는락사이의충돌이없기때문에, 트랜잭션이 SHARE 형태를유지하고있는동안 ROW EXCLUSIVE 를획득할수있지만다른트랜잭션이 SHARE 모드를유지하고있는경우에는 ROW EXCLUSIVE 을획득할수없습니다 ). 교착상태를해결하려면, 모든트랜잭션이반드시동일객체에대해동일한순서로락을획득하는것이좋습니다. 또한 1 개의객체에대해다중의락모드를호출하는경우, 트랜잭션은항상가장엄격한모드를먼저취득해야합니다. 매개변수 name 락을걸기위한기존테이블의이름 ( 스키마로수식된이름도가능 ). LOCK TABLE a, b; 명령은 LOCK TABLE a; LOCK TABLE b 와동일합니다. 테이블은하나씩 LOCK TABLE 명령에지정된순서로락이걸립니다. Lockmode 락모드는충돌하는것에락을걸도록지정합니다. 락모드를지정하지않으면, 가장제약이강한 ACCESS EXCLUSIVE 모드를사용합니다. (ACCESS EXCLUSIVE 는 Oracle 과호환되지않습니다. Postgres Plus Advanced Server 에서, 이모드는다른 트랜잭션이어떤방법으로도락이걸린테이블에액세스할수없게합니다.) NOWAIT 166
167 LOCK TABLE 이충돌하는락이해제되는것을대기하지않도록지정합니다. 지정된락을즉시 획득할수없으면트랜잭션은중단됩니다. 주석 모든형태의 LOCK 은 UPDATE 및 / 또는 DELETE 권한이있어야합니다. LOCK TABLE 은트랜잭션블록내부에서만사용할수있습니다. 따라서트랜잭션이완료되면락도 삭제됩니다. 트랜잭션블록외부에서 LOCK TABLE 명령을실행하면명령만을포함한트랜잭션이 형성되기때문에, 이락은취득후즉시삭제됩니다. LOCK TABLE 은테이블수준의락만을처리합니다. 따라서 ROW 를포함하는모드이름은적절치않습니다. 이모드이름은보통락이걸린테이블에서행수준의락을얻을수있다고생각될것입니다. 또한, ROW EXCLUSIVE 모드는공유할수있는테이블락입니다. LOCK TABLE 에대해서는전체락모드가같은의미를가지고있다는것을명심하십시오. 다른것은어떤모드에관하여어떤락모드와충돌한다는규칙뿐입니다 REVOKE 이름 REVOKE - 액세스권한을취소한다 개요 REVOKE ((SELECT INSERT UPDATE DELETE REFERENCES) [,...] ALL [PRIVILEGES]) ON tablename FROM (username groupname PUBLIC) [...] [CASCADE RESTRICT] REVOKE (SELECT ALL [PRIVILEGES]) ON sequencename FROM (username groupname PUBLIC) [...] [CASCADE RESTRICT] REVOKE (EXECUTE ALL [PRIVILEGES]) ON FUNCTION progname 167
168 ([[argmode] [argname] argtype] [...]) FROM (username groupname PUBLIC) [...] [CASCADE RESTRICT] REVOKE (EXECUTE ALL [PRIVILEGES]) ON PROCEDURE progname [([[argmode] [argname] argtype] [...])] FROM (username groupname PUBLIC) [...] [CASCADE RESTRICT] REVOKE (EXECUTE ALL [PRIVILEGES]) ON PACKAGE packagename FROM (username groupname PUBLIC) [...] [CASCADE RESTRICT] REVOKE role [...] FROM (username groupname PUBLIC) [...] [CASCADE RESTRICT] REVOKE (CONNECT RESOURCE DBA) [...] FROM (username groupname) [...] 설명 REVOKE 명령은 1 개이상의역할에대해이전에부여한권한을취소합니다. PUBLIC 키워드는 암시적으로정의된모든역할로구성된그룹입니다. 권한종류의의미에대해서는 GRANT 명령에대한설명을참조하십시오. 전체역할은그역할에직접부여된권한, 현재속해있는역할에부여된권한, PUBLIC 에부여된권한의 3 가지능력을가지고있다는것을명심하십시오. 따라서, 예를들면, PUBLIC 에서 SELECT 권한을취소하는것은전체역할이객체에대한 SELECT 권한을잃는것을의미합니다. 권한이직접적으로허용되는역할또는다른역할을통해허용되는역할은 SELECT 권한이유지됩니다. 권한이그랜트옵션과함께부여되어있는경우, 권한뿐만아니라그랜트옵션도취소됩니다. 그랜트옵션과권한이있는사용자가그권한을다른사용자에게부여하면, 부여받은사용자가보유하고있는권한은의존권한이라고합니다. 첫번째사용자가보유한권한또는그랜트옵션이취소된때, 그권한에의존권한이있으면, 그리고 CASCADE 가지정되면의존권한도 168
169 취소됩니다. 지정되지않으면권한취소가실패합니다. 이재귀적인권한취소는연이은사용자를통해부여된권한속에서도 REVOKE 를실행한사용자에게추적가능한범위내에서만적용됩니다. 따라서, 의존권한이있는사용자가다른사용자를통해권한을부여받는다면, REVOKE 을실행한후그권한을보유하고있을가능성이있습니다. 참고 : CASCADE 는 Oracle 호환옵션이없습니다. Oracle 은기본적으로의존권한을취소 cascades 합니다. 그러나 Postgres Plus Advanced Server 는분명히 CASCADE 를지정해야합니다. 지정하지 않으면 REVOKE 명령은실패합니다. 역할의구성원자격을취소하는경우처럼행동하지만 GRANT OPTION 아니라 ADMIN OPTION 가호출됩니다. 주석 취소할수있는사용자가직접부여한권한입니다. 예를들어, 사용자 A 가그랜트옵션을사용하여사용자 B 에게권한을주고, 그런다음사용자 B 가사용자 C 에게그권한을주었다고하면사용자 A 는사용자 C 의권한을직접취소할수없습니다. 대신, 사용자 A 가사용자 B 에게서그랜트옵션을박탈할수있고, 반대로 CASCADE 옵션을이용함으로인해사용자 C 에게권한을박탈당할수있습니다. 다른상황을생각해봅시다. A 와 B 모두가동일한권한을 C 에게준경우, A 는 A 에부여한권한을취소할수있지만, B 에부여한권한을취소할수없습니다. 따라서 C 는실질적으로그권한을계속가지고있는것입니다. 객체의소유자가아니면, 이객체의권한에대해 REVOKE 를실행하면사용자가객체에대한어떠한권한도가지고있지않는경우, 즉시명령이실패합니다. 어떤권한이있는경우명령처리가계속되지만, 취소할수있는권한은사용자에게그랜트옵션이있는권한입니다. REVOKE ALL PRIVILEGES 구문을전혀권한이없는상태에서실행하면경고메시지를발행합니다. 다른구문의경우그명령에명명된권한에대한그랜트옵션이없는상태에서실행하면경고를메시지를발행합니다. ( 대체로여기까지의설명은객체의소유자에대해서도마찬가지로적용됩니다, 그러나소유자는항상전체그랜트옵션을보유하고있는것으로취급하기때문에이런상황은결코발생하지않습니다 ) 슈퍼유저가 GRANT 와 REVOKE 발행을선택하면, 명령은해당객체의소유자가발행한것처럼실행됩니다. 근본적으로는모든권한은객체의소유자에서부터전달되는것이므로 ( 단, 그랜트옵션의연쇄를통해간접적으로전달되는경우도있지만 ), 슈퍼사용자는모든권한을취소할수있습니다. 그러나이경우에는위에서언급한 CASCADE 를사용해야합니다. REVOKE 는영향을주는객체의소유자가아닌다른역할을통해수행할수있지만객체를소유하는역할의구성원이거나해당객체에대해 WITH GRANT OPTION 권한을가진역할의구성원이어야합니다. 이경우해당객체의실제소유자역할이나 WITH GRANT OPTION 권한을가진역할에의해발행된것같이, 이명령은실행됩니다. 예를들면, t1 테이블이 g1 역할에의해 169
170 소유되고 u1 이 g1 역할의구성원이있다고가정합니다. 이경우 u1 이 g1 가부여한것으로 기록되어있는 t1 권한을취소할수있습니다. 여기에는 u1 이부여한권한과 g1 역할의다른 멤버에의해부여된권한이포함됩니다. REVOKE 를수행한역할이역할의여러구성원자격경로를통해간접적으로필요한권한을가진경우, 어떤역할이권한을부여하는역할로기록되는지의내용은지정되지않습니다. 이럴경우 SET ROLE 을사용하여 REVOKE 을수행하고자하는특정역할이되는것이좋습니다. 이와같이하지않으면의도하지않은역할에의해권한을박탈하는것이되고, 취소자체가실패하게될수있습니다. 예 public 에게준 emp 테이블에대한삽입권한을취소합니다. REVOKE INSERT ON emp FROM PUBLIC; salesemp 뷰에서, mary 사용자에게준모든권한을취소합니다. REVOKE ALL PRIVILEGES ON salesemp FROM mary; 이것은 " 자신이준모든권한을취소한다 " 는것을의미한다는것에주의하세요. 사용자 joe 에서역할 admins 의구성원자격을취소합니다. REVOKE admins FROM joe; 사용자 joe 에서 CONNECT 권한을취소합니다. REVOKE CONNECT FROM joe; 관련항목 GRANT, SET ROLE ROLLBACK 이름 170
171 ROLL BACK - 현재트랜잭션을중단합니다 개요 ROLLBACK [WORK] 설명 ROLLBACK 은현재트랜잭션을롤백하고해당트랜잭션에서갱신된것전체를폐기합니다. 매개변수 WORK 선택가능한키워드입니다. 아무런효과가없습니다. 주석 트랜잭션을성공적으로완료하기위해서는 COMMIT 을사용하십시오. 트랜잭션외부에서 ROLLBACK 을실행해도문제가되지않습니다. ROLLBACK 은 SPL 프로그램에서지원되지않습니다. 예 모든변경사항을중단합니다. ROLLBACK; 관련항목 COMMIT, ROLLBACK TO SAVEPOINT, SAVEPOINT ROLLBACK TO SAVEPOINT 이름 ROLLBACK TO SAVEP OINT - 세이브포인트로롤백한다. 171
172 개요 ROLLBACK [WORK] TO [SAVEPOINT] savepoint_name 설명 세이브포인트설정후실행된명령을모두롤백합니다. 세이브포인트는유효한상태로남아 있기때문에, 필요에따라나중에다시돌아갈수있습니다. ROLLBACK TO SAVEPOINT 는명명된세이브포인트이후에설정된모든세이브포인트를 암시적으로삭제합니다. 매개변수 savepoint_name 롤백할세이브포인트. 주석 설정되지않은세이브포인트의이름을지정하면에러가발생합니다. ROLLBACK TO SAVEPOINT 는 SPL 프로그램에서지원되지않습니다. 예 depts 설정후실행한명령의효력을취소합니다. \ set AUTOCOMMIT off INSERT INTO dept VALUES (50, 'HR', 'NEW YORK'); SAVEPOINT depts; INSERT INTO emp (empno, ename, deptno) VALUES (9001, 'JONES', 50); INSERT INTO emp (empno, ename, deptno) VALUES (9002, 'ALICE', 50); ROLLBACK TO SAVEPOINT depts; 관련항목 COMMIT, ROLLBACK, SAVEPOINT SAVEPOINT 이름 172
173 SAVEPOINT - 현재트랜잭션에서새로운세이브포인트를정의합니다 개요 SAVEPOINT savepoint_name 설명 SAVEPOINT 는현재트랜잭션에서새로운세이브포인트를설정합니다. 세이브포인트는트랜잭션에붙이는특별한표시입니다. 세이브포인트를설정하면, 그이후에 실행된명령을모두롤백하여세이브포인트를지정한시점의트랜잭션의상태로되돌릴수 있습니다. 매개변수 savep oint_name 새로운세이브포인트에부여할이름입니다. 주석 세이브포인트로롤백하려면 ROLLBACK TO SAVEPOINT 를이용하세요. 세이브포인트는트랜잭션블록내부에서만설정할수있습니다. 1 개의트랜잭션중에는여러 세이브포인트를설정할수있습니다. 이미존재하는세이브포인트와같은이름의세이브포인트가설정된경우에는오래된 세이브포인트도유지됩니다. 하지만롤백때는새로운방식의세이브포인트를사용합니다. 예 세이브포인트를설정하고실행하는모든명령의효력을취소합니다. \ set AUTOCOMMIT off INSERT INTO dept VALUES (50, 'HR', 'NEW YORK'); SAVEPOINT depts; INSERT INTO emp (empno, ename, deptno) VALUES (9001, 'JONES', 50); INSERT INTO emp (empno, ename, deptno) VALUES (9002, 'ALICE', 50); 173
174 SAVEPOINT emps; INSERT INTO jobhist VALUES (9001, '17 - SEP - 07 ', NULL,'CLERK ', 800, NULL, 50,'New Hire '); INSERT INTO jobhist VALUES (9002, '20 - SEP - 07 ', NULL,'CLERK ', 700, NULL, 50,'New Hire '); ROLLBACK TO depts; COMMIT; 이트랜잭션은 dept 테이블에행의삽입은커밋되지만, emp 테이블과 jobhist 테이블에의 삽입은롤백됩니다. 관련항목 COMMIT, ROLLBACK, ROLLBACK TO SAVEPOINT SELECT 이름 SELECT 테이블이나뷰에서행을반환합니다 개요 SELECT [optimizer_hint] [ALL DISTINCT] * expression [AS output_name] [...] FROM from_item [...] [WHERE condition] [[START WITH start_expression] CONNECT BY (PRIOR parent_expr = child_expr c hild_expr = PRIOR parent_expr) [ORDER SIBLINGS BY expression [ASC DESC] [...]]] [GROUP BY expression [...] [LEVEL] [HAVING condition [...] [(UNION [ALL] INTERSECT MINUS) select] [ORDER BY expression [ASC DESC] [...] [FOR UPDATE] 여기서 from_item 는다음중하나입니다. table_name [@ dblink] [alias] 174
175 (select) alias from_item [NATURAL] join_type from_item [ON join_condition USING (join_column [...])] 설명 SELECT 는 1 개이상의테이블에서행을반환합니다. SELECT 의일반적인과정은다음과같습니다. 1. FROM 리스트에있는모든요소를계산합니다 (FROM 리스트에서의각요소는실제테이블 또는가상테이블입니다 ). FROM 역할에여러요소가지정되면, 그들은교차조인됩니다 ( 아래의 FROM 절참조 ). 2. WHERE 절이지정된경우, 조건을충족하지않는모든행은출력에서삭제합니다 ( 아래의 WHERE 절을참조하십시오 ). 3. GROUP BY 절이지정되면, 1 개이상의값이조건에맞는각행에대해그룹으로나눠 출력됩니다. HAVING 절이있는경우, 지정한조건을충족하지않는그룹은삭제됩니다 ( 아래의 GROUP BY 절과 HAVING 절을참조하십시오 ). 4. UNION, INTERSECT, MINUS 연산자를사용하면, 여러 SELECT 문의출력을 1 개의결과집합으로조인할수있습니다. UNION 연산자는두결과집합에있는행과한쪽의결과집합에있는행을모두반환합니다. INTERSECT 연산자는두결과집합에있는행을반환합니다. MINUS 연산자는첫번째결과집합이고, 2 번째결과집합에없는행을반환합니다. 이러한 3 가지경우모두, 중복되는행은삭제됩니다. UNION 연산자의경우, ALL 이지정되면중복되는행은삭제되지않습니다 ( 아래 UNION 어구, INTERSECT 어구, MINUS 절을참조하십시오 ). 5. 실제로는선택한각행에대해 SELECT 출력방식을사용하여계산한결과의행이표시됩니다 ( 아래의 SELECT 역할을참조하십시오 ). 6. CONNECT BY 절이지정된경우, 계층관계가있는데이터를선택합니다. 그러한자료는행 사이에친자관계를가지고있습니다 ( 아래의 CONNECT BY 절을참조하십시오 ). 7. ORDER BY 절이지정된경우, 반환된행은지정된순서로정렬됩니다. ORDER BY 가지정되지 않으면, 시스템이조사과정에서찾은가장빠른순서대로행을반환합니다 ( 아래의 ORDER BY 절을참조하십시오 ). 8. DISTINCT 는결과에서중복행을삭제합니다. ALL( 기본값 ) 에서중복행을포함하는모든후보 행을반환합니다 ( 자세한내용은아래 DISTINCT 절을참조하십시오 ). 175
176 9. FOR UPDATE 절을사용하면, SELECT 문은동시에발생하는갱신에대비해선택된행에락을 겁니다. ( 아래의 FOR UPDATE 절을참조하십시오 ). 테이블에서값을읽으려면 SELECT 권한이있어야합니다. FOR UPDATE 를사용하려면 또한 UPDATE 권한이있어야합니다. 매개변수 optimizer_hint 최적화프로그램이실행계획을선택할때사용하는주석에둔힌트입니다. 최적화힌트에대한 자세한내용은 3.4 장을참조하십시오. 기타매개변수는다음장에서설명합니다 FROM 어구 FROM 절에는 SELECT 의대상이되는원본테이블을 1 개이상지정합니다. 여러원본을지정하면 결과는전체원본의카티션곱 ( 교차조인 ) 입니다. 일반적으로제약조건을지정하고카티션곱의 일부를반환하도록결과행을제약합니다. FROM 절에다음과같은요소를포함할수있습니다. table_name [@ dblink] 기존테이블또는뷰이름 ( 스키마로수식된이름도가능 ). dblink 는원격데이터베이스를 식별하는데이터베이스링크이름입니다. 데이터베이스링크에대한자세한내용은 CREATE DATABASE LINK 명령을참조하십시오. alias 별칭을포함하는 FROM 항목의대체이름입니다. 별칭은간결하게하기위해, 혹은자기조인 ( 동일한테이블을여러번검사하는조인 ) 의애매함을없애기위해사용됩니다. 별칭이지정된경우, 해당별칭을통해실제테이블이름또는함수이름을완전히숨깁니다. 예를들면, FROM foo AS f 로지정되면, 이후 SELECT 문장에서는이 FROM 항목을 foo 가아닌 f 로참조해야합니다. select FROM 절에는하위 SELECT 를사용할수있습니다. 단일의 SELECT 명령을실행하는동안, 하위 SELECT 의결과는임시테이블에있는것처럼작동합니다. 하위 SELECT 는괄호로둘러싸여있어야합니다. 또한반드시별칭을주지않으면안됩니다. 176
177 join_type 다음중하나입니다. [INNNER] JOIN LEFT [OUTER] JOIN RIGHT [OUTER] JOIN FULL [OUTER] JOIN CROSS JOIN INNER 및 OUTER 조인형식에서는조인조건, 즉 NATURAL, ON join_condition, USING (join_column [...]) 중 1 개만을지정해야합니다. 각각의 의미는아래를참조하세요. CROSS JOIN 은이어구를작성하지않아도상관없습니다. JOIN 절은 2 개의 FROM 항목을결합합니다. 중첩된순서를결정하는데필요하다면괄호를 사용하십시오. 괄호없이, JOIN 은왼쪽에서오른쪽으로순환합니다. 어떤경우에도 JOIN 은콤마로 분리된 FROM 항목보다강한속박을갖습니다. CROSS JOIN 과 INNER JOIN 은카티션곱 1 개를생성합니다. 이것은 FROM 의맨위에 2 개의항목을조인한결과와동일합니다. 그러나조인조건 ( 만약있다면 ) 에의해제약을걸수있습니다. CROSS JOIN 은 INNER JOIN ON (TRUE) 과동일하며, 조건에의해삭제되는행은없습니다. 이조인형식은기술상의편의를위해서만사용할수있습니다. 이에따라 FROM 와 WHERE 으로실행하지않으면아무것도실행하지않습니다. LEFT OUTER JOIN 은조건에맞는카티션곱의모든행 ( 즉, 그조인조건을만족하는모든조합 ) 이외왼쪽테이블에서오른쪽테이블에조인조건에응하는행이없는행의복사본을반환합니다. 이왼쪽테이블의행을조인한결과테이블의폭을확장하기위해오른쪽테이블의열에 null 값이삽입됩니다. 행이일치하는가를결정할때는 JOIN 어구자신의조건만을고려하는것을주의하세요. 다른외부조인조건은나중에적용됩니다. 역으로, RIGHT OUTER JOIN 은모든조인행이외에왼쪽테이블의행과일치하는행이없는오른쪽행 ( 왼쪽은 null 로확장됩니다 ) 을반환합니다. 좌우테이블에입력값을바꿀수있는경우, LEFT OUTER JOIN 로변환할수있으므로 RIGHT OUTER JOIN 는기술상의편의를위해제공된것에불과합니다. FULL OUTER JOIN 은모든조인행이외에일치하지않은왼쪽테이블의행 ( 오른쪽은 null 로 확장 ), 일치하지않은오른쪽테이블의행 ( 왼쪽은 null 로확장 ) 을모두반환합니다. ON join_condition 177
178 join_condition 은조인에서어떤행이일치할지의여부, BOOLEAN 형식의값을 반환하는식 (WHERE 절과유사합니다 ) 입니다. USING (join_column [...]) USING (a, b,...) 절은 ON left_table.a = right_table.a AND left_table.b = right_table.b... 의 약어입니다. USING 은해당하는열의각두쪽모두가아니라한쪽만을조인출력에포함되는 것을의미합니다. NATURAL NATURAL 은 2 개의테이블에서같은이름을가진행을모두선택한 USING 리스트의약어입니다 WHERE 어구 WHERE 어구는일반적으로다음과같은형식이됩니다 ( 이어구는생략가능 ). WHERE condition condition 은평가결과로 BOOLEAN 형식을반환하는모든표현식입니다. 이조건에부합하지않는 행은출력에서삭제됩니다. 모든변수에실제행의값을대입하고, 식이 True 를반환하면그 부분은조건을충족시키는것으로간주됩니다 GROUP BY 구문 임의의 GROUP BY 절은보통다음과같은형식입니다. GROUP BY expression [...] GROUP BY 는그룹화된식을위해같은값을가지는선택된모든행을하나의행으로압축합니다. expression 은입력열명이나이름, 출력열의서수 (SELECT 목록항목 ), 입력열값형식의임의의식으로표현될수있습니다. 애매한경우, GROUP BY 이름은출력열이름보다는입력열이름으로해석됩니다. 집계함수를사용하면, 각그룹의모든행을대상계산되어지고, 그결과로각그룹의값이생성됩니다 ( 한편, GROUP BY 이없으면집계함수는선택된모든행을대상으로계산을실시하고, 하나의값을생성합니다 ). GROUP BY 가있으면, 집계함수를제외하고, 그룹화되지않은열을참조하는 SELECT 목록은사용할수없습니다. 그룹화되지않은열을반환하는값은여러값이될가능성이있기때문입니다 HAVING 구문 178
179 선택적인 HAVING 구문은일반적으로다음과같은형식입니다. HAVING condition condition 은 WHERE 절에지정하는것과동일합니다. HAVING 은조건을만족하지않는그룹행을제거합니다. HAVING 과 WHERE 은다음사항이크게다릅니다. WHERE 은 GROUP BY 를적용하기전에각행을필터링하는반면, HAVING 은 GROUP BY 를적용한후에생성된그룹행에대해필터링을합니다. 집계함수내에서참조되는경우를제외하고, 조건에서참조된각열은분명히그룹화된열을참조해야만합니다 SELECT 목록 SELECT 목록 (SELECT 와 FROM 사이에있는키워드 ) 는 SELECT 문의출력행을형성하는표현식을지정합니다. 이표현식을통해 FROM 절의처리후, 참조되는열을볼수있습니다. ( 일반적으로이동합니다 ). AS output_name 절을사용하면, 출력열에다른이름을지정할수있습니다. 이이름은주로표시하기위한열의라벨로사용됩니다. 또한, ORDER BY 절과 GROUP BY 절의열값을참조할때도이이름을사용할수있습니다. 그러나 WHERE 및 HAVING 절에서는사용할수없습니다. 이들은표현식을작성해야만합니다. 표현식을대신해, * 은선택된행의열을빠르게출력리스트에입력할수있도록합니다 UNION 절 UNION 절은일반적으로다음과같은형식입니다. select_statement UNION [ALL] select_statement select_statement 는 ORDER BY 나 FOR UPDATE 절이없는모든 SELECT 문장입니다 (ORDER BY 는괄호로둘러싼하위표현식을부여할수있습니다. 괄호가없는경우에는이절은우측 입력표현식이아닌, UNION 결과에적용됩니다 ). UINON 연산자는 SELECT 문을포함하는반환행의결합을계산합니다. 최소한결과집합하나가 있을때, 두결과의결합된행이설정됩니다. UINON 연산자를직접적으로나타내는두가지 SELECT 문은같은수의열을산출해야하며, 대응하는열은데이터형식이호환되어야만합니다. UNION 연산자는 SELECT 문을포함하는행을리턴하는결합집합을산출합니다. ALL 옵션이지정되지않는한, UNION 의결과는중복되는행을가지지않습니다. ALL 은 중복되는행을제거하지않습니다. 179
180 괄호로지정되지않는다면, 같은 SELECT 문장에서복수의 UNION 연산자는왼쪽에서오른쪽으로 실행됩니다. 현재, FOR UPDATE 는 UNION 결과나 UNION 의입력결과를위해지정할수없습니다 INTERSECT 구문 INTERSECT 절은일반적으로다음과같은형식입니다. select_st atement INTERSECT select_statement select_statement 는 ORDER BY 나 FOR UPDATE 절이없는모든 SELECT 문장입니다. INTERSECT 연산자는 SELECT 문장이포함된리턴행의교집합을산출합니다. 두결과집합에 나타나는경우, 두결과의교집합의행이설정됩니다. INTERSECT 의결과는중복된행을포함하지않습니다. 괄호가지정되지않는한, 같은 SELECT 문장에서복수의 INTERSECT 연산자는왼쪽에서 오른쪽으로실행됩니다. INTERSECT 는 UNION 보다더엄중하게구속합니다. 즉, A UNION B INTERSECT C 는 A UNION (B INTERSECT C) 로해석됩니다 MINUS 구문 MINUS 절은일반적으로다음과같은형식입니다. select_statement MINUS select_statement select_statement 는 ORDER BY 나 FOR UPDATE 절이없는모든 SELECT 문장입니다. MINUS 은왼쪽 SELECT 문장의결과는존재하지오른쪽 SELECT 문의결과에없는행집합을 생성합니다. MINUS 결과에중복행을포함하지않습니다. 같은 SELECT 문에서여러 MINUS 연산자를사용하는경우, 괄호를지정하지않는한왼쪽에서 오른쪽으로실행됩니다. MINUS 는 UNION 과동일한수준으로구속합니다 CONNECT BY 구문 CONNECT BY 절은계층쿼리를실행할때, 부모 - 자식관계를결정합니다. 일반적으로다음과 같은형식입니다. 180
181 CONNECT BY (PRIOR parent_expr = child_expr child_expr = PRIOR parent_ex pr) parent_expr 는부모의후보행으로실행됩니다. FROM 구문에반환되는행에서 parent_expr = child_expr 이 true 인경우, 이행은부모의자식행으로간주됩니다. 다음절은선택해서 CONNECT BY 절과함께지정될수있습니다. START WITH start_expression FROM 구문에반환되는행을 start_expression 으로실행한결과가 true 일경우, 이는계층의 루트노드가됩니다. ORDER SIBLINGS BY expression [ASC DESC] [...] 결과집합의 expression 으로계층의동기행이정돈됩니다. ( 계층쿼리에대한자세한내용은 절을참조하십시오.) ORDER BY 구문 선택할수있는 ORDER BY 절은일반적으로다음과같은형식입니다. ORDER BY expression [ASC DESC] [...] expression 은출력열 (SELECT 목록항목 ) 의이름이나서수, 또는입력열값에서형성되는임의의 수식이될수있습니다. ORDER BY 절은사용하면결과행을지정된식에따라정렬할수있습니다. 가장왼쪽의표현식에따라, 2 개의행이동등하다고판단되면, 다음표현식과비교합니다. 그결과도동등한경우, 다음과같은방식으로계속진행됩니다. 지정된모든식이동등할경우, 실행에의존하는순서에따라반환됩니다. 서수는결과열의위치 ( 왼쪽에서오른쪽으로 ) 를참조합니다. 이기능은유일한이름이없는 열의기본순서를정의할수있도록합니다. AS 절을사용하면, 결과열에이름을할당할수 있기때문에, 이는꼭필요하지는않습니다. 또한, ORDER BY 절에는 SELECT 결과목록에나타나지않는열이포함하여, 모든공식을사용할 수있습니다. 따라서다음과같은문장을사용할수있습니다. SELECT ename FROM emp ORDER BY empno; 181
182 이기능의한계는 UNION, INTERSECT 나 MINUS 구문결과를적용하는 ORDER BY 가표현식이 아닌, 출력열이름이나숫자로지정되어야만한다는것입니다. ORDER BY 표현식결과열이름을입력열이름에모두일치하는단순한이름이주어진경우, ORDER BY 는결과열이름으로취급합니다. 이는동일한상황에서 GROUP BY 의선택과 반대됩니다. 이러한불일치는 SQL 표준과호환성을유지하기때문에발생합니다. ORDER BY 구문의표현식후에, 선택적으로키워드 ASC ( 오름차순 ) 나 DESC ( 내림차순 ) 을추가하실 수있습니다. 지정돼있지않는경우, 디폴트로 ASC 를가정합니다. null 값은다른어떤값보다높은값으로정렬됩니다. 즉, 오름정렬순서에서 null 값은 마지막에정렬되며, 내림차순에서는 null 값이처음으로정렬됩니다. 문자열데이터는데이터베이스클러스터를초기화하는동안, 결정된로케일지정대조순서에 따라정렬됩니다 DISTINCT 구문 DISTINCT 가지정되면, 중복되는모든부분은결과집합으로부터삭제됩니다 ( 각그룹의 중복으로부터한행만유지됩니다 ). ALL 은반대로모든행이유지되며, 기본으로설정됩니다 FOR UPDATE 구문 FOR UPDATE 절은다음과같은형식입니다. FOR UPDATE FOR UPDATE 를사용하면, SELECT 문은검색된행이업데이트에대해잠기게됩니다. 이에따라현재트랜잭션이완료될때까지, 이줄은다른트랜잭션에의해변경되거나삭제되지않습니다. 즉, 현재의트랜잭션이종료될때까지, 이행은다른트랜잭션 UPDATE, DELETE 나 SELECT FOR UPDATE 의실행을차단합니다. 또한, 다른트랜잭션으로부터 UPDATE, DELETE, SELECT FOR UPDATE 에의해선택된행이이미잠겨있을경우, SELECT FOR UPDATE 는다른트랜잭션이종료되기를기다리며, 그다음락을실행하고, 업데이트된행을반환합니다 ( 행이삭제되면반환하지않습니다 ). FOR UPDATE 는반환된행이테이블의모든행에해당하는지명확하게확인할수없는경우에는 사용할수없습니다. 예를들면, 집합으로사용할수없습니다. 예제 dept 테이블을 emp 테이블과조인합니다. 182
183 SELECT d.deptno, d.dname, e.empno, e.ename, e.mgr, e.hiredate FROM emp e, dept d WHERE d.deptno = e.deptno; deptno dname empno ename mgr hiredate ACCOUNTING 7934 MILLER JAN :00:00 10 ACCOUNTING 7782 CLARK JUN :00:00 10 ACCOUNTING 7839 KING 17 - NOV :00:00 20 RESEARCH 7788 SCOTT APR :00:00 20 RESEARCH 7566 JONES APR :00:00 20 RESEARCH 7369 SMITH DEC :00:00 20 RESEARCH 7876 ADAMS MAY :00:00 20 RESEARCH 7902 FORD DEC :00:00 30 SALES 7521 WARD FEB :00:00 30 SALES 7844 TURNER SEP :00:00 30 SALES 7499 ALLEN FEB :00:00 30 SALES 7698 BLAKE MAY :00:00 30 SALES 7654 MARTIN SEP :00:00 30 SALES 7900 JAMES DEC :00:00 (14 rows) 전체직원의 sal 과부서번호를이용한그룹결과의열을합계를구하기위해서다음과같이 합니다. SELECT deptno, SUM (sal) AS total FROM emp GROUP BY deptno; deptno total (3 rows) 전체직원의 sal 과부서번호를이용한결과그룹열의합계를구하고, 보다총계가적은 그룹을보여줍니다. SELECT deptno, SUM (sal) AS total FROM emp GROUP BY deptno 183
184 HAVING SUM (sal) <10000; deptno total (2 rows) 다음의두가지예제는두번째열 (dname) 의내용에따른개개의결과를정렬하는동일한 방법입니다. SELECT * FROM dept ORDER BY dname; deptno dname loc ACCOUNTING NEW YORK 40 OPERATIONS BOSTON 20 RESEARCH DALLAS 30 SALES CHICAGO (4 rows) SELECT * FROM dept ORDER BY 2; deptno dname loc ACCOUNTING NEW YORK 40 OPERATIONS BOSTON 20 RESEARCH DALLAS 30 SALES CHICAGO (4 rows) SET CONSTRAINTS 이름 SET CONSTRAINTS -- 현재트랜잭션을위한제한검사모드설정 개요 SET CONSTRAINTS (ALL name [...]) (DEFERRED IMMEDIATE) 184
185 설명 SET CONSTRAINTS 는현재트랜잭션에서제한검사방법을설정합니다. IMMEDIATE 제한은각 문장의실행이끝날때마다확인합니다. DEFERRED 제한은트랜잭션이처리되기전에검사되지 않습니다. 각각의제한은 IMMEDIATE 또는 DEFE RRED 중하나의형태를가지고있습니다. 생성에따라, 제한은 DEFERRABLE INITIALLY DEFERRED, DEFERRABLE INITIALLY IMMEDIATE, NOT DEFERRABLE 3 개중하나의성격을갖게됩니다. 3 번째클래스는항상 IMMEDIATE 형태이고 SET CONSTRAINTS 커맨드의영향을받지않습니다. 처음두클래스에서는트랜잭션을지정된형태로시작하지만, 트랜잭션에서 SET CONSTRAINTS 를사용하면행동을수정할수있습니다. 제한이름목록을가진 SET CONSTRAINTS 을변경하는것은이러한제한모드입니다 ( 이들은 모두연기할수있습니다 ). 지정된이름과일치하는여러제한사항이있을경우, 모든제한 조건에영향을받습니다. SET CONSTRAINTS ALL 지연수있는모든제한형태를변경합니다. SET CONSTRAINTS 를사용하여제한형태를 DEFERRED 에서 IMMEDIATE 로변경할때, 새로운형태는소급적으로적용됩니다. 즉, 트랜잭션의종료시점에서임의의데이터변경이검사되지않았을경우, SET CONSTRAINTS 커맨드가실행되는동안대신해서검사합니다. 만약제한을위반했을경우, SET CONSTRAINTS 는실패합니다 ( 그리고제한형태는변경되지않습니다 ). 따라서 SET CONSTRAINTS 를이용하면, 트랜잭션의특정한시점에서강제로제한검사를수행할수있습니다. 현재, 외부키제한조건만이설정에따라영향을받습니다. 검사제한및유일성제약은항상 효과적으로지연되지는않습니다. 참고 이커맨드만변경하는것은현재트랜잭션내의제한동작입니다. 따라서트랜잭션블록의 외부에서이커맨드를실행해도아무런효과가없습니다 SET ROLE 이름 SET ROLE - 현재세션에서현재사용자 ID 를설정할 개요 SET ROLE { rolename NONE } 설명 185
186 이커맨드는현재 SQL 세션에서현재사용자식별자를 rolename 로설정합니다. SET ROLE 후에, SQL 커맨드에대한권한검사는임명된롤에정상적으로로그인한경우와마찬가지로 수행됩니다. 지정된 rolename 는현재세션사용자가구성원으로속한롤이어야합니다. ( 세션사용자가 슈퍼유저일경우, 어떤역할이라도선택될수있습니다.) NONE 은현재사용자의식별자를현재세션사용자의식별자로재설정합니다. 이형식은모든 사용자에의해실행될수있습니다. 참고 이커맨드를사용하여권한을추가하거나제한하는것이가능합니다. 세션사용자의역할이 INHERITS 속성을가지는경우, 자동으로 SET ROLE 에설정된모든역할의권한을가지게됩니다. 이경우, SET ROLE 은실제세션사용자에직접할당된권한세션사용자가속한역할에할당된권한중지정된목록에서사용할수있는권한을남겨두고다른사람을모두삭제합니다. 다른한편으로, 세션사용자의역할이 NOINHERITS 속성을가진경우, SET ROLE 는세션사용자에직접할당되는모든권한을모두제거하고지정된역할에서사용할수있는권한을획득합니다. 특히, 슈퍼유저가슈퍼유저가아닌사용자로 SET ROLE 을선택하면, 슈퍼유저권한을잃게됩니다. 예제 사용자 mary 를 admins 역할의사용자 ID 를설정합니다. SET ROLE admins; 사용자 mary 를원래사용자 ID 로변경합니다. SET ROLE NONE; 관련항목 ALTER ROLE, CREATE ROLE, DROP ROLE, GRANT, REVOKE SET TRANSACTION 이름 SET TRANSACTION -- 현재트랜잭션의특성을설정 186
187 개요 SET TRANSACTION tran saction_mode 여기서 transaction_mode 는다음중하나입니다. ISOLATION LEVEL (SERIALIZABLE READ COMMITTED) READ WRITE READ ONLY 설명 SET TRANSACTION 커맨드는현재트랜잭션의특성을설정합니다. 이것은다음트랜잭션에 영향을미치지않습니다. 사용가능한트랜잭션특징은트랜잭션의격리수준과트랜잭션의액세스모드 ( 읽기 / 쓰기 또는읽기전용모드 ) 입니다. 트랜잭션의격리수준은동시에실행되는다른트랜잭션이존재할경우, 트랜잭션이볼수있는 데이터를결정하는것입니다. READ COMMITTED 문장은이것이시작되기전에처리된행만을볼수있습니다. 이것이디폴트로설정되어 있습니다. SERIALIZABLE 현재트랜잭션의모든문장은트랜잭션에서첫번째쿼리나데이터변경문장이실행되기전에 처리된행만을볼수있습니다. 트랜잭션격리수준은트랜잭션의첫번째쿼리나데이터변경문장 (SELECT, INSERT, DELETE, UPDATE 나 FETCH) 가실행된이후에는변경할수없습니다. 트랜잭션접근모드는해당트랜잭션의읽기 / 쓰기또는읽기전용여부를결정합니다. 기본값은읽기 / 쓰기입니다. 읽기전용트랜잭션은다음의 SQL 커맨드를거부합니다 : INSERT, UPDATE, DELETE. 또한, CREATE, ALTER, DROP 커맨드는모든 SQL 커맨드 : COMMENT, GRANT, REVOKE, TRUNCATE 를실행할수없습니다. 그리고 EXECUTE 커맨드는위의커맨드를포함할경우, 커맨드를실행할수없습니다. 이는디스크입력을예방하지않기때문에때문에읽기전용을높은수준에서실현하는개념입니다. 187
188 TRUNCATE 이름 TRUNCATE 비어있는테이블 개요 TRUNCATE TABLE name 설명 TRUNCATE 는테이블로부터모든행이빠르게삭제됩니다. 이는조건없는 DELETE 를사용하는 것과같은효과를가지지만, 실제로테이블을검사하지않기때문에더빠릅니다. 이커맨드는 큰테이블을대상으로하는경우에가장유용합니다. 매개변수 name 빈테이블의이름 ( 선택적으로스키마권한도가능 ). 참고 테이블이다른테이블의외래키참조하는경우, TRUNCATE 를사용할수없습니다. 이런 경우에는검사유효성은테이블스캔을요구하며, 전체적인관점에서실행되지않습니다. TRUNCATE 은테이블에존재하는사용자정의 ON DELETE 트리거를일절사용하지않습니다. 예제 bigtable 테이블을비웁니다. TRUNCATE TABLE bigtable; 관련항목 DELETE UPDATE 이름 188
189 UPDATE - 테이블의행을업데이트합니다 개요 UPDATE [optimizer_hint] table [@ dblink] SET column = (e xpression DEFAULT) [...] [WHERE condition] [RETURNING return_expression [...] (INTO (record variable [...]) BULK COLLECT INTO collection [...])] 설명 UPDATE 은조건을충족시키는모든행의지정된열값을변경합니다. SET 구문에는변경되는 열만을지정해야합니다. SET 구문에서명시적으로지정되지않은열의값은변경되지않습니다. RETURNING INTO (record variable [...]) 어구는 SPL 프로그램내에지정되어야합니다. 또한 UPDATE 커맨드의결과집합은 1 행다음에반환되면안됩니다. 그밖에는예외를던집니다. 결과집합이비어있으면대상레코드내용이거나변수가 null 로설정됩니다. UPDA TE 커맨드가 SPL 프로그램에서사용되는경우에만 RETURNING BULK COLLECT IN TO collection [...] 구문을지정할수있습니다. BULK COLLECT INTO 구문을대상으로여러 collection 이지정된경우, 각 collection 은단순한스칼라필드로구성되어야합니다. 즉, collection 는레코드일수없습니다. UPDATE 커맨드의결과는아무것도포함하지않거나하나이상의행을포함할수있습니다. return_expression 는 collection 의요소로서첫번째행을시작으로결과집합의각행을위해실행됩니다. collection 에있는기존행은삭제됩니다. 결과가비어있으면 collection 은비게됩니다. 테이블을변경하려면 UPDATE 권한을가져야합니다. 또한 expression 이나 condition 에서 가져올테이블에대한 SELECT 권한도필요합니다. 매개변수 optimizer_hint 실행계획의선택을위한옵티마이저에관해주석이내장된힌트입니다. 옵티마이저힌트에대한 자세한내용은 3.4 절을참조하십시오. 189
190 table 업데이트되는테이블의이름 ( 스키마이름도가능 ). dblink 원격데이터베이스를식별하는데이터베이스연결이름입니다. 데이터베이스링크에대한 자세한내용은 CREATE DATABASE LINK 커맨드를참조하십시오. column table 에있는열이름입니다. expression 열에할당하는표현식입니다. 이식은테이블의다른열과이전값을사용할수있습니다. DEFAULT 열에기본값을설정합니다 ( 기본표현식을지정하지않으면 null 입니다 ). condition BOOLEAN 형식을반환하는식입니다. 이식이 true 를반환하는행만업데이트됩니다. return_expression 테이블로부터 1 개이상의열을포함하는식입니다. return_expression 에서테이블의열이름이 지정된경우, return_expression 실행후열에할당되는값은다음과같이결정됩니다. return_expression 에서지정한열에 UPDATE 커맨드의값을할당하면, ret urn_expression 실행 중에값이사용됩니다. return_expression 에서지정한열에 UPDATE 커맨드의값이할당되지않은경우, return_expression 실행중에대상행의현재열값을사용합니다. record return_expression 으로실행한결과가할당되는레코드입니다. return_expression 의첫번째결과가 record 에서첫번째필드에할당되고, 2 번째결과가 2 번째필드에할당됩니다. 이하동일합니다. record 의필드수는식의숫자와동일해야합니다. 또한필드는할당된식의형식에호환되어야합니다. 190
191 variable return_expression 으로실행한결과가할당되는변수입니다. 1 개이상 return_expression 과 variable 가지정되면, return_expression 의첫번째결과가첫번째 variable 에할당됩니다. 2 번째결과가 2 번째 variable 에할당됩니다. 이하동일합니다. INTO 키워드다음에지정되는변수의수는 RETURNING 키워드뒤에표현식의수와동일해야합니다. 또한변수는할당된식과형식이호환되어야합니다. collection return_expression 으로실행한결과에서만들어지는요소의집합입니다. 하나의컬렉션즉, 단일필드집합수도있고, 레코드형식의집합일수도있습니다. 또는각집단이단일필드로구성된여러집단일수도있습니다. 반환되는표현식수는모두지정된집합필드수의순서와동일해야합니다. 그리고대응하는 return_expression 과 collection 필드는형식이호환되어야만합니다. 예제 dept 테이블에서부서의 20 를위한 AUSTIN 로장소를변경합니다. UPDATE dept SET loc = 'AUSTIN'WHERE deptno = 20; emp 테이블의 job SALESMAN 를가진직원에대해, 10% 의월급을업데이트하고, 수수료를 500 을증가시킵니다. UPDATE emp SET sal = sal * 1.1, comm = comm WHERE job = 'SALESMAN'; 3.4 옵티마이저 DELETE, SELECT 및 UPDATE 커맨드가실행되면 Postgres Plus Advanced Server 데이터베이스서버는반환된마지막행집합을커맨드결과집합으로생성하는프로세스제어가돌아갑니다. 이러한결과집합을생성하는방법은쿼리플래너 (query planner), 또는쿼리옵티마이저의일입니다. 지정된커맨드에따라, 1 개이상의실행후보가존재합니다. 이를쿼리계획 (query plans) 이라고합니다. 플래너는결과집합을만들기위한가능한방법을검토합니다. 실제로커맨드를실행하는데사용되는프로그램의선택은다양한요구사항에따라달라집니다. 데이터검색을위한각종처리비용을할당 (Postgresql.conf 파일플래너코스트상수참조 ) 플래너메소드인자설정 (postgresql.conf 파일플래너메소드설정영역참조 ) ANALYZE 커맨드는테이블데이터에집계된열통계정보 (ANALYZE 커맨드및열통계정보에대한자세한내용은 Postgres Plus 설명서참조 ) 191
192 대체로다양한실행계획중에서, 쿼리플래너는실제실행에서가장작은비용을선택합니다. 그러나주어진 DELETE, SELECT 및 UPDATE 커맨드에옵티마이저힌트를사용하여전체또는일부의선택에영향을줄수있습니다. 옵티마이저힌트는 DELETE, SELECT, 그리고 UPDATE 키워드를따르는코멘트와비슷한형식으로플래너가결과집합을생성하기위해특정한접근을이용할수있을지를알려줍니다. 개요 (DELETE SELECT UPDATE) / * + (h int [comment]) [...] * / statement_body (DELETE SELECT UPDATE) - + (h int [comment]) [...] statement_body 옵티마이저힌트는위와같이 2 가지다른형식으로제공됩니다. 두가지형식에서플러스 표시 (+) 는 / * 나 -- 주석을여는기호는힌트로서사용하기위해공백이없어야합니다. 첫번째형식은힌트와옵션코멘트가여러라인일수있습니다. 2 번째형식은모든힌트와 옵션코멘트가하나의라인이어야합니다. 문장의나머지는새로운라인의시작해야만합니다. 설명 옵티마이저사용에대해다음과같은점에주의해야합니다. 데이터베이스서버는가능한항상지정된힌트를사용하려고합니다. 플래너메소드인자가특정한계획형식을사용하지못하도록설정하면, 플래너가다른가능한선택권이전혀없을경우를제외하고, 힌트에지정되어도이계획은사용되지않습니다. 플래너메소드인자의예제는 enable_indexscan, enable_seqscan, enable_hashjoin, enable_mergejoin 및 enable_nestloop 입니다. 이들은모두 Boolean 인자입니다. 힌트는주석으로포함되어있음을주의하십시요. 결과적으로, 힌트가오타이거나인자가힌트로서뷰, 테이블, 열이름이오타일경우, SQL 커맨드에존재하지않는경우는에러에대한통지가발생하지않습니다. 구문오류가없으면모든힌트는간단하게무시됩니다. SQL 커맨드에테이블이나뷰이름을위해별칭을사용하는경우, 원래이름이아닌힌트로서사용되어야합니다. 예를들어, SELECT / * + FULL (acct) * / * FROM accounts acct..., acct, 는테이블이름이아닌 accounts 의별칭으로 FULL 힌트에지정되어야합니다. 힌트가정확하게형성되었나확인하고싶거나, 플래너가이힌트를사용하고있는지여부를확인하기위해서는 EXPLAIN 커맨드를쓰십시오. Postgres Plus 의 EXPLAIN 커맨드를설명하는문서를참조하십시오. 192
193 일반적으로옵티마이저힌트는실행어플리케이션에서사용되어야하는것은아닙니다. 특히, 테이블데이터는어플리케이션주기에따라변화합니다. 좀더동적인열을확실히함으로써 ANALYZEd 가수시로이루어지고, 열의통계정보는값의변화를업데이트할것입니다. 또한플래너는주어진커맨드를실행하기위한최소한의계획비용을생성하기위해이정보를사용합니다. 옵티마이저힌트의사용은이러한프로세스의목적과겹쳐지지않으며테이블데이터가어떻게변화하는지를간주하는동일한계획입니다. 인자 hint Optimizer 힌트지시. comment 추가적인정보문자열. 어떤문자가주석에포함되는가에대해제한이있다는것을주의하십시오. 일반적으로 comment 는알파벳, 숫자, 밑줄, 달러기호, 번호기호, 공백입니다. 이들은식별자구문을준수해야합니다. 식별자에대한자세한정보는 절을참조하십시오. 형식에주석이있지않으면, 다음힌트는무시되어질것입니다. statement_body DELETE, SELECT, 혹은 UPDATE 커맨드의나머지부분 다음절에서는다양한옵티마이저힌트지정에대해자세히설명합니다 기본최적화모드 Postgres Plus Advanced Server 데이터베이스클러스터의디폴트설정은많은최적화모드에서선택될수있습니다. 이설정은옵티마이저힌트내의 DELETE, SELECT, UPDATE 커맨드뿐아니라, ALTER SESSION 커맨드를사용하여세션을변경할수있습니다. 이러한디폴트모드를제어하는설정매개변수를 OPTIMIZER_MODE 이라고합니다. 다음표는가능한값을나타냅니다. 표 3-10 기본최적화모드 ALL_ROWS CHOOSE 힌트 설명모든결과집합을검색하도록최적화합니다결과집합으로부터검색된가정행수를기본으로기본최적화를실행하지않습니다. 이것이기본값이다. 193
194 FIRST_ROWS 결과집합에서첫번째행만을검색하도록최적화합니다. FIRST_ROWS_10 결과집합에서처음 10 행을검색하도록최적화합니다. FIRST_ROWS_100 결과집합에서처음 100 행을검색하도록최적화합니다. FIRST_ROWS_100 0 결과집합에서처음 1000 행을검색하도록최적화합니다. FIRST_ROWS (n) 결과집합에서처음 n 줄을검색하도록최적화합니다. 이형식은 ALTER SESSION SET OPTIMIZER_MODE 커맨드개체로는사용되지 않습니다. SQL 커맨드의힌트형태로만사용됩니다. 이러한최적화모드는클라이언트가발행한 SQL 커맨드가결과집합에서첫번째 "n" 행만을 보고싶으며, 나머지는버린다는가정을기반으로합니다. 쿼리에할당되는리소스는다음과 같이조정됩니다. 예제 현재세션은결과집합의처음 10 행을검색하도록최적화합니다. ALTER SESSION SET OPTIMIZER_MODE = FIRST_ROWS_10; OPTIMIZER_MODE 매개변수의현재값은 SHOW 커맨드로볼수있습니다. 이커맨드는 유틸리티의존커맨드라는것을주의하십시오. PSQL 에서 SHOW 커맨드는다음과같습니다. SHOW OPTIMIZER_MODE; optimizer_mode first_r ows_10 (1 row) Oracle 과호환되는 SHOW 커맨드는다음과같은형식입니다. SHOW PARAMETER OPTIMIZER_MODE; NAME VALUE optimizer_mode first_rows_10 다음은 SELECT 커맨드에대한힌트를사용하여최적화모드를보여줍니다. 194
195 SELECT / * + FIRST_ROWS (7) * / * FROM emp; empno ename job mgr hiredate sal comm deptno SMITH CLERK DEC :00: ALLEN SALESMAN FEB :00: WARD SALESMAN FEB :00: JONES MANAGER APR :00: MARTIN SALESMAN SEP :00: BLAKE MANAGER MAY :00: CLARK MANAGER JUN :00: SCOTT ANALYST APR :00: KING PRESIDENT 17 - NOV :00: TURNER SALESMAN SEP :00: ADAMS CLERK MAY :00: JAMES CLERK DEC :00: FORD ANALYST DEC :00: MILLER CLERK JAN :00: (14 rows) 액세스방법힌트 다음힌트는결과집합을생성하기위해옵티마이저가어떻게관계에접근하는가에영향을 줍니다. 표 3-11 액세스방법힌트 힌트 설명 FULL (table) table 에대해완전한순차적인검사실시. INDEX (table [index] [...]) NO_INDEX (table [index] [...]) 관계에접근하기위하여테이블에인덱스를사용한다. 관계에접근하기위하여테이블에인덱스를사용하지않는다. 또한, Table 3-10 에서보여주는 ALL_ROWS, FIRST_ROWS, FIRST_ROWS (n) 을사용할수있습니다. 예제 195
196 간단한어플리케이션은옵티마이저힌트효과를설명하기위한충분한자료가없기때문에, 이 절에서는나머지예에서는 Postgres Plus Advanced Server dbserver \ bin 하위디렉터리에 위치한 pgbench 어플리케이션으로생성되는은행데이터베이스를사용합니다. 다음단계는 accounts, branches, tellers, history, 테이블로구성된 bank 라는이름의데이터베이스를만듭니다. - s 5 옵션은 5 개지점생성에따른 5 개의크기조정요소를지정합니다. 각각 100,000 계좌를가지고, account 테이블에총 500,000 행을결과로갖습니다. 또한, branches 테이블에 5 개의행이있습니다. 10 명의텔러는 tellers 테이블로각지점마다총 50 개의행을결과로할당받습니다. 만약 Linux 환경이라면, 다음 SET PATH 커맨드대신, 아래의 export 커맨드를사용하십시오. export PATH = / opt/postgres Plus Advanced Server/8.3/dbserver/bin : $ PATH 다음은 Windows 에서의실행예입니다. SET PATH = C : \ Postgres Plus Advanced Server \ 8.3 \ dbserver \ bin; % PATH % createdb - U Postgres Plus Advanced Server bank CREATE DATABASE pgbench - i - s 5 - U Postgres Plus Advanced Server - d bank creating tables tuples done tuples done tuples done tuples done tuples done tuples done tuples done. set primary key... vacuum... done. 클라이언트당 10 개의트랜잭션은 8 명의클라이언트를위해 80 개의트랜잭션으로처리됩니다. 이는 history 테이블에 80 행으로작성됩니다. pgbench - U Postgres Plus Advanced Server - d bank - c 8 - t
197 ... transaction type : TPC - B (sort of) scaling factor : 5 number of clients : 8 number of transactions per client : 10 number of transactions actually processed : 80/80 tps = (including connections establishing) tps = (excluding connections establishing) 테이블의정의는다음과같습니다. \ d accounts Table "public.accounts" Column Type Modifiers aid integer not null bid integer abalance integer filler character (84) Indexes : "accounts_pkey"primary KEY, btree (aid) \ d branches Table "public.branches" Column Type Modifiers bid integer not null bbalance integer filler character (88) Indexes : "branches_pkey"primary KEY, btree (bid) \ d tellers Table "public.tellers" Column Type Modifiers
198 tid integer not null bid integer tbalance integer filler character (84) Indexes : "tellers_pkey"primary KEY, btree (tid) \ d history Table "public.history" Column Type Modifiers tid integer bid integer aid integer delta integer mtime timestamp without time zone filler character (22) EXPLAIN 커맨드는쿼리플래너에서선택한프로그램을표시합니다. 다음예제에서, aid 는주 키입니다. 따라서, accounts_pkey 인덱스를이용한빠른검색을사용합니다. EXPLAIN SELECT * FROM accounts WHERE aid = 100; QUERY PLAN Index Scan using accounts_pkey on accounts (cost = rows = 1 width = 97) Index Cond : (aid = 100) (2 rows) FULL 힌트가아래와같이인덱스를사용하는것을대신해서, 완전순차스캔을강요하는경우는 다음과같습니다. EXPLAIN SELECT / * + FULL (accounts) * / * FROM accounts WHERE aid = 100; QUERY PLAN Seq Scan on accounts (cost = rows = 1 width = 97) Filter : (aid = 100) (2 rows) 198
199 NO_INDEX 힌트는또한순차스캔을아래와같이강요합니다. EXPLAIN SELECT / * + NO_INDEX (accounts accounts_pkey) * / * FROM accounts WHERE aid = 100; QUERY PLAN Seq Scan on accounts (cost = rows = 1 width = 97) Filter : (aid = 100) (2 rows) 위의예제에서보여준 EXPLAIN 커맨드를사용외에, 플래너에의해힌트가사용되는지여부에 대한세한정보는 client_min_messages 과 trace_hint 설정매개변수를다음과같이설정함으로써 얻을수있습니다. SET client_min_messages TO info; SET trace_hints TO true; NO_INDEX 힌트를가지는 SELECT 커맨드는전에기술한설정매개변수를지정할때, 발생하는 추가정보를설명하기위해반복합니다. EXPLAIN SELECT / * + NO_INDEX (accounts accounts_pkey) * / * FROM accounts WHERE aid = 100; INFO : HINTS] Index Scan of [accounts] [accounts_pkey] rejected because of NO_INDEX hint. INFO : HINTS] Bitmap Heap Scan of [accounts] [accounts_pkey] rejected because of NO_INDEX hint. QUERY PLAN Seq Scan on accounts (cost = rows = 1 width = 97) Filter : (aid = 100) (2 rows) 만약힌트가무시되면, INFO: [HINTS] 라인이표시되지않습니다. 이것은구문오류나힌트의 오타가있음을나타냅니다. 다음예제는인덱스이름에오타가있습니다. EXPLAIN SELECT / * + NO_INDEX (accounts accounts_xxx) * / * FROM accounts WHERE aid = 100; QUERY PLAN Index Scan using accounts_pkey on accounts (cost = rows = 1 width = 97) Index Cond : (aid = 100) 199
200 (2 rows) 조인관계힌트 2 개의테이블을조인하면, 조인을실행하기위해가능한 3 개의계획이있습니다. 중첩루프조인 - 오른쪽테이블은왼쪽테이블에서모든행이한번스캔됩니다. 병합정렬조인 - 각테이블을조인시작전에, 조인속성에따라정렬합니다. 두테이블은병렬로스캔되고, 일치하는행은조인행을형성하기위해결합됩니다. 해시조인 - 적당한테이블이스캔되고, 조인속성은해시테이블로조인특성을해시키로사용하여로드됩니다. 그런다음, 왼쪽테이블은스캔되고, 조인속성은우측테이블로부터일치하는열을찾기위해해시키로서사용됩니다. 다음표는플래너에영향을주기위해사용할수있는옵티마이저힌트를조인계획의한 형식으로사용하기위해열거합니다. 표 3-12 조인힌트 힌트 USE_HASH (table [...]) NO_USE_HASH (table [...]) 설명테이블조인특성에서만든해시테이블에의한해시조인을사용합니다. 테이블조인특성에서만든해시조인을사용하지않습니다. USE_MERGE (table [...]) 테이블에병합정렬조인을사용합니다. NO_USE_MERGE (table [...]) 테이블에병합정렬조인을사용하지않습니다. USE_NL (table [...]) 테이블에중첩루프조인을사용합니다. NO_USE_NL (table [...]) 테이블에중첩루프조인을사용하지않습니다. 예제 다음예제에서는조인은 branches 과 accounts 테이블에서실행됩니다. 쿼리플랜은 branches 테이블의조인특성에서해시테이블을생성하고, 해시조인이사용되는것을의미합니다. EXPLAIN SELECT b.bid, a.aid, abalance FROM branches b, accounts a WHERE b.bid = a.bid; QUERY PLAN Hash Join (cost = rows = width = 12) Hash Cond : (a.bid = b.bid) 200
201 -> Seq Scan on accounts a (cost = rows = width = 12) -> Hash (cost = rows = 5 width = 4) -> Seq Scan on branches b (cost = rows = 5 width = 4) (5 rows) USE_HASH (a) 힌트를사용하면플래너가 branches 테이블이아닌, accounts 조인속성에서해시 테이블을만들도록강요할수있습니다. USE_HASH 힌트는 accounts 테이블별칭 a 를사용하고 있다는것을명심하십시오. EXPLAIN SELECT / * + USE_HASH (a) * / b.bid, a.aid, abalance FROM branches b, accounts a WHERE b.bid = a.bid; QUERY PLAN Hash Join (cost = rows = width = 12) Hash Cond : (b.bid = a.bid) -> Seq Scan on branches b (cost = rows = 5 width = 4) -> Hash (cost = rows = width = 12) -> Seq Scan on accounts a (cost = rows = width = 12) (5 rows) 다음으로, NO_USE_HASH (ab) 힌트는플래너가해시테이블이아닌접근을사용하도록 강요합니다. 결과적으로중첩루프입니다. EXPLAIN SELECT / * + NO_USE_HASH (ab) * / b.bid, a.aid, abalance FROM branches b, accounts a WHERE b.bid = a.bid; QUERY PLAN Nested Loop (cost = rows = width = 12) Join Filter : (b.bid = a.bid) -> Seq Scan on accounts a (cost = rows = width = 12) -> Materialize (cost = rows = 5 width = 4) -> Seq Scan on branches b (cost = rows = 5 width = 4) (5 rows) 마지막으로 USE_MERGE 힌트는플래너가병렬조인을사용하도록강요합니다. EXPLAIN SELECT / * + USE_MERGE (a) * / b.bid, a.aid, abalance FROM branches b, accounts a WHERE b.bid = a.bid; QUERY PLAN 201
202 Merge Join (cost = rows = width = 12) Merge Cond : (b.bid = a.bid) -> Sort (cost = rows = 5 width = 4) Sort Key : b.bid -> Seq Scan on branches b (cost = rows = 5 width = 4) -> Sort (cost = rows = width = 12) Sort Key : a.bid -> Seq Scan on accounts a (cost = rows = width = 12) (8 rows) 이세테이블의조인예에서, 플래너는첫째, branches 와 history 테이블에서해시조인을 실행합니다. 그다음마지막으로, accounts 테이블의 accounts_pkey 인덱스를가지는결과의중첩 루프조인을실행합니다. EXPLAIN SELECT h.mtime, h.delta, b.bid, a.aid FROM history h, branches b, accounts a WHERE h.bid = b.bid AND h.aid = a.aid; QUERY PLAN Nested Loop (cost = rows = 26 width = 20) -> Hash Join (cost = rows = 26 width = 20) Hash Cond : (h.bid = b.bid) -> Seq Scan on history h (cost = rows = 1020 width = 20) -> Hash (cost = rows = 5 width = 4) -> Seq Scan on branches b (cost = rows = 5 width = 4) -> Index Scan using accounts_pkey on accounts a (cost = rows = 1 width = 4) Index Cond : (h.aid = a.aid) (8 rows) 이플랜은병합정렬조인과해시조인결합해서사용하도록변경할수있습니다. EXPLAIN SELECT / * + USE_MERGE (hb) USE_HASH (a) * / h.mtime, h.delta, b.bid, a.aid FROM history h, branches b, accounts a WHERE h.bid = b.bid AND h. aid = a.aid; QUERY PLAN Merge Join (cost = rows = 26 width = 20) Merge Cond : (h.bid = b.bid) -> Sort (cost = rows = 1020 width = 20) Sort Key : h.bid 202
203 -> Hash Join (cost = rows = 1020 width = 20) Hash Cond : (h.aid = a.aid) -> Seq Scan on history h (cost = rows = 1020 width = 20) -> Hash (cost = rows = width = 4) -> Seq Scan on accounts a (cost = rows = width = 4) -> Sort (cost = rows = 5 width = 4) Sort Key : b.bid -> Seq Scan on branches b (cost = rows = 5 width = 4) (12 rows) 글로벌힌트 여기까지, 힌트는 SQL 커맨드에참조된테이블을직접적으로참조했습니다. 뷰가 SQL 커맨드를 참조할때, 뷰에나타나는테이블에힌트를적용할수있습니다. 힌트는뷰에나타나지않고, 뷰에서참조하는 SQL 커맨드에서표현됩니다. 서식 hint (view. table) 인수 hint 표 3-11 또는표 3-12 힌트. view table 을포함하는뷰이름입니다. table 힌트가적용되는테이블. 예제 203
204 3.4.3 절의마지막예제에서, history, branches, accounts 의 3 개테이블조인으로부터 tx 라는뷰가 생성됩니다. CREATE VIEW tx AS SELECT h.mtime, h.delta, b.bid, a.aid FROM history h, branches b, accounts a WHERE h.bid = b.bid AND h.aid = a.aid; 쿼리플랜은이뷰로부터선택됨으로써실행되며, 다음과같습니다. EXPLAIN SELECT * FROM tx; QUERY PLAN Nested Loop (cost = rows = 26 width = 20) -> Hash Join (cost = rows = 26 width = 20) Hash Cond : (h.bid = b.bid) -> Seq Scan on history h (cost = rows = 1020 width = 20) -> Hash (cost = rows = 5 width = 4) -> Seq Scan on branches b (cost = rows = 5 width = 4) -> Index Scan using accounts_pkey on accounts a (cost = rows = 1 width = 4) Index Cond : (h.aid = a.aid) (8 rows) 절의마지막조인에적용되는같은힌트는아래의뷰에서도적용될수있습니다. EXPLAIN SELECT / * + USE_MERGE (tx.h tx.b) USE_HASH (tx.a) * / * FROM tx; QUERY PLAN Merge Join (cost = rows = 26 width = 20) Merge Cond : (h.bid = b.bid) -> Sort (cost = rows = 1020 width = 20) Sort Key : h.bid -> Hash Join (cost = rows = 1020 width = 20) Hash Cond : (h.aid = a.aid) -> Seq Scan on history h (cost = rows = 1020 width = 20) -> Hash (cost = rows = width = 4) -> Seq Scan on accounts a (cost = rows = width = 4) 204
205 -> Sort (cost = rows = 5 width = 4) Sort Key : b.bid -> Seq Scan on branches b (cost = rows = 5 width = 4) (12 rows) 저장된뷰내테이블에대한힌트를적용하고, 힌트는다음예제에서설명하는것처럼하위쿼리의테이블에적용될수있습니다. 간단한어플리케이션의 emp 테이블쿼리에서는 emp 테이블을별칭 b 로정의하고, emp 테이블의하위쿼리와조인하고, 직원과관리자목록을보여줍니다. SELECT a.empno, a.ename, b.empno "mgr empno"b.ename "mgr ename"from emp a, (SELECT * FROM emp) b WHERE a.mgr = b.empno; empno ename mgr empno mgr ename FORD 7566 JONES 7788 SCOTT 7566 JONES 7521 WARD 7698 BLAKE 7844 TURNER 7698 BLAKE 7654 MARTIN 7698 BLAKE 7900 JAMES 7698 BLAKE 7499 ALLEN 7698 BLAKE 7934 MILLER 7782 CLARK 7876 ADAMS 7788 SCOTT 7782 CLARK 7839 KING 7698 BLAKE 7839 KING 7566 JONES 7839 KING 7369 SMITH 7902 FORD (13 rows) 이계획은다음의쿼리플래너에의해선택됩니다. EXPLAIN SELECT a.empno, a.ename, b.empno "mgr empno"b.ename "mgr ename"from emp a, (SELECT * FROM emp) b WHERE a.mgr = b.empno; QUERY PLAN Merge Join (cost = rows = 13 width = 26) Merge Cond : (a.mgr = emp.empno) -> Sort (cost = rows = 14 width = 20) Sort Key : a.mgr -> Seq Scan on emp a (cost = rows = 14 width = 20) 205
206 -> Sort (cost = rows = 14 width = 13) Sort Key : emp.empno -> Seq Scan on emp (cost = rows = 14 width = 13) (8 rows) 힌트는하위쿼리내의 emp 테이블에테이블스캔을대신해서, emp_pk, 인덱스스캔을실행하기 위해적용될수있습니다. 쿼리플랜의차이를주의하십시오. EXPLAIN SELECT / * + INDEX (b.emp emp_pk) * / a.empno, a.ename, b.empno "mgr empno"b.ename "mgr ename"from emp a, (SELECT * FROM emp) b WHERE a. mgr = b.empno; QUERY PLAN Merge Join (cost = rows = 13 width = 26) Merge Cond : (a.mgr = emp.empno) -> Sort (cost = rows = 14 width = 20) Sort Key : a.mgr -> Seq Scan on emp a (cost = rows = 14 width = 20) -> Index Scan using emp_pk on emp (cost = rows = 14 width = 13) (6 rows) 충돌힌트 힌트를다루는마지막절에서는 2 개이상의서로충돌하는 SQL 커맨드에대한정보를 제공합니다. 이런경우, 서로충돌하는힌트는무시됩니다. 다음은서로상반되는힌트의 목록입니다. 표 3-13 충돌힌트 힌트 충돌힌트 ALL_ROWS FULL (table) INDEX (table) FIRST_ROWS - 전체포맷 INDEX (table [i ndex) FULL (table) NO_INDEX (table) INDEX (table index) FULL (table) NO_INDEX (table index) USE_HASH (table) NO_USE_HASH (table) 206
207 USE_MERGE (table) USE_NL (table) NO_USE_MERGE (table) NO_USE_NL (table) 논리연산자 일반적인논리연산자를사용할수있습니다. : AND, OR, NOT SQL 은 3 값의 Boolean 연산논리를사용하고, 이 NULL 값은 " 알수없음 " 을의미합니다. 다음 진리표를참조하십시오. Table 3-14 AND/OR 진리표 a b a AND b a OR b True True True True True False False True True Null Null True False False False False False Null False Null Null Null Null Null Table 3-15 NOT 진리표 a NOT a True False Null False True Null AND 연산자 OR 연산자를교환할수있습니다. 즉, 결과에영향을주지않고좌우피연산자를 교환할수있습니다 비교연산자 아래표의일반적인비교연산자를사용할수있습니다. Table 3-16 비교연산자 207
208 연산자 설명 < 더작은 > 더큰 <= 작거나동일한 >= 크거나동일한 = 동일 <> 동일하지않은!= 동일하지않은 비교연산자는그의미가통하면모든데이터형식에서사용할수있습니다. 모든비교연산자는 BOOLEAN 형태의값을반환하는바이너리연산자입니다. 1 < 2 < 3 와같은표현은유효하지 않습니다.( 3 과 Boolean 값을비교하는 < 연산자가없기때문입니다.) 비교연산자이외에, 특별한 BETWEEN 구문을사용할수있습니다. a BETWEEN x AND y 는동일합니다. a >= x AND a <= y 비슷하게 a NOT BETWEEN x AND y 는동일합니다. a < x OR a > y 첫번째방식을두번째방식으로내부적으로갱신하는데필요한 CPU 주기의각각의형식에는 차이가없습니다. 값이 NULL 인지아닌지확인하려면다음구문을사용합니다 expression IS NULL expression IS NOT NULL 208
209 NULL 은 "equal to" NULL 와같지않기때문에, expression = NULL 를사용하지마세요.(null 값은 알려지지않은값을보여주고, 두개의알려지지않은값과의동일여부를알수없습니다.) 이 행동은 SQL 표준을따릅니다. 어떤애플리케이션은 expression 가 null 값을평가하는경우, expression = NULL 가참을반환할 것으로예상할수있습니다. SQL 표준에따르도록애플리케이션이변경되는것을추천합니다 수학함수와연산자 수학연산자는여러 Postgres Plus Advanced Server 형태에서제공됩니다. 가능한모든연산에 대한일반적인수학조건이없는형식 ( 예를들면, 날짜 / 시간데이터형식 ) 은후행항목에서 실제동작을설명됩니다. 다음표는사용가능한수학연산자를보여줍니다. Table 3-17 수학연산자 연산자 설명 예 결과 + 가산 감산 * 곱셈 2 * 3 6 / 나눗셈 ( 정수나누기나머지생략 ) 4 / 2 2 다음표는사용가능한수학함수를보여줍니다. 이중여러함수들은다인자형태와함께여러형태로제공됩니다. 별다른주의가없으면, 함수의주어진형태는인자와같은데이터형태를반환합니다. DOUBLE PRECISION 데이터를사용하는함수는주로호스트시스템의 C 라이브러리의가장상위에서구현됩니다. 경계부분의정확성과행동은호스트시스템에의존하고바뀝니다. Table 3-18 수학함수 함수반환형태설명예결과 ABS(x) X 와동일절대값 ABS(-17.4) 17.4 CEIL(DOUBLE 입력형태와 인자보다작지 CEIL(-42.8) -42 PRECISION or 동일 않은최소 NUMBER) 정수 EXP(DOUBLE PRECISION or 입력형태와지수 EXP(1.0) 동일 209
210 NUMBER) FLOOR(DOUBLE 입력형태와 인자보다크지 FLOOR(-42.8) 43 PRECISION or 동일 않은최대 NUMBER) 정수 LN(DOUBLE PRECISION or NUMBER) 입력형태와 동일 자연로그 LN(2.0) LOG(b NUMBER, x NUMBER) NUMBER b 기반로그 LOG(2.0, 64.0) MOD(y, x) 인자형태와 동일 y/x 의나머지 MOD(9, 4) 1 NVL(x, y) 인자형태와 x 가 null 인 NVL(9, 0) 9 동일 ; 두 경우, NVL 는 인자는 y 를반환 동일한 데이터형태 POWER(a DOUBLE PRECISION, b DOUBLE PRECISION) DOUBLE PRECISION a 의 b 승 POWER(9.0, 3.0) POWER(a NUMBER, b NUMBER a 의 b 승 POWER(9.0, 3.0) NUMBER) ROUND(DOUBLE PRECISION or NUMBER) 입력형태와 동일 반올림 ROUND(42.4) 42 ROUND(v NUMBER, s NUMBER INTEGER) s 자리에서 반올림 ROUND( , 2) SIGN(DOUBLE 입력형태와 인자기호 (-1, SIGN(-8.4) -1 PRECISION or 동일 0, +1) NUMBER) SQRT(DOUBLE PRECISION or NUMBER) 입력형태와 동일 제곱근 SQRT(2.0) TRUNC(DOUBLE PRECISION or NUMBER) 입력형태와생략 TRUNC(42.8) 42 동일 210
211 TRUNC(v NUMBER, s NUMBER s 자리에서 TRUNC( , 2) INTEGER) 생략 WIDTH_BUCKET(op INTEGER 피연산자가 WIDTH_BUCKET(5.35, 3 NUMBER, b1 할당한 0.024, 10.06, 5) NUMBER, b2 b1 에서 NUMBER, count b2 까지, 버킷 INTEGER) 수 count 등등, 히스토그램의 버킷을 반환합니다. 다음표는사용가능한삼각함수를보여줍니다. 삼각함수는인자를취하고, DOUBLE PRECISION 형태의값을반환합니다. Table 3-19 삼각함수 함수 ACOS(x) ASIN(x) ATAN(x) ATAN2(x, y) COS(x) SIN(x) TAN(x) 설명코사인반비례사인반비례탄젠트반비례 x/y 의탄젠트반비례코사인사인탄젠트 문자열함수와연산자 여기에서는문자열값을검색하고변경하는함수와연산자를설명합니다. 이컨텍스트의문자열은 CHAR, VARCHAR2, CLOB 의모든형태의값을포함합니다. 별다른주의가없는경우, 아래에나열된모든함수는이런모든형태를작동시킵니다. CHAR 형태의사용시, 자동삽입되는잠재적결과에주의해야합니다. 일반적으로, 여기에설명된함수들은문자열이없는형태의데이터에도, 처음문자열표현으로변환함으로써작동합니다. Table 3-20 SQL 문자열함수와연산자 함수반환형태설명예결과 211
212 string string CLOB 문자열결합 'Enterprise' 'DB' EnterpriseDB CONCAT(string, string) CLOB 문자열결합 'a' 'b' ab INSTR(string, set, [ start INTEGER String 의문자집합의 [, occurrence ] ]) 위치를찾고, string 문자열의 start 위치에서시작하고, 첫번째, 두번째, 세번째, 등연속으로집합의발생찾기 INSTR('PETER PIPER PICKED UP A PACK OF PICKED PEPPERS','PI',1,3) 33 LOWER(string) CLOB String 을소문자로변환 LOWER('TOM') tom SUBSTR(string, start [, CLOB Start 부터시작하는 SUBSTR('This is a is count ]) 서브문자열을추출하고, test',6,2) count 문자에보낸다. Count 가지정되지않은 경우, 문자열은시작부터 끝까지생략됩니다. TRIM([ LEADING CLOB 문자만을 ( 기본값에의한 TRIM(BOTH 'x' FROM Tom TRAILING BOTH ] 공백 ) 포함하는가장긴 'xtomxx') [ characters ] FROM 문자열을문자열의 string) 시작과끝, 양쪽끝에서 제거한다. LTRIM(string [, set]) CLOB Set 에지정된모든문자를주어진 string 의왼쪽에서제거한다. set 가지정되지않은경우, 빈공백은기본값으로사용됩니다. RTRIM(string [, set]) CLOB Set 에지정된모든 문자를주어진 string 의 왼쪽에서제거한다. set 가지정되지않은경우, 빈공백은기본값으로 사용됩니다. UPPER(string) CLOB string 을대문자로 전환 LTRIM('abcdefghi', 'abc') RTRIM('abcdefghi', 'ghi') UPPER('tom') defghi abcdef TOM 212
213 추가적문자열변경함수가가능하며다음의표에있습니다. 표 3-20 에나열된 SQL 표준문자열 함수의구현을위해내부적으로사용됩니다. Table 3-21 다른문자열함수 함수반환형태설명예결과 ASCII(string) INTEGER 인자의첫번째 바이트의 ASCII 코드 ASCII('x') 120 CHR(INTEGER) CLOB 문자와함께주어진 ASCII 코드 CHR(65) A DECODE(expr, expr1a, Same as expr1a, expr2a, 등과 DECODE(3, 1,'One', Three expr1b [, expr2a, argument Expr 의첫번째일치를 2,'Two', 3,'Three', 'Not expr2b ]... [, default ]) types of 찾는다. 일치를 found') expr1b, 발견하면, expr1b, expr2b,..., expr2b 등의매개변수 default 쌍을반환한다. 일치하는것이없으면 default 을반환한다. 일치하지않고, default 까지지정되지 않으면 null 을 반환한다. INITCAP(string) CLOB 각단어의첫번째글자를대문자로, 나머지를소문자로변환한다. 여기서단어는숫자가아닌문자로구분된영문자와숫자로구성된문자행을말한다. INITCAP('hi THOMAS') Hi Thomas LPAD(string, length CLOB 문자 fill ( 기본값의 LPAD('hi', 5, 'xy') xyxhi INTEGER [, fill ]) 공간 ) 앞에추가하여 string 을 length 크기로 합니다. string 이이미 length 의길이를 초과하는경우는 213
214 생략된다 ( 오른쪽 ). NVL(expr1, expr2) 인자형식과 expr1 가 null 이아닌 NVL(null, 'abc') abc 동일 ; 두 경우에는 expr1 를, 인자는 그렇지않으면 동일한형식 expr2 를반환한다. REPLACE(string, CLOB 문자열의값을다른 REPLACE( 'GEORGE', EGOREG search_string [, 값과교체한다. 'GE', 'EG') replace_string ] replace_string 값을 지정하지않으면, search_string 값은 제거된다. RPAD(string, length CLOB 문자 fill ( 기본값의 RPAD('hi', 5, 'xy') hixyx INTEGER [, fill ]) 공간 ) 앞에추가하여 string 을 length 크기로 합니다. String 가이미 length 의길이를 초과하는경우는 생략된다. TRANSLATE(string, from, CLOB from 집합의문자와 TRANSLATE('12345', a23x5 to) 일치하는 string 의 '14', 'ax') 문자는 to 집합의 문자와교체됩니다 LIKE 연산자사용의패턴일치 Postgres Plus Advanced Server 는전통적인 SQL LIKE 연산자의사용과일치하는패턴을 제공합니다. LIKE 연산자구문은다음과같습니다. string LIKE pattern [ ESCAPE escape-character ] string NOT LIKE pattern [ ESCAPE escape-character ] 모든 pattern 은문자열집합을결정합니다. LIKE 표현은 string 이 pattern 에의해문자열집합에 포함될경우참을반환합니다. 예상하듯이, NOT LIKE 표현은 LIKE 이참을반환하거나그반대일 경우, 거짓을반환합니다. 동일한표현은 NOT 입니다. (string LIKE pattern). pattern 이백분율기호또는밑줄을포함하지않는경우, 패턴은오직문자열만을표시합니다. LIKE 의경우, 동일한연산자작동을합니다. pattern 의 underscore 밑줄 (_) 은모든문자를의미하고, 백분율기호 (%) 는 0 또는그이상의문자의문자열과의일치를의미합니다. 214
215 예 : 'abc' LIKE 'abc' true 'abc' LIKE 'a%' true 'abc' LIKE '_b_' true 'abc' LIKE 'c' false LIKE 패턴일치는항상전체문자열을대상으로합니다. 문자열내의패턴을일치시키기위해, 패턴은백분율기호로시작하고끝나야합니다. 다른문자와일치하지않고, 리터럴밑줄이나백분율기호와일치시키기위해, pattern 의각 문자는이스케이프문자에의해선행되어야합니다. ESCAPE 구문으로다른것을선택할수 있지만, 기본값이스케이프문자는백슬래시되어야합니다. 백슬래시는문자열리터럴에특별한의미가있음을주의하세요. 따라서백슬래시를포함하는패턴을계속해서작성하기위해서는, SQL 명령문에두개의백슬래시를작성해야합니다. 그러므로, 사실상리터럴백슬래시와일치하는패턴을작성하는것은명령문에네개의백슬래시를작성하는것을의미합니다. ESCAPE 와함께, 다른이스케이프문자를선택함으로써피할수있습니다. 백슬래시는더이상 LIKE 에있어서특별한것이아닙니다.( 그러나, 여전히문자열리터럴파서에특별하므로, 두개의백슬래시가여전히필요합니다.) ESCAPE '' 을작성하는것으로이스케이프문자를선택하지않는것이가능합니다. 효과적으로 이스케이프기법이작동하지않게됩니다. 패턴에서의밑줄과백분율기호의특별한의미를 취소할수없게합니다 날짜 / 시간함수와연산자 Table 3-28 는다음의서브섹션에나타난세부사항과함께, 날짜 / 시간값프로세스가가능한함수를보여줍니다. Table 3-27 는기본산술연산자 (+, -) 의행동을설명합니다. 함수의형식화를위해, 섹션을참조합니다 섹션으로부터날짜 / 시간데이터형식의배경정보에익숙해야합니다. Table 3-27 날짜 / 시간연산자 연산자예결과 + DATE ' ' OCT-01 00:00:00 + TIMESTAMP ' :30:00' OCT-01 13:30:00 - DATE ' ' SEP-01 00:00:00 - TIMESTAMP ' :30:00' SEP-01 13:30:00 - TIMESTAMP ' :00:00' - TIMESTAMP ' day 15 hours Table 3-28 의날짜 / 시간함수에서 DATE 와 TIMESTAMP 데이터형식의사용은교환가능합니다. 215
216 Table 3-28 날짜 / 시간함수 ADD_MONTHS(DATE, NUMBER) 함수반환형식설명예결과 DATE 날짜에월을더한다 ; 참조 CURRENT_DATE DATE 현재날짜 ; 참조 EXTRACT(field FROM TIMESTAMP) DOUBLE PRECISION 서브필드추출 ; 참조 LAST_DAY(DATE) DATE 주어진날짜에의해달의마지막날을반환한다. 주어진날짜가시간부분을포함하면, 결과는변경이없이이월됩니다. LOCALTIMESTAMP [ (precision) ] MONTHS_BETWEEN(DATE, DATE) NEXT_DAY(DATE, dayofweek) ROUND(DATE [, format ]) TIMESTAMP 현재날짜와시간 ( 현재트랜잭션의시작 ); 참조 NUMBER DATE DATE 두날짜사이달의수 ; 참조 주어진날짜를뒤따르는 dayofweek 와일치하는날짜 참조 format 에따라반올림된날짜 ; 참조 ADD_MONTHS('28-FEB- 97', 3.8) CURRENT_DATE EXTRACT(hour FROM TIMESTAMP ' :38:40') 31-MAY-97 00:00:00 04-JUL LAST_DAY('14-APR-98') 30-APR-98 00:00:00 LOCALTIMESTAMP MONTHS_BETWEEN('28-3 FEB-07', '30-NOV-06') NEXT_DAY('16-APR- 07','FRI') ROUND(TO_DATE('29- MAY-05'), 'MON') 04-JUL-07 15:33: APR-07 00:00:00 01-JUN-05 00:00:00 SYSDATE DATE 현재날짜와시간 SYSDATE 06-AUG-07 10:06:27 TRUNC(DATE [, format ]) DATE format 에따라생략 ; 참조 TRUNC(TO_DATE('29- MAY-05'), 'MON') 01-MAY-05 00:00: ADD_MONTHS ADD_MONTHS 함수는주어진날짜에월의지정된수를가산합니다. ( 또는두번째매개변수가 부일경우감산합니다.) 월의마지막날을제외하고, 그달의날짜결과는주어진날짜와 동일합니다. 이경우에는항상그달의결과날은월의마지막날입니다. 월매개변수의수의일부분은계산이수행되기전에생략됩니다. 주어진날짜가시간부분을포함하면, 변경되지않은결과를유지합니다. 다음은 ADD_MONTHS 함수의예입니다. SELECT ADD_MONTHS('13-JUN-07',4) FROM DUAL; 216
217 add_months OCT-07 00:00:00 (1 row) SELECT ADD_MONTHS('31-DEC-06',2) FROM DUAL; add_months FEB-07 00:00:00 (1 row) SELECT ADD_MONTHS('31-MAY-04',-3) FROM DUAL; add_months FEB-04 00:00:00 (1 row) EXTRACT EXTRACT 함수는날짜 / 시간값으로부터년이나시간과같은서브필드를추출합니다. EXTRACT 함수는 DOUBLE PRECISION 형의값을반환합니다. 다음은유효필드명입니다. YEAR 년필드 SELECT EXTRACT(YEAR FROM TIMESTAMP ' :38:40') FROM DUAL; date_part (1 row) MONTH 년내월의수 (1-12) SELECT EXTRACT(MONTH FROM TIMESTAMP ' :38:40') FROM DUAL; date_part (1 row) DAY ( 월의 ) 날짜필드 (1-31) SELECT EXTRACT(DAY FROM TIMESTAMP ' :38:40') FROM DUAL; 217
218 date_part (1 row) HOUR 시간필드 (0-23) SELECT EXTRACT(HOUR FROM TIMESTAMP ' :38:40') FROM DUAL; date_part (1 row) MINUTE 분필드 (0-59) SELECT EXTRACT(MINUTE FROM TIMESTAMP ' :38:40') FROM DUAL; date_part (1 row) SECOND 분수부분을포함한, 초필드 (0-59) SELECT EXTRACT(SECOND FROM TIMESTAMP ' :38:40') FROM DUAL; date_part (1 row) MONTHS_BETWEEN MONTHS_BETWEEN 함수는두날짜사이의달수를반환합니다. 첫번째데이터가두번째 데이터보다큰경우는정, 첫번째데이터가더두번째데이터보다적은경우는부로결과는 숫자값입니다. 결과는두날짜매개변수의날이동일하거나, 두날짜매개변수가각달의마지막날인경우 항상모든달의수입니다. 다음은 MONTHS_BETWEEN 함수의예입니다. SELECT MONTHS_BETWEEN('15-DEC-06','15-OCT-06') FROM DUAL; 218
219 months_between (1 row) SELECT MONTHS_BETWEEN('15-OCT-06','15-DEC-06') FROM DUAL; months_between (1 row) SELECT MONTHS_BETWEEN('31-JUL-00','01-JUL-00') FROM DUAL; months_between (1 row) SELECT MONTHS_BETWEEN('01-JAN-07','01-JAN-06') FROM DUAL; months_between (1 row) NEXT_DAY NEXT_DAY 함수는주어진날짜보다더큰지정된평일의첫번째발생을반환합니다. 예를들어, SAT 와같이, 최소한평일의첫세글자가지정되어야합니다. 주어진날짜는시간부분을 포함하고, 변하지않는결과를유지합니다. 다음은 NEXT_DAY 함수의예입니다. SELECT NEXT_DAY(TO_DATE('13-AUG-07','DD-MON-YY'),'SUNDAY') FROM DUAL; next_day AUG-07 00:00:00 (1 row) SELECT NEXT_DAY(TO_DATE('13-AUG-07','DD-MON-YY'),'MON') FROM DUAL; next_day AUG-07 00:00:00 (1 row) ROUND 219
220 ROUND 함수는지정된템플릿양식에따라날짜를반환합니다. 템플릿양식이생략된경우, 날짜는가장가까운날에반올림됩니다. 다음의표는 ROUND 함수의템플릿양식을보여줍니다. Table 3-29 함수의템플릿날짜양식 CC, SCC 양식 SYYY, YYYY, YEAR, SYEAR, YYY, YY, Y 설명 cc01 년 1 월 1 일을반환합니다. Cc 는마지막두숫자가 <= 50 이거나, 첫번째두숫자가 1 많은마지막두숫자가 > 50 이면, 주어진년도의처음두숫자를나타냅니다. ( 서기년 ) yyyy 년 1 월 1 일을반환합니다. Yyyy 는 6 월 30 일이전, 7 월 1 일이후, 최근년으로반올림됩니다. IYYY, IYY, IY, I ISO 년의시작을반올림합니다. 이것은월과일이 6 월 30 일이전, 또는 Q MONTH, MON, MM, RM WW IW W DDD, DD, J DAY, DY, D HH, HH12, HH24 MI 7 월 1 일이후, 반올림에의해결정됩니다. 월과일이두번째분기의 15 일이나그이전, 또는두번째분기의 16 일이거나그이후, 반올림에따라분기의첫날을반환합니다. 날이 15 일이나그이전이면, 지정된달의첫날을, 16 일이나그이후이면, 그다음달의첫날을반환합니다. 해당년도의첫날과같은, 한주의동일한최근날짜를반올림합니다. ISO 년의첫날과같은, 한주의요일과동일한최근날짜를반올림합니다. 해당월의첫날과같은, 한주의동일한최근날짜를반올림합니다. 최근날짜의시작을반올림합니다. 11:59:59 AM 또는더이른경우동일한날짜의시작을반올림합니다. 12:00:00 PM 또는더늦은경우그다음날의시작을반올림합니다. 최근일요일을반올림합니다. 최근시를반올림합니다. 최근분을반올림합니다. ROUND 함수사용법의예입니다. 다음은최근 100 년에서반올림하는예입니다. SELECT TO_CHAR(ROUND(TO_DATE('1950','YYYY'),'CC'),'DD-MON-YYYY') "Century" FROM DUAL; Century JAN-1901 (1 row) 220
221 SELECT TO_CHAR(ROUND(TO_DATE('1951','YYYY'),'CC'),'DD-MON-YYYY') "Century" FROM DUAL; Century JAN-2001 (1 row) 최근년의반올림예입니다. SELECT TO_CHAR(ROUND(TO_DATE('30-JUN-1999','DD-MON-YYYY'),'Y'),'DD-MON-YYYY') "Year" FROM DUAL; Year JAN-1999 (1 row) SELECT TO_CHAR(ROUND(TO_DATE('01-JUL-1999','DD-MON-YYYY'),'Y'),'DD-MON-YYYY') "Year" FROM DUAL; Year JAN-2000 (1 row) 다음은가장최근 ISO 년반올림의예입니다. 첫번째예는 2004 년에반올림합니다 의 ISO 년은 2003 년 12 월 29 일에시작합니다. 두번째예는 2005 년에반올림합니다. 같은년도의 1 월 3 일에 ISO 년을시작합니다. (ISO 년은신년의월요일에서일요일까지중최소 4 일을포함하는, 7 일단위의첫번째 월요일부터시작합니다. 따라서, 전년도의 12 월 ISO 년부터시작할수있습니다.) SELECT TO_CHAR(ROUND(TO_DATE('30-JUN-2004','DD-MON-YYYY'),'IYYY'),'DD-MON-YYYY') "ISO Year" FROM DUAL; ISO Year DEC-2003 (1 row) SELECT TO_CHAR(ROUND(TO_DATE('01-JUL-2004','DD-MON-YYYY'),'IYYY'),'DD-MON-YYYY') "ISO Year" FROM DUAL; ISO Year JAN-2005 (1 row) 다음은최근분기의반올림예입니다. SELECT ROUND(TO_DATE('15-FEB-07','DD-MON-YY'),'Q') "Quarter" FROM DUAL; Quarter 221
222 JAN-07 00:00:00 (1 row) SELECT ROUND(TO_DATE('16-FEB-07','DD-MON-YY'),'Q') "Quarter" FROM DUAL; Quarter APR-07 00:00:00 (1 row) 다음은최근달의반올림예입니다. SELECT ROUND(TO_DATE('15-DEC-07','DD-MON-YY'),'MONTH') "Month" FROM DUAL; Month DEC-07 00:00:00 (1 row) SELECT ROUND(TO_DATE('16-DEC-07','DD-MON-YY'),'MONTH') "Month" FROM DUAL; Month JAN-08 00:00:00 (1 row) 다음은최근 ISO 주에반올림합니다. 첫번째경우는 2007 년첫날은월요일입니다. 1 월 18 일에가까운일요일은 1 월 15 일입니다. 두번째예에서는 1 월 19 일은 1 월 22 일에가까운월요일입니다. SELECT ROUND(TO_DATE('18-JAN-07','DD-MON-YY'),'WW') "Week" FROM DUAL; Week JAN-07 00:00:00 (1 row) SELECT ROUND(TO_DATE('19-JAN-07','DD-MON-YY'),'WW') "Week" FROM DUAL; Week JAN-07 00:00:00 (1 row) 다음은최근 ISO 주에반올림합니다. ISO 주월요일부터시작됩니다. 첫번째경우는 2004 년 1 월 1 일은 2003 년 12 월 29 일에가장가까운월요일입니다. 두번째예에서는 2004 년 1 월 2 일은 2004 년 1 월 4 일에가장가까운월요일입니다, SELECT ROUND(TO_DATE('01-JAN-04','DD-MON-YY'),'IW') "ISO Week" FROM DUAL; ISO Week DEC-03 00:00:00 222
223 (1 row) SELECT ROUND(TO_DATE('02-JAN-04','DD-MON-YY'),'IW') "ISO Week" FROM DUAL; ISO Week JAN-04 00:00:00 (1 row) 다음예는월의첫번째날처럼같은날에시작하는것으로간주되는한주의가장가까운주를 반올림합니다. SELECT ROUND(TO_DATE('05-MAR-07','DD-MON-YY'),'W') "Week" FROM DUAL; Week MAR-07 00:00:00 (1 row) SELECT ROUND(TO_DATE('04-MAR-07','DD-MON-YY'),'W') "Week" FROM DUAL; Week MAR-07 00:00:00 (1 row) 다음예는최근날의반올림입니다. SELECT ROUND(TO_DATE('04-AUG-07 11:59:59 AM','DD-MON-YY HH:MI:SS AM'),'J') "Day" FROM DUAL; Day AUG-07 00:00:00 (1 row) SELECT ROUND(TO_DATE('04-AUG-07 12:00:00 PM','DD-MON-YY HH:MI:SS AM'),'J') "Day" FROM DUAL; Day AUG-07 00:00:00 (1 row) 다음예는주의최근날시작의반올림입니다. SELECT ROUND(TO_DATE('08-AUG-07','DD-MON-YY'),'DAY') "Day of Week" FROM DUAL; Day of Week AUG-07 00:00:00 (1 row) SELECT ROUND(TO_DATE('09-AUG-07','DD-MON-YY'),'DAY') "Day of Week" FROM DUAL; 223
224 Day of Week AUG-07 00:00:00 (1 row) 다음예는최근시간의반올림입니다. SELECT TO_CHAR(ROUND(TO_DATE('09-AUG-07 08:29','DD-MON-YY HH:MI'),'HH'),'DD-MON-YY HH24:MI:SS') "Hour" FROM DUAL; Hour AUG-07 08:00:00 (1 row) SELECT TO_CHAR(ROUND(TO_DATE('09-AUG-07 08:30','DD-MON-YY HH:MI'),'HH'),'DD-MON-YY HH24:MI:SS') "Hour" FROM DUAL; Hour AUG-07 09:00:00 (1 row) 다음예는최근분의반올림입니다. SELECT TO_CHAR(ROUND(TO_DATE('09-AUG-07 08:30:29','DD-MON-YY HH:MI:SS'),'MI'),'DD- MON-YY HH24:MI:SS') "Minute" FROM DUAL; Minute AUG-07 08:30:00 (1 row) SELECT TO_CHAR(ROUND(TO_DATE('09-AUG-07 08:30:30','DD-MON-YY HH:MI:SS'),'MI'),'DD- MON-YY HH24:MI:SS') "Minute" FROM DUAL; Minute AUG-07 08:31:00 (1 row) TRUNC TRUNC 함수는지정된템플릿양식을따른날짜를반환합니다. 템플릿양식이생략된경우, 날짜는최근날은생략됩니다. 다음표는 TRUNC 함수의템플릿양식을보여줍니다. Table 3-30 TRUNC 함수의템플릿날짜양식 양식 CC, SCC cc01 년 1 월 1 일을반환하고, 주어진년도의첫두숫자는 cc 입니다. SYYY, YYYY, YEAR, SYEAR, YYY, YY, Y 설명 yyyy 년 1 월 1 일을반환하고, yyyy 는주어진년입니다. 224
225 IYYY, IYY, IY, I 주어진날짜를포함하는 ISO 년의시작날짜를반환합니다. Q 주어진날짜를포함하는분기의첫날을반환합니다. MONTH, MON, MM, RM WW 지정된달의첫날을반환합니다. 그년도의첫날과같은, 한주의주어진날짜와동일하거나, 이전의가장늦은날짜를반환합니다. IW 주어진날짜를포함하는 ISO 주의시작을반환합니다. W 그달의첫날과같은, 한주의주어진날짜와동일하거나, 이전의가장늦은날짜를반환합니다. DDD, DD, J 주어진날짜의날의시작을반환합니다. DAY, DY, D 주어진날짜를포함하는한주 ( 일요일 ) 의시작을반환합니다. HH, HH12, HH24 시의시작을반환합니다. MI 분의시작을반환합니다. 다음은 TRUNC 함수사용법의예입니다. 다음예는 100 년단위로생략됩니다. SELECT TO_CHAR(TRUNC(TO_DATE('1951','YYYY'),'CC'),'DD-MON-YYYY') "Century" FROM DUAL; Century JAN-1901 (1 row) 다음예는년이생략됩니다. SELECT TO_CHAR(TRUNC(TO_DATE('01-JUL-1999','DD-MON-YYYY'),'Y'),'DD-MON-YYYY') "Year" FROM DUAL; Year JAN-1999 (1 row) 다음예는 ISO 년의시작이생략됩니다. SELECT TO_CHAR(TRUNC(TO_DATE('01-JUL-2004','DD-MON-YYYY'),'IYYY'),'DD-MON-YYYY') "ISO Year" FROM DUAL; ISO Year DEC-2003 (1 row) 다음예는분기의시작날짜가생략됩니다. SELECT TRUNC(TO_DATE('16-FEB-07','DD-MON-YY'),'Q') "Quarter" FROM DUAL; 225
226 Quarter JAN-07 00:00:00 (1 row) 다음예는월의시작이생략됩니다. SELECT TRUNC(TO_DATE('16-DEC-07','DD-MON-YY'),'MONTH') "Month" FROM DUAL; Month DEC-07 00:00:00 (1 row) 다음예는년의첫번째날에의해결정되는한주의시작을생략합니다 년의첫번째날은 월요일이고, 1 월 19 일이전월요일은 1 월 15 일입니다. SELECT TRUNC(TO_DATE('19-JAN-07','DD-MON-YY'),'WW') "Week" FROM DUAL; Week JAN-07 00:00:00 (1 row) 다음예는 ISO 주의시작을생략합니다. ISO 주는월요일로시작합니다 년 1 월 2 일은 2003 년 12 월 29 일월요일에시작한 ISO 주입니다. SELECT TRUNC(TO_DATE('02-JAN-04','DD-MON-YY'),'IW') "ISO Week" FROM DUAL; ISO Week DEC-03 00:00:00 (1 row) 다음예는, 월의첫번째날로써, 같은날시작한것으로간주되는한주의시작은생략합니다. SELECT TRUNC(TO_DATE('21-MAR-07','DD-MON-YY'),'W') "Week" FROM DUAL; Week MAR-07 00:00:00 (1 row) 다음예는날의시작을생략합니다. SELECT TRUNC(TO_DATE('04-AUG-07 12:00:00 PM','DD-MON-YY HH:MI:SS AM'),'J') "Day" FROM DUAL; Day AUG-07 00:00:00 (1 row) 226
227 다음예는한주의시작 ( 일요일 ) 을생략합니다. SELECT TRUNC(TO_DATE('09-AUG-07','DD-MON-YY'),'DAY') "Day of Week" FROM DUAL; Day of Week AUG-07 00:00:00 (1 row) 다음예는시간의시작을생략합니다. SELECT TO_CHAR(TRUNC(TO_DATE('09-AUG-07 08:30','DD-MON-YY HH:MI'),'HH'),'DD-MON-YY HH24:MI:SS') "Hour" FROM DUAL; Hour AUG-07 08:00:00 (1 row) 다음예는분을생략합니다. SELECT TO_CHAR(TRUNC(TO_DATE('09-AUG-07 08:30:30','DD-MON-YY HH:MI:SS'),'MI'),'DD- MON-YY HH24:MI:SS') "Minute" FROM DUAL; Minute AUG-07 08:30:00 (1 row) CURRENT DATE/TIME Postgres Plus Advanced Server 는현재날짜와시간과관련된값을반환하는함수의수를 제공합니다. 이러한함수는현재트랜잭션의시작시간을기준으로값을반환합니다. CURRENT_DATE LOCALTIMESTAMP LOCALTIMESTAMP(precision) SYSDATE LOCALTIMESTAMP 는정밀매개변수를선택적으로제공할수있고, 두번째필드의반올림된 여러부분적숫자의결과를초래합니다. SELECT CURRENT_DATE FROM DUAL; date AUG-07 (1 row) SELECT LOCALTIMESTAMP FROM DUAL; 227
228 timestamp AUG-07 16:11: (1 row) SELECT LOCALTIMESTAMP(2) FROM DUAL; timestamp AUG-07 16:11:44.58 (1 row) SELECT SYSDATE FROM DUAL; timestamp AUG-07 16:11:48 (1 row) 이러한함수는현재트랜잭션의시작시간을반환하기때문에, 그값들은트랜잭션동안에변화하지않습니다. 다음과같은특성을고려합니다. 현재 시간의일관성있는표현이가능한단일트랜잭션을허용하는의도를가지며, 동일트렌잭션내의다수의변경은동일타임스템프를생성합니다. 다른데이터베이스시스템은이러한값을수시로증가시킵니다 시퀀스조작함수 여기서는시퀀스객체연산을위한 Postgres Plus Advanced Server s 의함수를설명합니다. 시퀀스객체 ( 시퀀스생성자또는시퀀스라고불리는 ) 는 CREATE SEQUENCE 명령으로생성된특별한한개행테이블입니다. 시퀀스객체는보통테이블의행의유일한식별자를생성하기위해사용됩니다. 아래에나열된시퀀스함수는시퀀스객체로부터연속되는시퀀스값을획득하는멀티유저-보안방법을단순히제공합니다. sequence.nextval sequence.currval Sequence 는 CREATE SEQUENCE 명령의시퀀스에할당된식별자입니다. 다음은이러한함수의 사용법을설명합니다. NEXTVAL 시퀀스객체는그다음값을추진하고, 그값을반환합니다. 자동적으로행해집니다 : 다수세션이 NEXTVAL 을동시에생성할경우에만, 안전하게뚜렷한각시퀀스값을받을수있습니다. 228
229 CURRVAL 현재세션에서이시퀀스의가장최근에 NEXTVAL 에의해획득한값을돌려줍니다. ( 이세션에서시퀀스의 NEXTVAL 가불린적이없는경우, 에러가보고됩니다.) 세션-로컬값을반환하기때문에, 현재세션에서그래왔듯이, 다른세션이 NEXTVAL 의실행여부에대해서예상가능한답을주는것에주의하세요. 시퀀스객체는기본값매개변수와함께생성되는경우, NEXTVAL 는 1 로시작하는연속적인값을 반환합니다. 기타동작으로 CREATE SEQUENCE 명령에서특수한매개변수를사용하여얻을수 있습니다. 중요사항 : 동시트랜잭션의블록을막기위해, 같은시퀀스로부터수를검색합니다. NEXTVAL 연산은롤백하지않습니다. 즉, 한번값이나오면, 트랜잭션이나중에 NEXTVAL 을중단한다고해도, 사용된것으로간주합니다. 이것은중단된트랜잭션이할당된값의시퀀스에사용된 구멍 을남기는것을의미합니다 조건문표현식 여기에서는 Postgres Plus Advanced Server 에서사용가능한 SQL- 준수구문에대해설명합니다 CASE SQL CASE 식은다른언어에서의 if/else 명령문과유사한일반조건문표현식입니다, CASE WHEN condition THEN result [ WHEN... ] [ ELSE result ] END CASE 구는식이유효하면어디서나사용할수있습니다. condition 은 boolean 형식의결과를반환하는식입니다. 만약결과가참이라면 CASE 표현식은 result 입니다. 만일후속 WHEN 구의결과가거짓인경우, 동일한방법으로점검합니다. WHEN 의 condition 이참이면아니면, CASE 표현식은 ELSE 구의 result 입니다. ELSE 구가어떤조건과일치하지않으면, 결과는 NULL 입니다. 다음은예입니다.: SELECT * FROM test; a (3 rows) 229
230 SELECT a, CASE WHEN a=1 THEN 'one' WHEN a=2 THEN 'two' ELSE 'other' END FROM test; a case one 2 two 3 other (3 rows) 모든 result 표현식의데이터형식은하나의출력형식에바꿀수있습니다. 다음의 단순한 CASE 표현식은일반적형식의특화된변형입니다. CASE expression WHEN value THEN result [ WHEN... ] [ ELSE result ] END Expression 은, 동등한하나를찾을때까지, WHEN 구에지정된모든값을계산하고비교합니다. 동등한것이없으면, ELSE 구 ( 또는 null 값 ) 의 result 가반환됩니다. 단순한 CASE 구문을사용해위의예가작성될수있습니다. SELECT a, CASE a WHEN 1 THEN 'one' WHEN 2 THEN 'two' ELSE 'other' END FROM test; a case one 2 two 3 other (3 rows) CASE 표현식은결과를결정하기위해필요하지않은서브표현식을평가하지않습니다. 예를들어, 0 으로나누기오류를방지하기위한방법입니다. SELECT... WHERE CASE WHEN x <> 0 THEN y/x > 1.5 ELSE false END; COALESCE COALESCE 함수는 null 이아닌첫번째인자를반환합니다. Null 은인자가 null 인경우에만 반환됩니다. 230
231 COALESCE(value [, value2 ]... ) 데이터를표시에검색될때, null 값대신기본값이사용됩니다. 예를들면 : SELECT COALESCE(description, short_description, '(none)')... CASE 식처럼, COALESCE 는결과를결정하는데필요하지않은인자는평가하지않습니다. 즉, 첫 번째 null 이아닌인자의오른쪽인자는평가되지않습니다. SQL 표준함수는 to NVL 과 IFNULL 의비슷한기능을제공하고, 다른일부데이터베이스시스템에서사용됩니다 NULLIF NULLIF 함수는 value1 와 value2 가동일한경우, null 값을반환합니다. 그렇지않으면, value1 을 반환합니다. NULLIF(value1, value2) 주어진위의 COALESCE 예의역연산수행에사용됩니다. SELECT NULLIF(value1, '(none)')... value1 이 (none) 이면 null 을반환하고, 그렇지않으면 value1 을반환합니다 GREATEST and LEAST GREATEST 와 LEAST 함수는표현식의수목록으로부터가장크거나가장작은값을선택합니다. GREATEST(value [, value2 ]... ) LEAST(value [, value2 ]... ) 표현식은결과의형식이되는보통의데이터형식을변환할수있어야합니다. 목록내의 Null 값은무시됩니다. 결과는모든식이 null 로평가될경우에만 null 이됩니다. GREATEST 와 LEAST 는 SQL 표준에는없지만, 일반적인확장인것에주의하세요 집계함수 집계함수는여러입력값으로부터단일결과를계산합니다. 다음표는내장된집계함수를 보여줍니다. 231
232 Table 3-31 일반목적의집계함수 함수인자데이터형식반환형식설명 AVG(expression) INTEGER, REAL, 정수인자는 NUMBER, 모든입력값의평균 DOUBLE PRECISION, NUMBER 부동소수점인자는 DOUBLE PRECISION, ( 산술평균 ) 나머지는인자데이터 형식과동일 COUNT(*) BIGINT 입력행의수 COUNT(expression) Any BIGINT 식이 null 이아닌값을 가지는입력행의수 MAX(expression) 숫자, 문자열, 또는 인자형식과동일 모든입력값간의식의 날짜 / 시간형식 최대값 MIN(expression) 숫자, 문자열, 또는 인자형식과동일 모든입력값간의식의 날짜 / 시간형식 최소값 SUM(expression) INTEGER, REAL, SMALLINT 또는 모든입력값간의식의 DOUBLE PRECISION, INTEGER 형식의 합계 NUMBER 인자는 BIGINT, BIGINT 형식의인자는 NUMBER, 부동소수점 인자는 DOUBLE PRECISION, 나머지는 인자는데이터형식과 동일 이함수는 COUNT 함수를제외하고, 1 행을선택하지않은경우 NULL 값을반환하는것을 주의하십시오. 특히, SUM 의행은 0 이아닌, null 을반환하지않습니다. 필요한경우 null 을 0 으로대체하기위해 COALESCE 함수를사용할수있습니다. 통계분석작업에자주사용되는집계함수가다음표에나와있습니다. ( 주로일반적으로사용되는집계의목록의혼란을피하기위해분리됩니다.) 설명부분에서 N 은, 모든입력식이 null 이아닌입력행의개수를나타냅니다. 모든경우에서, 예를들면 N 이 0 인경우와같이, 계산이무의미한경우에 null 이반환됩니다. 232
233 Table 3-32 통계에대한집계함수 함수 인자형식 반환형식 설명 CORR(Y, X) DOUBLE PRECISION DOUBLE PRECISION 상관계수 COVAR_POP(Y, X) DOUBLE PRECISION DOUBLE PRECISION 모집단공분산 COVAR_SAMP(Y, X) DOUBLE PRECISION DOUBLE PRECISION 표본공분산 REGR_AVGX(Y, X) DOUBLE PRECISION DOUBLE PRECISION 독립변수의평균 (sum(x) / N) REGR_AVGY(Y, X) DOUBLE PRECISION DOUBLE PRECISION 종속변수의평균 (sum(y) / N) REGR_COUNT(Y, X) DOUBLE PRECISION DOUBLE PRECISION null 이아닌두식의입력행의수 REGR_INTERCEPT(Y, X) DOUBLE PRECISION DOUBLE PRECISION (X, Y) 의조합에의해결정된선형방정식에대한최소두곱셈 y 역수 REGR_R2(Y, X) DOUBLE PRECISION DOUBLE PRECISION 상관계수의제곱 REGR_SLOPE(Y, X) DOUBLE PRECISION DOUBLE PRECISION (X, Y) 의조합에의해결정된최소두곱셈에맞는선형방정식의기울기 REGR_SXX(Y, X) DOUBLE PRECISION DOUBLE PRECISION Sum (X 2 ) sum (X) 2 / N ( 독립변수의 제곱의합 ) REGR_SXY(Y, X) DOUBLE PRECISION DOUBLE PRECISION Sum (X*Y) sum (X) * sum (Y) / N ( 독립변수 x 종속변수의 곱의합 ) REGR_SYY(Y, X) DOUBLE PRECISION DOUBLE PRECISION Sum (Y 2 ) sum (Y) 2 / N ( 종속변수의 제곱의합 ) STDDEV(expression) INTEGER, REAL, 부동소수점형식의 STDDEV_SAMP 의 DOUBLE PRECISION, 인자는 DOUBLE 역사적명칭 NUMBER PRECISION, 그렇지 않으면 NUMBER STDDEV_POP(expression) INTEGER, REAL, 부동소수점형식의입력값의모집단 233
234 DOUBLE PRECISION, 인자는 DOUBLE 표준분산 NUMBER PRECISION, 그렇지 않으면 NUMBER STDDEV_SAMP(expression) INTEGER, REAL, 부동소수점형식의 입력값의표본 DOUBLE PRECISION, 인자는 DOUBLE 표준분산 NUMBER PRECISION, 그렇지 않으면 NUMBER VARIANCE(expression) INTEGER, REAL, 부동소수점형식의 VAR_SAMP 의역사적 DOUBLE PRECISION, 인자는 DOUBLE 명칭 NUMBER PRECISION, 그렇지 않으면 NUMBER VAR_POP(expression) INTEGER, REAL, 부동소수점형식의 입력값의 DOUBLE PRECISION, 인자는 DOUBLE 모집단분산 ( 모집단 NUMBER PRECISION, 그렇지 표준편차의제곱 ) 않으면 NUMBER VAR_SAMP(expression) INTEGER, REAL, 부동소수점형식의 입력값의표본분산 DOUBLE PRECISION, 인자는 DOUBLE ( 표본표준편차의제곱 ) NUMBER PRECISION, 그렇지 않으면 NUMBER 서브쿼리식 여기서는 SQL 기반의 Postgres Plus Advanced Server 에서사용가능한서브쿼리표현에대해 설명합니다. 이섹션에서설명하는모든식은 Boolean( 참 / 거짓 ) 결과를돌려줍니다 EXISTS EXISTS 의인자는임의의 SELECT 명령문이나서브쿼리입니다. 서브쿼리는어떤행의반환여부를 결정하기위해평가됩니다. 적어도한행을반환하면, EXISTS 의결과는 참, 서브쿼리가아무 행도돌려주지않으면, EXISTS 의결과는 거짓 입니다. EXISTS(subquery) 서브쿼리는쿼리주변으로부터의변수를참조할수있습니다. 서브쿼리의평가에서상수역할을 합니다. 234
235 서브쿼리는본래완료하는모든방법이아닌, 적어도한행이반환여부를결정하기에충분할 때까지실행됩니다. 실제로부작용이생길지여부를예상하기는어려우므로, ( 시퀀스함수호출과 같은 ) 부작용이있는하위쿼리를작성하는것은권장하지않습니다. 결과는행의내용이아니라, 어떤행을반환하는지에의존하기때문에, 일반적으로서브쿼리의출력리스트는관계없습니다. 보통의코딩전환은 EXISTS(SELECT 1 WHERE...) 형식의모든 EXISTS 테스트를작성하기위한것입니다. 그렇지만, 이러한규칙에 INTERSECT 를사용하는서브쿼리와같은예외가있습니다. 이단순한예는 deptno 에내부결합과같습니다만, 다수의 emp 행과정합하는것이있더라도, 각 dept 행의출력행을생성합니다. SELECT dname FROM dept WHERE EXISTS (SELECT 1 FROM emp WHERE emp.deptno = dept.deptno); dname ACCOUNTING RESEARCH SALES (3 rows) IN 우측편은한열을확실히반환하는, 괄호처리된서브쿼리입니다. 좌측식은서브쿼리결과의각 행에비교되고평가됩니다. 동일한서브쿼리행이발견되면, IN 의결과는 참 입니다. 동일한행이 발견되지않으면 ( 아무행도반환하지않는서브쿼리가특별한경우를포함 ), 결과는 거짓 입니다. expression IN (subquery) 좌측식이 null 을산출할경우나, 동일한우측값이없는, 적어도하나의우측행이 null 을 산출하는경우, IN 구성의결과는거짓이아니라, null 이됩니다. null 값의 Boolean 조합 SQL 의 기본규칙은동일합니다. EXISTS 와같이, 완전하게평가되는서브쿼리를가정하는것을권장하지않습니다 NOT IN 우측편은한열을확실히반환하는, 괄호처리된서브쿼리입니다. 좌측식은서브쿼리결과의각행에비교되고평가됩니다. 동일하지않은서브쿼리행이발견되면, NOT IN 의결과는 참 입니다. 동일한행이발견되면 ( 아무행도반환하지않는서브쿼리가특별한경우를포함 ), 결과는 거짓 입니다. 235
236 expression NOT IN (subquery) 좌측식이 null 을산출할경우나, 동일한우측값이없는, 적어도하나의우측행이 null 을 산출하는경우, NOT IN 구성의결과는참이아니라, null 이됩니다. null 값의 Boolean 조합 SQL 의기본규칙은동일합니다. EXISTS 와같이, 완전하게평가되는서브쿼리를가정하는것을권장하지않습니다 ANY/SOME 우측은괄호로둘러싸인서브쿼리에, 확실하게한열을반환해야합니다. 좌측식은평가되고주어진연산자를사용해, Boolean 결과를산출하는각서브쿼리의결과행과비교됩니다. 결과가참인경우, ANY 결과는 " 참 " 입니다. 참인결과가발견되지않는경우, ( 아무행도반환하지않는서브쿼리가특별한경우를포함 ) 결과는 거짓 입니다. expression operator ANY (subquery) expression operator SOME (subquery) SOME 은 ANY 와동의어입니다. IN 은 = ANY 와동일합니다. 성공하지않거나, 우측행이연산자의결과로 null 을산출하는경우, ANY 구성의결과는거짓이 아닌, null 이되는것을주의해주세요. Null 값의 Boolean 조합은 SQL 의기본규칙과동일합니다. EXISTS 처럼, 서브쿼리가완전하게평가되는것을가정하는것을권장하지않습니다 ALL 우측은괄호로둘러싸인서브쿼리에, 확실하게한열을반환해야합니다. 좌측식은평가되고주어진연산자를사용해, Boolean 결과를산출하는각서브쿼리의결과행과비교됩니다. 결과가참인경우, ALL 결과는 " 참 " 입니다. 참인결과가발견되지않는경우. ( 아무행도반환하지않는서브쿼리가특별한경우를포함 ) 결과는 거짓 입니다. 비교한것이행에실패를반환하지않고, 적어도한행에 null 을반환하는경우, 결과는 Null 입니다. expression operator ALL (subquery) NOT IN 은 <> ALL 과동일합니다. 236
237 EXISTS 처럼, 서브쿼리가완전하게평가되는것을가정하는것을권장하지않습니다. 제 4 장저장프로시저언어 이장에서는저장프로시저언어 - SPL 에대해설명합니다. SPL 은 Postgres Plus Advanced Server 에서 custom 절차, 함수, 트리거, 패키지작성을위한생산성높은프로그램언어입니다. SPL 은다음과같은특징이있습니다. SQL 언어를보완하기위한전체적인절차상의프로그래밍기능을추가합니다. 데이터베이스를위한저장프로시저, 함수, 트리거, 패키지를만드는유일한공통언어입니다. pgadmin III 와통합되어완벽한개발및테스트환경을제공합니다. 코드재사용을촉진합니다. 쉽게사용할수있습니다. 이장에서는우선 SPL 프로그램의기본요소에대해설명합니다. SPL 프로그램구조에대한개요를살펴보고, 프로시저와함수를작성하는방법에대해설명합니다. 트리거는 SPL 을사용하는동안은내용이많이다르므로, 별도로설명하겠습니다. 제 5 장트리거에대한정보를살펴보고, 제 6 장에서는패키지에대해설명합니다 이장후반영역에서는 SPL 언어에대한자세한내용을설명하고동시에어플리케이션의예를 살펴봅니다. 4.1 SPL 의기본요소 이장에서는 SPL 프로그램의기본요소에대해설명합니다 문자집합 SPL 프로그램은입력할때, 다음의문자집합을사용합니다. 대문자 A ~ Z 와소문자 a 부터 z 숫자 0 ~ 9 기호 ( ) + - * / < > =! ~ ^ ; :. %, " # $ & _ ( )? [ ] 공백, 문자탭, 스페이스, CR (carriage returns) 식별자, 표현식, 문장, 제어구조등은이러한문자들을사용해입력되는 SPL 언어를구성합니다. 237
238 참고 : SPL 프로그램에서처리된데이터는데이터베이스인코딩에서지원되는문자집합에의해 결정됩니다 대소문자구분 SPL 프로그램에서사용되는키워드와사용자정의식별자는대소문자를구분하지않습니다. 예를들어, DBMS_OUTPUT.PUT_LINE ( 'Hello World') ; 문은 dbms_output.put_line ( 'Hello World'); 또는 Dbms_O utput.put_line ( 'Hello World'); 나 DBMS_output.Put_line ( 'Hello World'); 와동일한것으로간주됩니다. 하지만문자와문자상수는 Postgres Plus Advanced Server Advanced Server 데이터베이스에서 가져온자료와외부소스로부터입력된데이터와같이대소문자를구별해야합니다. DBMS_OUTPUT.PUT_LINE ( 'Hello World!') ; 문장은다음과같이출력됩니다. Hello World! 또한 DBMS_OUTPUT.PUT_LINE ( 'HE LLO WORLD!'); 문장은다음과같이출력됩니다. HELLO WORLD! 식별자 Identifiers 는변수, 커서, 프로그램인자등 SPL 프로그램의다양한요소를식별하는데사용되는 사용자정의이름입니다. 식별자구문규칙은 SQL 언어의식별자와동일합니다. SQL 언어의식별자에관해서는 절을참조하십시오. 식별자는 SPL 키워드나 SQL 언어키워드와같아서는안됩니다. 다음은유효한식별자의예입니다. x last name a_ $ _Sign Many $$$$$$$$ signs THIS_IS_AN_EXTREMELY_LONG_NAME A 수식어 (Qualifiers) 수식어는자격있는오브젝트항목의소유자나내용을기술하는이름입니다. 자격있는오브젝트는 자격있는이름과뒤이어공백이없는점, 공백없는오브젝트이름으로지정됩니다. 이구문은 점문법 (dot notation ) 으로불립니다. 238
239 다음은수식된오브젝트의구문을나타냅니다. 수식어. 수식어.]... 객체 수식어는오브젝트의소유자이름이며오브젝트는수식어에속하는항목의이름입니다. 이전 수식어가다음수식어와오브젝트로구별되는항목을가지는연쇄되는수식어를가질수 있습니다. 대부분의식별자는수식될수있습니다. 따라서식별자가무엇을나타내고내용의용도는 무엇인가에따라수식됩니다. 수식어예제는다음과같습니다. 속해있는스키마에의해수식된프로시저및함수이름-예 schema_name. procedure_name (...) 속해있는스키마에의해수식된트리거이름 예 schema_name. trigger_name 속해있는테이블에의해수식된열이름 예 emp.empno 속해있는스키마에의해수식된테이블이름 예 public.emp 테이블과스키마에의해수식된열이름 예 public.emp.empn o 일반적인규칙으로, SPL 문장구문으로이름을사용하면수식된이름으로간주됩니다. 일반적으로수식된이름은그이름의관련성이모호한경우에만사용합니다. 예를들어, 동일한이름을가진 2 개의프로시저가 2 개의다른스키마에속해있으며, 하나의 프로그램에서호출될경우나같은프로그램내에서테이블열과 SPL 변수가같은이름으로 사용되는경우입니다. 가능하다면, 수식된이름을사용하지않도록권합니다. 이장에서는다음과같은규정이이름의 중복을피하기위해사용되고있습니다. SPL 프로그램의선언부분에지정된모든변수는 v_ 로시작됩니다. 예 v_empno 프로시저나함수정의에선언된모든형식인자는 P_ 로시작됩니다. 예 P_empno 열이름과테이블이름은특별한접두사를가지지않습니다. 예 column empno in table emp 상수 상수또는문자열은고정값이고, SPL 프로그램에서사용되는다양한형식의표현합니다. - 예 숫자, 문자열, 날짜등. 상수는다음과같은형식으로분류됩니다. 숫자 ( 정수와실수 ) 숫자상수에관한더자세한정보는 절참조 239
240 문자와문자 - 문자와문자열상수에관한더자세한정보는 절참조 날짜 / 시간 - 날짜 / 시간데이터형식과상수에관한더자세한정보는 절을참조 4.2 SPL 프로그램 SPL 은절차상블록구조의언어입니다. SPL 에서생성되는프로그램은프로시저, 함수, 트리거, 패키지의 4 가지유형이있습니다. 프로시저와함수에대해서는이장의뒷부분에서더자세히설명합니다. 트리거는 5 장에서, 패키지에관해서는제 6 장에서설명합니다 SPL 블록구조 프로그램이프로시저, 함수나트리거인것과관계없이 SPL 프로그램은동일한블록구조를가지고있습니다. 블록은 3 개의영역으로구성됩니다. 옵션선언영역, 필수실행영역, 그리고옵션예외영역입니다. 적어도, 1 개의블록은 BEGIN 과 END 키워드내에하나, 혹은하나이상의 SPL 문장으로구성된 1 개의실행영역을가집니다. 실행영역과예외영역이내의문장을사용하는변수, 커서, 타입을정의하는옵션의선언영역이 존재합니다. 선언은실행영역 BEGIN 키워드이전에작성합니다. 블록이사용되는문맥에따라 선언영역은키워드 DECLARE 로시작합니다. 마지막으로, BEGIN - END 블록안에옵션예외영역이있습니다. 예외영역은키워드 EXCEPTION 으로시작하고, 해당블록의마지막까지계속됩니다. 블록에서문장에의해예외가던져지면, 프로그램제어는예외영역으로이동합니다. 예외영역의내용과예외에따라서처리되거나되지않을수있습니다. 아래는일반적인블록의구조를나타냅니다. [[DECLARE] declarations ] BEGIN stateme nts [EXCEPTION WHEN exception_condition THEN statements [...] END; Declarations 는블록에서하나또는그이상의변수, 커서, 타입을선언합니다. 각각의선언문은 세미콜론으로종료되어야합니다. 키워드 DECLARE 사용은블록이나온정황에따라달라집니다. 240
241 statements 는하나또는그이상의 SPL 문장입니다. 각문장은세미콜론으로종료됩니다. END 키워드가표시된블록의끝도세미콜론으로종료되어야합니다. 예외영역이존재한다면, EXCEPTION 키워드로시작됩니다. exception_condition 은하나또는그이상의예외유형을테스트하는조건을설명합니다만약발생한예외가 exception_condition 중하나의조건을충족하면 WHEN exception_conditio n 항목을따르는문장이실행됩니다. 구문을동반하는하나또는그이상의 WHEN exception_condition 항목이존재합니다. 다음은가장간단한 NULL 문장을실행영역으로구성된블록의예입니다. BEGIN NULL; END; 다음블록은선언및실행영역을가진블록입니다. DECLARE v_numerator NUMBER (2); v_denominator NUMBER (2); v_result NUMBER (5,2); BEGIN v_numerator : = 75; v_denominator : = 14; v_result : = v_numerator / v_denominator; DBMS_OUTPUT.PUT_LINE (v_numerator 'divided by' v_denominator 'is' v_result); END; 이경우, 3 개의숫자변수가 NUMBER 로선언됩니다. 실행영역에서는 2 개의변수에값을 할당하고, 하나의변수는다른변수로나눠집니다. 3 번째변수에그결과를저장하고결과를 표시합니다. 이블록이실행되면결과는다음과같습니다. 75 divided by 14 is 5.36 다음블록은 3 가지영역으로구성됩니다. - 선언, 실행, 예외영역 DECLARE v_numerator NUMBER (2); v_denominator NUMBER (2); v_result NUMBER (5,2); BEGIN v_numerator : = 75; v_denominator : = 0; v_result : = v_numerator / v_denominator; DBMS_OUTPUT.PUT_LINE (v_numerator 'divided by' v_denominator 'is' v_result); EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE ( 'An exception occurred'); END; 241
242 다음출력은 0 으로나눴을때발생되는예외영역문장의실행결과를보여줍니다. An exception occurred 익명블록 이전절에서블록의기본구조를설명했습니다. 블록은간단하게 Postgres Plus Advanced Server 에서실행될수있습니다. 이런블록을익명블록 (anonymous block) 이라고합니다. 익명블록은이름이없으며, 데이터베이스에저장되지않습니다. 블록은한번실행되고애플리케이션의버퍼로부터삭제됩니다. 블록의코드가다시애플리케이션에나타날때까지반복할수없습니다. 익명블록은테스트와같은즉시실행하거나한번실행하는프로그램에유용합니다. 하지만보통같은블록코드를여러번실행할수있습니다. 코드를여러번입력하지않고반복블록을실행하기위해서는, 익명블록을프로시저와함수로전환합니다. 다음에는데이터베이스에저장할수있으며, 다른프로시저나함수또는, 어플리케이션에서반복적으로실행가능한프로시저및함수를작성하는방법을설명합니다 프로시저개요 프로시저는독립적인 SPL 프로그램문장으로서호출가능한 SPL 프로그램입니다. 프로시저가 호출되면, 프로시저는호출한곳으로부터입력인자형식의값을선택적으로받을수있습니다. 그리고출력인자형식의값을선택적으로리턴할수있습니다 프로시저작성 CREATE PROCEDURE 커맨드는데이터베이스에저장된프로시저를정의하고이름을지정합니다. CREATE [OR REPLACE] PROCEDURE name [(parameters) [AUTHID (DEFINER CURRENT_USER)] (IS AS) [ declarations ] BEGIN statements END [ name ]; name 은프로시저식별자입니다. 만약 [OR REPLACE ] 이지정되어있고, 프로시저와같은이름이이미스키마에있다면, 새로운프로시저는기존프로시저를대체합니다. 만약 [OR REPLACE] 이지정되지않는경우, 프로시저와같은이름이이미동일한스키마에존재하여도기존프로시저를새로운프로시저로대체하지않습니다. parameters 인자목록입니다. 만약 AUTHID 항목이 242
243 생략되었거나 DEFINER 가기술되었다면, 프로시저소유자의검색경로와권한은데이터베이스오브젝트에대한액세스권한과권한이없는데이터베이스오브젝트참조를결정하는데이용됩니다. 만약 CURRENT_USER 가기술되어있으면, 프로시저를실행하는현재유저의권리와검색경로는데이터베이스오브젝트에액세스할수있는권한과자격이없는오브젝트참조를결정하도록사용됩니다. declarations 변수, 커서, 타입을정의합니다. statements 는 SPL 프로그램문장입니다. BEGIN - END 블록은 EXCEPTION 영역을포함할수있습니다. 다음의간단한프로시저는인자를필요로하지않습니다. CREATE OR REPLACE PROCEDURE simple_procedure IS BEGIN DBMS_OUTPUT.PUT_LINE ( 'That' 's all folks!'); END simple_procedure; Postgres Plus Advanced Server 에프로시저코드를입력하여프로시저를데이터베이스에 저장합니다. 프로시저생성에관한정보는 CREATE PROCEDURE 커맨드를참조하십시오 프로시저호출 프로시저는다른 SPL 프로그램으로부터인자나세미콜론다음의프로시저이름을간단히 기술하여호출될수있습니다. name [(parameters); name 은프로시저의식별자입니다. para meters 는실제인자목록입니다. 참고 : 건네진실제인자가없을경우, 프로시저는열고닫는괄호없이호출되어야합니다. 다음은익명블록에서의프로시저호출입니다. BEGIN simple_procedure; END; That 's all folks! 참고 : 애플리케이션은프로시저호출에각각특유의방법이있습니다. Java 애플리케이션에서 애플리케이션프로그래밍인터페이스, JDBC, 가사용됩니다. 243
244 프로시저삭제 프로시저는 DROP P ROCEDURE 커맨드를사용해서데이터베이스에서삭제할수있습니다. DROP PROCEDURE name; Name 은삭제프로시저이름입니다. 이전에작성된프로시저는이예제에서삭제됩니다. DROP PROCEDURE simple_procedure; 더자세한내용은 DROP PROCEDURE 커맨드를참조하십시오 기능개요 함수는식으로호출되는 SPL 프로그램입니다. 호출하면함수가있는식을대신해서값이리턴됩니다. 함수는입력인자형식으로호출하는프로그램으로부터값을선택적으로받습니다. 또한, 함수가자체값을반환한다는사실은다른값을출력인자형태로호출한측에게반환한다는것을일컫습니다. 하지만함수에서출력인자의이용은추천되는프로그래밍방법이아닙니다 함수작성 CREATE FUNCTION 커맨드는데이터베이스에저장되는함수를정의하고이름을지정합니다. CREATE [OR REPLACE] FUNCTION name [(parameters) RETURN data_type [AUTHID (DEFINER CURRENT_USER)] (IS AS) [ declarations ] BEGIN statements END [ name ]; Name 은함수의식별자입니다. 만약 [ OR REPLACE ] 이지정되어있고, 스키마에이미같은이름의함수가존재하면, 기존함수를새로운함수로교체합니다. 만약 [ OR REPLACE ] 이지정되지않은경우, 같은스키마에존재하는동일한이름의함수를새로운함수로대체하지않습니다. Parameters 은공식적인인자목록입니다. data_type 은함수로반환한값의데이터형식입니다. 만약 AUTHID 항목이없거나 DEFINER 이지정되어있으면, 함수소유자의검색경로와권한은데이터베이스오브젝트에대한액세스권한과권한이없는데이터베이스오브젝트참조를결정하도록각각사용됩니다. 만약 CURRENT_USER 이지정되어있으면, 함수를실행하는 244
245 현재사용자의권한과검색경로가데이터베이스오브젝트에대한액세스권한과권한이없는데이터베이스오브젝트참조를결정하는데각각사용됩니다. Declarations 는변수, 커서, 타입정의입니다. statements 는 SPL 프로그램문장입니다. BEGIN - END 블록에는 EXCEPTION 영역이포함되어있습니다. 다음은인자를가지지않는간단한함수의예입니다. CREATE OR REPLACE FUNCTION simple_function RETURN VARCHAR2 IS BEGIN RETURN 'That' 's All Folks!'; END simple_function; 다음은 2 개의입력인자를갖는다른함수입니다. 인자에대해서는다음절에서자세히 설명합니다. CREATE OR REPLACE FUNCTION emp_comp ( p_sal NUMBER, p_comm NUMBER ) RETURN NUMBER IS BEGIN RETURN (p_sal + NVL (p_comm, 0)) * 24; END emp_comp; 더자세한내용은 CREATE FUNCTION 커맨드를참조하십시오, 함수호출 함수는 SPL 문장어디서나작성할수있습니다. 함수는만약괄호로둘러싼인자가있다면, 뒤에 이름을기술함으로써간단히호출됩니다. name [(parameters) name 은함수이름입니다. Parameters 는실제인자목록입니다. 참고 : 만약건네진인자가없을경우, 함수는빈인자목록에서호출되거나전체적으로열고 닫는괄호가생략될수있습니다. 다음은다른 SPL 프로그램에서함수가호출되는방법을보여주고있습니다. BEGIN DBMS_OUTPUT.PUT_LINE (simple_function); END; That 's All Folks! 245
246 다음함수는일반적으로 SQL 구문안에사용됩니다. SELECT empno "EMPNO"ename "ENAME", sal "SAL"comm "COMM" emp_comp (sal, comm) "YEARLY COMPENSATION"FROM emp; EMPNO ENAME SAL COMM YEARLY COMPENSATION SMITH ALLEN WARD JONES MARTIN BLAKE CLARK SCOTT KING TURNER ADAMS JAMES FORD MILLER (14 rows) 함수삭제 DROP FUNCTION 커맨드는함수를데이터베이스로부터삭제할수있습니다. DROP FUNCTION name; name 은삭제하는함수이름입니다. 이예제에서는전에생성된함수를삭제합니다, DROP FUNCTION simple_function; 더자세한내용은 DROP FUNCTION 커맨드를참조하십시오 프로시저와함수인자 프로시저와함수사용에서중요한부분은호출프로그램에서프로시저나함수에데이터를 전달하고, 프로시저나함수로부터데이터를받는기능입니다. 이것은 parameters 를이용하여 이루어집니다. 인자는프로시저나함수정의에선언된이름을따르는괄호안에표시됩니다. 프로시저나함수에선언된인자는 formal parameters ( 형식인자 ) 라고합니다. 프로시저와함수가호출되면, 호출프로그램은호출된프로그램이이용한실제데이터와처리결과를받는변수를전달합니다. 프로시저와함수를호출됐을때, 호출한프로그램에서제공되는데이터와변수는 actual parameters ( 실제인자 ) 로서참조되어집니다. 246
247 다음은형식인자의일반형식을정의한것입니다. (name [ IN OUT IN OUT ] data_type) Name 은형식인자에지정된식별자입니다. IN 은프로시저와함수가받는입력데이터를위한인자를정의합니다. IN 인자는기본값으로초기화됩니다. OUT 은프로시저와함수의반환데이터를위한인자를정의합니다. IN, OUT 이지정되어있으면, 인자는입력및출력에이용됩니다. 만일 IN, OUT, IN OUT 전체가생략되면, 인자는디폴트로 IN 이정의된것처럼행동합니다. 인자가 IN, OUT 또는 IN OUT 중하나이면인자 mode 로서참조됩니다. data_type 은인자데이터형식을정의합니다. 다음은인자를가진프로시저의예입니다. CREATE OR REPLACE PROCEDURE emp_query ( p_deptno IN NUMBER, p_empno IN OUT NUMBER, p_ename IN OUT VARCHAR2, p_job OUT VARCHAR2, p_hiredate OUT DATE, p_sal OUT NUMBER ) IS BEGIN SELECT empno, ename, job, hiredate, sal INTO p_empno, p_ename, p_job, p_hiredate, p_sal FROM emp WHERE deptno = p_deptno AND (empno = p_empno OR ename = UPPER (p_ename)); END; 이예에서는 p_deptno 은 IN 형식인자이고, p_empno 과 p_ename 은 IN OUT 형식인자, p_job, p_hiredate 와 p_sal 는 OUT 형식인자입니다. 참고 : 이전의예에서는, VARCHAR2 인자에최대길이가지정되지않았습니다. 그리고 NUMBER 인자는정밀도와스케일이지정되지않았습니다. 인자선언에서길이, 정밀도, 스케일및기타제약조건을지정하는것은오류를일으켰습니다. 이러한제한은프로시저와함수가호출될때, 실제인자에서자동으로상속됩니다. emp_query 프로시저는실제인자와조화하여다른프로그램에서호출될수있습니다. 다음은 emp_query 를호출하는다른 SPL 프로그램의예입니다. DECLARE v_deptno NUMBER (2); v_empno NUMBER (4); v_ename VARCHAR2 (10); v_job VARCHAR2 (9); 247
248 v_hiredate DATE; v_sal NUMBER; BEGIN v_deptno : = 30; v_empno : = 7900; v_ename : = ''; emp_query (v_deptno, v_empno, v_ename, v_job, v_hiredate, v_sal); DBMS_OUTPUT.PUT_LINE ( 'Department :' v_deptno); DBMS_OUTPUT.PUT_LINE ( 'Employee No :' v_empno); DBMS_OUTPUT.PUT_LINE ( 'Name :' v_ename); DBMS_OUTPUT.PUT_LINE ( 'Job :' v_job); DBMS_OUTPUT.PUT_LINE ( 'Hire Date :' v_hiredate); DBMS_OUTPUT.PUT_LINE ( 'Salary :' v_sal); END; 이경우에, v_deptno, v_empno, v_ename, v_job, v_hiredate 및 v_sal 는실제인자입니다. 위의예에서출력은다음과같습니다. Department : 30 Employee No : 7900 Name : JAMES Job : CLERK Hire Date : 03 - DEC - 81 Salary : 인자형태 전에언급했듯이, 인자는 IN, OUT, IN OUT 3 가지모드중 1 개를가집니다. 다음의형식인자특성은그형태에따라달라집니다. 프로시저또는함수를호출할때의초기값 호출된프로시저와함수가형식인자를변경할수있는가 어떻게실제인자가호출프로그램에서호출대상프로그램에인도되는가 호출대상프로그램에서처리할수없는예외가발생했을때, 형식인자값에무슨일이일어나는가다음표는형태에따른인자의행동을요약합니다. 표 4-1 인자형태모드속성 IN IN OUT OUT 초기화되는형식인자포맷 : 실제인자값실제인자값실제인자값 형식인자를호출한프로그램으로 변경할수있는가? 아니오예예 실제인자내용 : ( 일반적으로호출한 호출이전의 형식인자의 형식인자의 프로그램종료후 ) 원래실제인자 최종값 최종값 값 248
249 실제인자내용 : ( 호출된프로그램에서 호출이전의 형식인자의 호출이전의 예외처리후 ) 원래실제인자 최종값 원래실제인자 값 값 실제인자내용 : ( 호출된프로그램에서 호출이전의 호출이전의 호출이전의 예외가처리되지않은후 ) 원래실제인자 원래실제인자 원래실제인자 값 값 값 테이블에표시된것처럼, IN 형식인자는기본값으로초기화되지않는한, 호출되는실제인자로초기화됩니다. IN 인자는호출한프로그램에서참조할수있지만, 호출된프로그램은 IN 인자에새로운값을할당하지는않을것입니다. 호출프로그램으로제어가돌아가면, 실제인자는항상호출하기전에지정된값을유지하고있습니다. OUT 형식인자는호출할때실제인자로초기화됩니다. 호출된프로그램은그값을참조하여형식인자에새값을할당합니다. 만약호출되는프로그램이예외없이완료되면, 실제인자는형식인자에마지막으로설정된값입니다. 만약처리되는예제가발생하면, 실제인자값은형식인자의마지막값이됩니다. 처리할수없는예제가발생한다면, 실제인자의값은호출전의상태로남아있습니다. IN 인자처럼, IN OUT 형식인자는호출될때실제인자로초기화됩니다. OUT 인자와같이, IN OUT 형식인자는호출된프로그램에의해변경가능하며, 만약호출된프로그램이예외없이종료됐다면, 형식인자의최근값은호출프로그램의실제인자로전달됩니다. 처리되는예제가발생되면, 실제인자의값은형식인자에할당된마지막값입니다. 처리되지않는예제가발생한경우, 실제인자에는호출이전의값이그대로남아있습니다 프로그램의보안 사용자가 SPL 프로그램을실행하거나사용자에게 SPL 프로그램을실행할수있도록한 데이터베이스오브젝트액세스에대한보안은다음과같이제어됩니다. 프로그램을실행시키는권한 프로그램이접근하려는데이터베이스오브넥트 ( 다른 SPL 프로그램포함 ) 에부여된권한 프로그램이소유자의권한으로정의되거나호출권한으로정의되는가 다음절에서는이러한사실을설명합니다 EXECUTE 권한 SPL 프로그램 ( 함수, 프로시저또는패키지 ) 은다음중어느하나가 true 일경우에만실행을 시작할수있습니다. 249
250 현재사용자가관리자이다. 또는 현재사용자가에게해당 SPL 프로그램 EXECUTE 권한이부여되었다, 또는 현재사용자가 EXECUTE 권한을가진그룹의일원으로 EXECUTE 권한을상속받았다, 또는 EXECUTE 권한이 PUBLIC 그룹에게부여되었다. Postgres Plus Advanced Server 는 SPL 프로그램이생성되면자동적으로 EXECUTE 사용권한이 PUBLIC 그룹에할당됩니다. 따라서모든사용자가즉시프로그램을실행할수있습니다. 기본권한은 REVOKE EXECUTE 커맨드를사용하여해제할수있습니다. 자세한내용은 REVOKE 커맨드를참조하십시오. 예를들면다음과같습니다. REVOKE EXECUTE ON PROCEDURE list_emp FROM PUBLIC; 프로그램에서확실한 EXECUTE 권한은개별사용자또는그룹에부여할수있습니다. GRANT EXECUTE ON PROCEDURE list_emp TO john; 지금, 사용자 john 은 list_emp 프로그램을실행할수있으나, 다른사용자는이영역의처음조건 목록에만족하지않기때문에프로그램을실행할수없습니다. 한번프로그램이실행되면, 다음보안처리는프로그램이다음과같은데이터베이스오브젝트에 대한작업을수행할수있는권한이있는지를확인하는것입니다. 테이블이나뷰를데이터읽기및갱신 테이블, 뷰, 인덱스, 시퀀스와같은데이터베이스오브젝트의생성, 갱신, 삭제 시퀀스로부터현재값과다음값을취득 다른프로그램 ( 함수, 프로시저및패키지 ) 를호출. 각각의활동은데이터베이스오브젝트의권한으로사용자를허용하거나허용하지않음으로써보호될수있습니다. 참고 : 데이터베이스는동일한형식으로이름이같은오브젝트를하나이상가질수있는것에 유의하십시오. 그러나데이터베이스에서이오브젝트는다른스키마에속합니다. 이런경우, SPL 프로그램에의해참조되는오브젝트는무엇일까요? 이것이다음절의주제입니다 데이터베이스오브젝트이름결정 SPL 프로그램에서데이터베이스오브젝트는자격있는이름이나자격이없는이름에의해서 참조될수있습니다. 자격있는이름은 schema. name 형식으로 schema 는 name 식별자를가진 데이터베이스오브젝트스키마의이름입니다. 자격이없는이름은 "schema." 부분을가지지 250
251 않습니다. 자격있는이름으로참조가이루어지면, 지정된스키마가존재하는지아닌지를 가리키는데이터베이스오브젝트에대해명확해집니다. 그러나자격없는이름의오브젝트위치를검색하는것은최근사용자의검색경로를필요로합니다. 사용자가세션의현재사용자가되면, 디폴트검색경로는항상관련된사용자에게할당됩니다. 검색경로는스키마목록을가지고있으며, 이는자격없는데이터베이스오브젝트에대한참조위치를왼쪽에서오른쪽으로검색한결과목록입니다. 만약검색경로에서어떠한스키마도발견되지않으면, 해당오브젝트가존재하지않는것으로판단됩니다. 기본검색경로는 PSQL 의 SHOW search_path 커맨드를사용하여나타냅니다. SHOW search_path; search_path $ user, public, sys, dbo (1 row) 위의검색경로에서 $ user, 위의현재세션사용자가 enterprisedb 인경우, 현재사용자를참조하는일반적인플레이스폴더입니다. 자격이없는데이터베이스오브젝트는다음스키마에서차례로검색됩니다. 순서는 enterprisedb 다음에 public 다음에 sys 마지막으로 dbo 입니다. 검색경로에자격없는이름이발견되면, 현재사용자가특정한오브젝트에서요청을수행할수 있는적절한권한이있는지결정됩니다. 참고 : 검색경로의개념은 Oracle 과호환되지않습니다. 자격없는이름을참조하면, Oracle 은단순히현재사용자의스키마데이터베이스오브젝트이름을검색하면됩니다. Oracle 에서사용자와스키마는동일한항목이지만, Postgres Plus Advanced Server 에서는사용자와스키마는 2 개의독립적인오브젝트입니다. 이사실은중요합니다 데이터베이스오브젝트권한 한번 SPL 프로그램이실행을시작하면, 참조하는오브젝트에대한현재사용자의사용권한을검사하여전체데이터베이스오브젝트에대한액세스가실행됩니다. 데이터베이스오브젝트에대해 GRANT 와 REVOKE 커맨드를사용하여각각권한을부여하거나해제할수있습니다. 만일현재사용자가데이터베이스오브젝트에권한없이접속하면프로그램은예외를발생시킵니다. 예외처리에대한자세한내용은 절을참조하십시오. 마지막주제는정확히현재사용자가누구인가를설명합니다. 251
252 소유자권한 vs. 호출자권한 SPL 프로그램이실행을시작하려고할때, 어떤사용자가이과정과관련되는지가결정됩니다. 사용자가 current user ( 현재사용자 ) 로간주됩니다. 자격이없는오브젝트참조를해결하기위해현재사용자의검색경로를결정합니다. 현재사용자의데이터베이스오브젝트권한은허락된프로그램을참조하는데이터베이스오브젝트에액세스할수있는지여부를결정하는데사용됩니다. SPL 프로그램은소유자또는호출자의권한으로생성되는지에따라현재사용자의선택이영향을받습니다. AUTHID 항목은그선택을결정합니다. AUTHID DEFINER 항목의계정은소유자권한을프로그램에제공합니다. 만약 AUTHID 항목이생략되어도이것은기본값입니다. AUTHID CURRENT _USER 항목을사용하면호출자에게권한이부여됩니다. 이둘의차이점을아래에요약합니다. 만약프로그램이소유자권한을가지고있다면, 프로그램이시작하는순간프로그램의소유자가현재사용자가됩니다. 프로그램소유자의검색경로가자격이없는오브젝트참조를해결하는데사용됩니다. 그리고프로그램소유자의데이터베이스오브젝트권한은참조하는오브젝트를액세스할수있는지여부를결정하기위해사용됩니다. 어떤사용자가실제로프로그램을호출하는지는관련이없습니다. 만약프로그램이호출자권한을가지는경우, 프로그램이호출될때의현재사용자가프로그램실행되는동안현재사용자로남습니다. ( 그러나호출된서브프로그램은예외입니다. - 아래설명참조 ) 호출자권한프로그램이시작되면, 현재사용자는일반적으로세션이시작됩니다 ( 예를들면, 데이터베이스접속생성 ). 그러나세션이시작한후에도 SET ROLE 커맨드를사용하여현재사용자를변경할수있습니다. 호출자권한프로그램에서는, 프로그램의실제소유자가누구인지는전혀관계가없습니다. 이상의정의는다음과같이말할수있습니다. 만약소유자권한프로그램이소유자권한프로그램을호출하면, 현재사용자가호출한 프로그램이실행되는동안호출프로그램의사용자에서호출되는프로그램의소유자로 전환됩니다 만약소유자권한프로그램이호출자권한프로그램을호출하면, 호출프로그램소유자가 호출및호출대상프로그램양측의현재사용자로남게됩니다. 만약호출자권한프로그램이호출자권한프로그램을호출하면, 호출프로그램의현재 사용자는호출될프로그램을실행하는동안현재사용자로남게됩니다 252
253 만약호출자권한프로그램이소유자권한프로그램을호출하면, 현재사용자가호출한 프로그램이실행되는동안소유자권한프로그램소유자로전환됩니다. 위에서언급한대로, 호출된프로그램이점차다른프로그램을호출할경우, 같은원칙이적용 됩니다. 보안과관련된절은간단한어플리케이션을사용하는예제로마무리합니다 보안예제 다음예제에서는새데이터베이스를두명의사용자와함께생성됩니다. - hr_mgr 는스키마 hr_mgr 안에모든샘플어플리케이션의사본을보유한사용자 ; 그리고 sales_mgr 는스키마 sales_mgr 을보유하고영업에서일하는직원만을포함하는 emp 테이블의복사본만을보유하고있습니다. 프로시저 list_emp, hire_clerk 함수, emp_admin 패키지는이예제에서사용됩니다. 샘플 애플리케이션을설치할때주어진모든기본권한은삭제하고예제에좀더안전한환경에서다시 명시적인권한을부여합니다. list_emp 과 hire_clerk 프로그램은기본소유자권한에서호출자권한으로변경됩니다. sales_mgr 가이프로그램을실행했을때를설명하면다음과같습니다. 프로그램은 sales_mgr 의검색경로와권한을이름확인과인증검사를위해사용하기때문에, sales_mgr 스키마내의 emp 테이블이실행됩니다. emp_admin 패키지의 get_dept_name 및 hire_emp 프로그램은 sales_mgr 를통해실행됩니다. 이경우 hr_mgr 스키마내 dept 테이블과 emp 테이블은소유자권한을가진 emp_admin 패키지의소유자인 hr_mgr 로접근됩니다. 1 단계 - 데이터베이스와사용자만들기 사용자 enterprisedb, 데이터베이스 hr 생성 : CREATE DATABASE hr; hr 데이터베이스로전환하고사용자생성 : \ c hr enterprisedb CREATE USER hr_mgr IDENTIFIED BY password; CREATE USER sales_mgr IDENTIFIED BY password; 2 단계 - 예제어플리케이션만들기 253
254 모든샘플애플리케이션을작성합니다. 스키마는 hr_mgr 의소유자는 hr_mgr 입니다. \ c - hr_mgr \ i C : / Postgres Plus Advanced Server/8.3/samples/edb-sample.sql BEGIN CREATE TABLE CREATE TABLE CREATE TABLE CREATE VIEW CREATE SEQUENCE... CREATE PACKAGE CREATE PACKAGE BODY COMMIT 3 단계 - 스키마 sales_mgr 에 emp 테이블을작성 스키마 sales_mgr 에 sales_mgr 가소유한 emp 테이블의하위집합을만듭니다. \ c - hr_mgr GRANT USAGE ON SCHEMA hr_mgr TO sales_mgr; \ c - sales_mgr CREATE TABLE emp AS SELECT * FROM hr_mgr.emp WHERE job = 'SALESMAN'; 위의예에서, GRANT USAG E ON SCHEMA 커맨드는스키마 hr_mgr 에 emp 테이블의복사본을만들려면 sales_mgr 에권한을부여해야합니다. Oracle 은사용자와전혀다른스키마라는개념이없기때문에이단계는 Postgres Plus Advanced Server 이필요하며, Oracle 과호환성이없습니다. 4 단계 - 기본권한삭제 다음에최소한의필요한권한을설정하기위해모든권한을제거합니다. \ c - hr_mgr REVOKE USAGE ON SCHEMA hr_mgr FROM sales_mgr; REVOKE ALL ON dept FROM PUBLIC; REVOKE ALL ON emp FROM PUBLIC; REVOKE ALL ON next_empno FROM PUBLIC; REVOKE EXECUTE ON FUNCTION new_empno () FROM PUBLIC; REVOKE EXECUTE ON PROCEDURE list_emp FROM PUBLIC; REVOKE EXECUTE ON FUNCTION hire_clerk (VARCHAR2, NUMBER) FROM PUBLIC; REVOKE EXECUTE ON PACKAGE emp_admin FROM PUBLIC; Step 5 - list_emp 를호출자권한으로변경사용자 hr_mgr 로서접속하는동안, list_emp 프로그램에 AUTHID CURRENT_USER 항목을추가하고이를 Postgres Plus Advanced Server 에다시저장합니다. 이단계를수행할때는 254
255 hr_mgr 로로그인해야합니다. 그렇지않으면수정된프로그램이 hr_mgr 스키마가아닌 public 스키마에저장됩니다. CREATE OR REPLACE PROCEDURE list_emp AUTHID CURRENT_USER IS v_empno NUMBER (4); v_ename VARCHAR2 (10); CURSOR emp_cur IS SELECT empno, ename FROM emp ORDER BY empno; BEGIN OPEN emp_cur; DBMS_OUTPUT.PUT_LINE ( 'EMPNO ENAME'); DBMS_OUTPUT.PUT_LINE (' '); LOOP FETCH emp_cur INTO v_empno, v_ename; EXIT WHEN emp_cur % NOTFOUND; DBMS_OUTPUT.PUT_LINE (v_empno '' v_ename); END LOOP; CLOSE emp_cur; END; 6 단계 - hire_clerk 를호출자권한으로변경하고 new_empno 를권한이주어진호출 hr_mgr 사용자로접속하는동안, hire_clerk 프로그램에 AUTHID CURRENT_USER 항목을 추가합니다. 또한, BEGIN 문장다음에 new_empno 에 hr_mgr.new_empno 를참조하는자격을부여합니다. 이것은 hire_clerk 함수가 hr_mgr 스키마내 new_empno 함수를호출할수있도록하기위한것입니다. 호출은완전한수식이름으로변경되어야합니다. 한편 hire_clerk 은현재호출자권한프로그램이기때문에, new_empno 에대한자격없는호출은실제로이프로그램이있는 hr_mgr 스키마에지정된것이아닌, hire_clerk 를호출하는원래의검색경로스키마의 new_empno 을찾습니다. 이프로그램을다시저장할때 hr_mgr 로로그인되었는지확인하십시오. 그렇지않으면변경된 프로그램은 hr_mgr 스키마가아닌 public 스키마에저장될지모릅니다. CREATE OR REPLACE FUNCTION hire_clerk ( p_ename VARCHAR2, p_deptno NUMBER ) RETURN NUMBER AUTHID CURRENT_USER IS v_empno NUMBER (4); v_ename VARCHAR2 (10); v_job VARCHAR2 (9); v_mgr NUMBER (4); v_hiredate DATE; v_sal NUMBER (7,2); v_comm NUMBER (7,2); v_deptno NUMBER (2); 255
256 BEGIN v_empno : = hr_mgr.new_empno; INSERT INTO emp VALUES (v_empno, p_ename, 'CLERK', 7782, TRUNC (SYSDATE), , NULL, p_deptno); SELECT empno, ename, job, mgr, hiredate, sal, comm, deptno INTO v_empno, v_ename, v_job, v_mgr, v_hiredate, v_sal, v_comm, v_deptno FROM emp WHERE empno = v_empno; DBMS_OUTPUT.PUT_LINE ( 'Department :' v_deptno); DBMS_OUTPUT.PUT_LINE ( 'Employee No :' v_empno); DBMS_OUTPUT.PUT_LINE ( 'Name :' v_ename); DBMS_OUTPUT.PUT_LINE ( 'Job :' v_job); DBMS_OUTPUT.PUT_LINE ( 'Manager :' v_mgr); DBMS_OUTPUT.PUT_LINE ( 'Hire Date :' v_hiredate); DBMS_OUTPUT.PUT_LINE ( 'Salary :' v_sal); DBMS_OUTPUT.PUT_LINE ( 'Commission :' v_comm); RETURN v_empno; EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE ( 'The following is SQLERRM :'); DBMS_OUTPUT.PUT_LINE (SQLERRM); DBMS_OUTPUT.PUT_LINE ( 'The following is SQLCODE :'); DBMS_OUTPUT.PUT_LINE (SQLCODE); RETURN -1; END; 7 단계 - 필요한권한부여 hr_mgr 사용자가접속하는동안, sales_mgr 이 list_emp 프로시저, hire_clerk 함수와 emp_admin 패키지를실행할수있는권한을부여합니다. 데이터오브젝트 sales_mgr 은 sales_mgr 스키마내 emp 테이블에만액세스할수있는권한을가지고있는것을주의하십시요. sales_mgr 은 hr_mgr 스키마의모든테이블에접근할권한이없습니다. GRANT EXECUTE ON PROCEDURE list_emp TO sales_mgr; GRANT EXECUTE ON FUNCTION hire_clerk (VARCHAR2, NUMBER) TO sales_mgr; GRANT EXECUTE ON FUNCTION new_empno () TO sales_mgr; GRANT EXECUTE ON PACKAGE emp_admin TO sales_mgr; 8 단계 - list_emp 과 hire_clerk 프로그램실행 sales_mgr 사용자로접속하고, 다음의익명블록을실행합니다. \ c - sales_mgr DECLARE v_empno NUMBER (4); BEGIN hr_mgr.list_emp; DBMS_OUTPUT.PUT_LINE ('*** Adding new employee ***'); v_empno : = hr_mgr.hire_clerk ( 'JONES', 40); DBMS_OUTPUT.PUT_LINE ('*** After new employee added ***'); hr_mgr.list_emp; END; 256
257 EMPNO ENAME ALLEN 7521 WARD 7654 MARTIN 7844 TURNER *** Adding new employee *** Department : 40 Employee No : 8000 Name : JONES Job : CLERK Manager : 7782 Hire Date : 08 - NOV :00:00 Salary : *** After new employee added *** EMPNO ENAME ALLEN 7521 WARD 7654 MARTIN 7844 TURNER 8000 JONES 익명차단프로그램으로접근한테이블과시퀀스는아래의그림으로나타냈습니다. 회색 타원형은 sales_mgr 과 hr_mgr 스키마입니다. 프로그램실행시현재사용자는굵은적색글씨로 괄호안에표현됩니다. 그림 3 - 호출자권한프로그램 sales_mgr 의 emp 테이블로부터의선택은테이블에서이루어진업데이트를표시합니다. SELECT empno, ename, hiredate, sal, deptno, hr_mgr.emp_admin.get_dept_name (deptno) FROM sales_mgr.emp; 257
258 empno ename hiredate sal deptno get_dept_name ALLEN 20 - FEB :00: SALES 7521 WARD 22 - FEB :00: SALES 7654 MARTIN 28 - SEP :00: SALES 7844 TURNER 08 - SEP :00: SALES 8000 JONES 08 - NOV :00: OPERATIONS (5 rows) 다음그림은 sales_mgr 스키마내의 emp 테이블을참조하는 SELECT 커맨드를보여줍니다. emp_admin 패키지의 get_dept_name 함수가참조하는 dept 테이블은 hr_mgr 스키마에있습니다. 왜냐하면 emp_admin 패키지는소유자권한을가지고 hr_mgr 가소유하고있기때문입니다. 그림 4 소유자권한패키지 9 단계 - emp_admin 패키지내 hire_emp 프로그램실행 sales_mgr 사용자로접속하는동안, emp_admin 패키지의 hire_emp 프로시저를실행합니다. EXEC hr_mgr.emp_admin.hire_emp (9001, 'ALICE', 'SALESMAN', 8000, TRUNC (SYSDATE), 1000,7369,40); 이그림은 emp_admin 소유자권한패키지내 hire_emp 프로시저가 hr_mgr 에속하는 emp 테이블을업데이트한다는것을의미합니다. 258
259 그림 5 소유자권한패키지 이제사용자 hr_mgr 로접속합니다. 다음 SELECT 커맨드는 hr_mgr emp 테이블에추가된새로운 직원을확인합니다. 여기서 emp_admin 패키지는소유자권한을가지며, hr_mgr 은 emp_admin 소유자입니다. \ c - hr_mgr SELECT empno, ename, hiredate, sal, deptno, hr_mgr.emp_admin.get_dept_name (deptno) FROM hr_mgr.emp; empno ename hiredate sal deptno get_dept_name SMITH 17 - DEC :00: RESEARCH 7499 ALLEN 20 - FEB :00: SALES 7521 WARD 22 - FEB :00: SALES 7566 JONES 02 - APR :00: RESEARCH 7654 MARTIN 28 - SEP :00: SALES 7698 BLAKE 01 - MAY :00: SALES 7782 CLARK 09 - JUN :00: ACCOUNTING 7788 SCOTT 19 - APR :00: RESEARCH 7839 KING 17 - NOV :00: ACCOUNTING 7844 TURNER 08 - SEP :00: SALES 7876 ADAMS 23 - MAY :00: RESEARCH 7900 JAMES 03 - DEC :00: SALES 7902 FORD 03 - DEC :00: RESEARCH 7934 MILLER 23 - JAN :00: ACCOUNTING 9001 ALICE 08 - NOV :00: OPERATIONS (15 rows) 4.3 변수선언 절에서설명한것처럼, SPL 은블록구조의언어입니다. 블록의첫번째영역은선언 부입니다. 선언부는변수, 정의, 커서및블록을포함하는 SPL 문장에서사용되는다른형식의 정의를포함합니다. 본절에서는변수선언에대해자세히설명합니다. 259
260 4.3.1 변수선언 일반적으로블록내에서사용되는모든변수는블록선언부에서선언되어야합니다. 변수 선언은변수에지정된이름과데이터형식으로이루어집니다. ( 데이터형식에대해서는 3.2 절 참조 ) 선택적으로, 변수를선언할때기본값으로초기화할수있습니다. 변수선언의일반적인구문은다음과같습니다. name type [(: = DEFAULT) (expression NULL)]; name 은변수에할당된식별자입니다. type 은변수에지정된데이터형식입니다. 만약 [: = expression ] 이지정되어있으면, 블록이실행될때변수에기본값이할당됩니다. 만약이 항목이없는경우, 변수는 SQL null 값으로초기화됩니다. 기본값은블록이실행될때마다평가됩니다. 예를들어 DATE 형식의변수에 SYSDATE 를 지정하면, 이변수는프로시저와함수가사전에컴파일됐던시간이아닌현재호출시간을 가집니다. 다음프로시저는문자열과숫자표현의기본값을사용하는변수선언의예를보여줍니다. CREATE OR REPLACE PROCEDURE dept_salary_rpt ( p_deptno NUMBER ) IS todays_date DATE : = SYSDATE; rpt_title VARCHAR2 (60) : = 'Report For Department #' p_deptno 'on' todays_date; base_sal INTEGER : = 35525; base_comm_rate NUMBER : = ; base_annual NUMBER : = ROUND (base_sal * base_comm_rate, 2); BEGIN DBMS_OUTPUT.PUT_LINE (rpt_title); DBMS_OUTPUT.PUT_LINE ( 'Base Annual Salary :' base_annual); END; 다음은위의프로시저출력이변수선언으로기본값이확실하게변수로할당되었다는것을 보여줍니다. EXEC dept_salary_rpt (20); Report For Department # 20 on 10 - JUL :44:45 Base Annual Salary : 변수선언에서 % TYPE 사용 260
261 데이터베이스테이블값을변수로 SPL 프로그램에서선언하고싶은경우가있습니다. 테이블 열을 SPL 변수간의호환되도록하기위해, 2 개의데이터형식은동일해야합니다. 그러나, 드물지만테이블정의에변화가발생할수있습니다. 만약열의데이터형식을변경하는 경우에는 SPL 프로그램변수에도대응하는변화가필요합니다. 변수선언에사용할데이터형식을코딩하는대신, 열특성 % TYPE 을대신사용할수있습니다. 점 (dot) 표기에의한자격있는이름이나이전에선언했던변수이름앞에 % TYPE 를지정해야합니다. 열의데이터형식및 % TYPE 이앞에붙은변수는변수로선언됩니다. 만약지정된열과변수의데이터유형이변경되더라도선언코드를수정하지않고, 관련변수는새로운데이터형식으로전환됩니다. 참고 : % TYPE 속성은형식인자의정의에서사용될수있습니다. name (table. column variable) % TYPE; Name 은선언되는변수와형식인자의식별자입니다. Column 은 table 이나뷰의열이름입니다. Variable 는 name 으로식별하는미리정의된변수이름입니다. 다음예제는프로시저직원수를사용해서, emp 테이블을쿼리하고직원데이터를표시하여, 해당직원이근무하는부서의모든직원의평균임금을계산합니다. 그리고선택한직원의 급여를해당부서의평균급여와비교합니다. CREATE OR REPLACE PROCEDURE emp_sal_query ( p_empno IN NUMBER ) IS v_ename VARCHAR2 (10); v_job VARCHAR2 (9); v_hiredate DATE; v_sal NUMBER (7,2); v_deptno NUMBER (2); v_avgsal NUMBER (7,2); BEGIN SELECT ename, job, hiredate, sal, deptno INTO v_ename, v_job, v_hiredate, v_sal, v_deptno FROM emp WHERE empno = p_empno; DBMS_OUTPUT.PUT_LINE ( 'Employee # :' p_empno); DBMS_OUTPUT.PUT_LINE ( 'Name :' v_ename); DBMS_OUTPUT.PUT_LINE ( 'Job :' v_job); DBMS_OUTPUT.PUT_LINE ( 'Hire Date :' v_hiredate); DBMS_OUTPUT.PUT_LINE ( 'Salary :' v_sal); DBMS_OUTPUT.PUT_LINE ( 'Dept # :' v_deptno); SELECT AVG (sal) INTO v_avgsal FROM emp WHERE deptno = v_deptno; IF v_sal> v_avgsal THEN DBMS_OUTPUT.PUT_LINE ( 'Employee' 's salary is more than the department' 261
262 'average of' v_avgsal); ELSE DBMS_OUTPUT.PUT_LINE ( 'Employee' 's salary does not exceed the department' 'average of' v_avgsal); END IF; END; 위의예제에서프로시저의선언영역으로 emp 테이블의데이터형식을명시적으로코딩하지 않고쓸수있습니다. CREATE OR REPLACE PROCEDURE emp_sal_query ( p_empno IN emp.empno % TYPE ) IS v_ename emp.ename % TYPE; v_job emp.job % TYPE; v_hiredate emp.hiredate % TYPE; v_sal emp.sal % TYPE; v_deptno emp.deptno % TYPE; v_avgsal v_sal % TYPE; BEGIN SELECT ename, job, hiredate, sal, deptno INTO v_ename, v_job, v_hiredate, v_sal, v_deptno FROM emp WHERE empno = p_empno; DBMS_OUTPUT.PUT_LINE ( 'Employee # :' p_empno); DBMS_OUTPUT.PUT_LINE ( 'Name :' v_ename); DBMS_OUTPUT.PUT_LINE ( 'Job :' v_job); DBMS_OUTPUT.PUT_LINE ( 'Hire Date :' v_hiredate); DBMS_OUTPUT.PUT_LINE ( 'Salary :' v_sal); DBMS_OUTPUT.PUT_LINE ( 'Dept # :' v_deptno); SELECT AVG (sal) INTO v_avgsal FROM emp WHERE deptno = v_deptno; IF v_sal> v_avgsal THEN DBMS_OUTPUT.PUT_LINE ( 'Employee' 's salary is more than the department' 'average of' v_avgsal); ELSE DBMS_OUTPUT.PUT_LINE ( 'Employee' 's salary does not exceed the department' 'average of' v_avgsal); END IF; END; 참고 : p_empno 은 % TYPE 을사용하여정의한형식인자의예를보여줍니다. v_avgsal 는테이블열대신다른변수를참조하는 % TYPE 사용법을나타냅니다. 다음은이프로시저실행결과의예입니다. EXEC emp_sal_query (7698); Employee # : 7698 Name : BLAKE Job : MANAGER Hire Date : 01 - MAY :00:00 Salary : Dept # : 30 Employee 's salary is more than the department average of
263 4.3.3 레코드선언에서의 % ROWTYPE 사용 % TYPE 속성을통해열의데이터형식에의존하는변수를쉽게만들수있습니다. % ROWTYPE 속성을통해지정한테이블의모든열필드의레코드를정의할수있습니다. 각필드는해당 열의데이터형식입니다. 참고 : 레코드의필드는 NOT NULL 항목이나 DEFAULT 항목으로정의되는다른열의속성중어느 것도상속받지않습니다. Record 는이름은필드집합에지시를내립니다. Field 는변수와마찬가지로식별자와데이터 형식을갖습니다. 그러나레코드에속하는속성을가지며, 레코드이름을수식어로서점 표기법을사용하여참조합니다. 레코드는 % ROWTYPE 속성을사용하여선언됩니다. % ROWTYPE 속성은테이블이름앞에 붙습니다. 지정한테이블의각열은, 열과같은데이터형식의레코드이름이지정된필드로 정의됩니다. record table % ROWTYPE; Record 은레코드에할당된식별자입니다. Table 은열을레코드의필드를정의하는이름입니다. 뷰또한레코드를정의하기위해사용됩니다. 다음은이전영역의 emp_sal_query 프로시저가 emp 테이블의열을별도의변수로정의하지 않고, r_emp 레코드를 emp % ROWTYPE 을이용하여만들면어떻게변경될수있는지 보여줍니다. CREATE OR REPLACE PROCEDURE emp_sal_query ( p_empno IN emp.empno % TYPE ) IS r_emp emp % ROWTYPE; v_avgsal emp.sal % TYPE; BEGIN SELECT ename, job, hiredate, sal, deptno INTO r_emp.ename, r_emp.job, r_emp.hiredate, r_emp.sal, r_emp.deptno FROM emp WHERE empno = p_empno; DBMS_OUTPUT.PUT_LINE ( 'Employee # :' p_empno); DBMS_OUTPUT.PUT_LINE ( 'Name :' r_emp.ename); DBMS_OUTPUT.PUT_LINE ( 'Job :' r_emp.job); DBMS_OUTPUT.PUT_LINE ( 'Hire Date :' r_emp.hiredate); DBMS_OUTPUT.PUT_LINE ( 'Salary :' r_emp.sal); DBMS_OUTPUT.PUT_LINE ( 'Dept # :' r_emp.deptno); SELECT AVG (sal) INTO v_avgsal FROM emp WHERE deptno = r_emp.deptno; IF r_emp.sal> v_avgsal THEN 263
264 DBMS_OUTPUT.PUT_LINE ( 'Employee' 's salary is more than the department' 'average of' v_avgsal); ELSE DBMS_OUTPUT.PUT_LINE ( 'Employee' 's salary does not exceed the department' 'average of' v_avgsal); END IF; END; 사용자정의레코드형과레코드변수 레코드는 % ROWTYPE 속성을사용하여테이블의정의를기반으로선언할수있는부분을 절에서설명했습니다. 본절에서는어떤특정한테이블정의에얽매이지않는새로운 레코드구조를정의하는방법을설명합니다, TYPE IS RECORD 구문은레코드형식정의를만드는데사용합니다. record type 은하나이상의 레코드와각각의데이터형식으로구성됩니다. 레코드형식자체가데이터조작에이용되는 것은아닙니다. 다음은레코드형식을정의하는구문입니다. TYPE rectype IS RECORD (field_1 [, field_2 datatype_2]...); datatype_1 rectype 레코드형식에할당된식별자입니다. field_1, field_2... 레코드형식필드에할당된 식별자입니다. datatype_1, data type_2... 은각각 field_1, field_2... 데이터형식입니다. record variable 아니면그냥 record 레코드형식의인스턴스입니다. 레코드는레코드형식으로 선언됩니다. 필드이름이나형식등의레코드속성은레코드형식에서상속됩니다. 다음은레코드선언구문입니다. record rectype record 레코드변수에할당된식별자입니다. Rectype 은이전에정의된레코드형식의 식별자입니다. 한번선언되면레코드는데이터를보유하기위해사용할수있습니다. 레코드필드를참조하기위해서는점표기법을사용합니다. record.field record 은이전에선언한레코드변수이며, field 는 record 가정의한레코드유형에속하는 필드의식별자입니다. 264
265 다시 emp_sal_query 을변경합니다. - 이번에는사용자정의레코드형과레코드변수를 사용하십시오. CREATE OR REPLACE PROCEDURE emp_sal_query ( p_empno IN emp.empno % TYPE ) IS TYPE emp_typ IS RECORD ( ename emp.ename % TYPE, job emp.job % TYPE, hiredate emp.hiredate % TYPE, sal emp.sal % TYPE, deptno emp.deptno % TYPE ); r_emp emp_typ; v_avgsal emp.sal % TYPE; BEGIN SELECT ename, job, hiredate, sal, deptno INTO r_emp.ename, r_emp.job, r_emp.hiredate, r_emp.sal, r_emp.deptno FROM emp WHERE empno = p_empno; DBMS_OUTPUT.PUT_LINE ( 'Employee # :' p_empno); DBMS_OUTPUT.PUT_LINE ( 'Name :' r_emp.ename); DBMS_OUTPUT.PUT_LINE ( 'Job :' r_emp.job); DBMS_OUTPUT.PUT_LINE ( 'Hire Date :' r_emp.hiredate); DBMS_OUTPUT.PUT_LINE ( 'Salary :' r_emp.sal); DBMS_OUTPUT.PUT_LINE ( 'Dept # :' r_emp.deptno); SELECT AVG (sal) INTO v_avgsal FROM emp WHERE deptno = r_emp.deptno; IF r_emp.sal> v_avgsal THEN DBMS_OUTPUT.PUT_LINE ( 'Employee' 's salary is more than the' 'department average of' v_avgsal); ELSE DBMS_OUTPUT.PUT_LINE ( 'Employee' 's salary does not exceed the' 'department average of' v_avgsal); END IF; END; 데이터형식의이름을지정하는대신, % TYPE 속성을레코드타입을정의하는필드데이터 형식으로사용될수있는것을주의하십시오. 다음은프로시저를실행결과입니다. EXEC emp_sal_query (7698); Employee # : 7698 Name : BLAKE Job : MANAGER Hire Date : 01 - MAY :00:00 Salary : Dept # : 30 Employee 's salary is more than the department average of
266 4.4 기본문장 이번절에서는 SPL 프로그램에서사용되는프로그래밍문장에대해설명합니다 NULL 가장간단한문장은 NULL 문장입니다. 이문장은실행가능한문장이지만, 아무것도하지 않습니다. NULL; 다음은가장간단하고도효과적인 SPL 프로그램입니다. BEGIN NULL; END; NULL 문은 IF - THEN - ELSE 문장분기와같은실행가능한문장이필요한플레이스홀더로 유용합니다. 예를들면다음과같습니다 : CREATE OR REPLACE PROCEDURE divide_it ( p_numerator IN NUMBER, p_denominator IN NUMBER, p_result OUT NUMBER ) IS BEGIN IF p_denominator = 0 THEN NULL; ELSE p_result : = p_numerator / p_denominator; END IF; END; 지정 대입문장은변수와 OUT, IN OUT 모드의형식인자로구성됩니다. : = 왼쪽위치를지정하고 오른쪽위치에수식을지정합니다. variable : = expression; variable 은이전에선언한변수, O UT 형식인자또는 IN OUT 형식인자를위한식별자입니다. expression 는단일값을생성하는식입니다. 이표현에의해생성된값은 variable 에적합한데이터형식을가지고있어야합니다. 266
267 4.3 절의 dept_salary_rpt 예제는변수선언에서대입문장을사용한것을나타냅니다. 이예제와의 차이점은프로시저실행영역에서대입문장의대표적인사용방법입니다. CREATE OR REPLACE PROCEDURE dept_salary_rpt ( p_deptno NUMBER ) IS todays_date DATE; rpt_title VARCHAR2 (60); base_sal INTEGER; base_comm_rate NUMBER; base_annual NUMBER; BEGIN todays_date : = SYSDATE; rpt_title : = 'Report For Department #' p_deptno 'on' todays_date; base_sal : = 35525; base_comm_rate : = ; base_annual : = ROUND (base_sal * base_comm_rate, 2); DBMS_OUTPUT.PUT_LINE (rpt_title); DBMS_OUTPUT.PUT_LINE ( 'Base Annual Salary :' base_annual); END; SELECT INTO SELECT INTO 문은 SQL SELECT 커맨드 SPL 의변형입니다. 그차이는다음과같습니다 : SELECT INTO 는그결과를 SPL 프로그램문장에서유효한변수와레코드에할당하도록설계되 었습니다 SELECT INTO 에접근할수있는결과는대부분 1 행입니다 위를제외하고, WHERE, ORDER BY, GROUP BY, HAVING 와같은 SELECT 커맨드의모든항목은 SELECT INTO 에도유효합니다. 다음은 SELECT INTO 의 2 가지변형입니다. SELECT select_expressions INTO target FROM...; target 은콤마로분리된간단한변수의리스트입니다. select_expressions 과문장의나머지 부분은 SELECT 커맨드와같습니다. 검색된값은데이터형식, 수그리고결과구조의순서가 일치해야합니다. 그렇지않으면런타임오류가발생합니다. SELECT * INTO record FROM table -; record 은미리선언된레코드변수입니다. 267
268 만일쿼리가 0 행으로리턴되면, null 값이 target 으로설정됩니다. 만일쿼리가여러행에 리턴되면, 첫번째행이 target 로설정하고나머지부분은무시됩니다. (ORDER BY 를사용하지 않는한, " 첫행 " 은명확하게정의되지않으므로주의하시기바랍니다.) 참고 : 행이리턴되지않거나하나이상의행이리턴되는경우모두, SPL 에서예외가발생합니다. 참고 : SELECT INTO 에 BULK COL LECT 항목을사용하면, 컬렉션에반환된 1 줄이상의결과 집합을허용됩니다. SELECT INTO 문장의 BULK COLLECT 항목이용방법에대한자세한내용은 절을참조하십시오. EXCEPTION 블록지정이성공했는지여부 ( 여기에는적어도 1 줄이상의행을반환하는 ) 을 결정하기위해 WHEN NO_DATA_FOUND 항목을사용할수있습니다. emp_sal_quer y 프로시저의버전은결과집합을레코드에반환하는 SELECT INTO 의변형을 사용합니다. 또한 WHEN NO_DATA_FOUND 조건식을가진 EXCEPTION 블록이추가되었다는 것을주의하십시오. CREATE OR REPLACE PROCEDURE emp_sal_query ( p_empno IN emp.empno % TYPE ) IS r_emp emp % ROWTYPE; v_avgsal emp.sal % TYPE; BEGIN SELECT * INTO r_emp FROM emp WHERE empno = p_empno; DBMS_OUTPUT.PUT_LINE ( 'Employee # :' p_empno); DBMS_OUTPUT.PUT_LINE ( 'Name :' r_emp.ename); DBMS_OUTPUT.PUT_LINE ( 'Job :' r_emp.job); DBMS_OUTPUT.PUT_LINE ( 'Hire Date :' r_emp.hiredate); DBMS_OUTPUT.PUT_LINE ( 'Salary :' r_emp.sal); DBMS_OUTPUT.PUT_LINE ( 'Dept # :' r_emp.deptno); SELECT AVG (sal) INTO v_avgsal FROM emp WHERE deptno = r_emp.deptno; IF r_emp.sal> v_avgsal THEN DBMS_OUTPUT.PUT_LINE ( 'Employee' 's salary is more than the' 'department average of' v_avgsal); ELSE DBMS_OUTPUT.PUT_LINE ( 'Employee' 's salary does not exceed the' 'department average of' v_avgsal); END IF; EXCEPTION WHEN NO_DATA_FOUND THEN DBMS_OUTPUT.PUT_LINE ( 'Employee #' p_empno 'not found'); END; 만일검색이존재하는직원없이실행된다면, 결과는다음과같습니다. 268
269 EXEC emp_sal_query (0); Employee # 0 not found SELECT INTO 의 EXCEPTION 영역에서다른조건항목은 TOO_MANY_ROWS 예외입니다. 만약 SELECT INTO 문장에서하나이상의행이검색되면, SPL 에서예외가발생합니다. 다음블록이실행되면특정한부서에많은직원이등록되어있기때문에, TOO_MANY_ROWS 예외가발생합니다. DECLARE v_ename emp.ename % TYPE; BEGIN SELECT ename INTO v_ename FROM emp WHERE deptno = 20 ORDER BY ename; EXCEPTION WHEN TOO_MANY_ROWS THEN DBMS_OUTPUT.PUT_LINE ( 'More than one employee found'); DBMS_OUTPUT.PUT_LINE ( 'First employee returned is' v_ename); END; More than one employee found First employee returned is ADAMS 참고 : 예외처리에대한자세한내용은 절을참조하십시오 INSERT SQL 언어에서이용할수있는 INSERT 커맨드는 SPL 프로그램에서도사용할수있습니다. SPL 언어표현식은 SQL INSERT 커맨드로허용되는표현의모든위치에서사용할수있습니다. 따라서 SPL 변수및인자를삽입연산에값을전달할수있습니다. 다음은호출프로그램에서데이터를전달하여새로운직원의삽입을수행하는프로시저의 예입니다. CREATE OR REPLACE PROCEDURE emp_insert ( p_empno IN emp.empno % TYPE, p_ename IN emp.ename % TYPE, p_job IN emp.job % TYPE, p_mgr IN emp.mgr % TYPE, p_hiredate IN emp.hiredate % TYPE, p_sal IN emp.sal % TYPE, p_comm IN emp.comm % TYPE, p_deptno IN emp.deptno % TYPE ) IS BEGIN INSERT INTO emp VALUES ( p_empno, 269
270 p_ename, p_job, p_mgr, p_hiredate, p_sal, p_comm, p_deptno); DBMS_OUTPUT.PUT_LINE ( 'Added employee...'); DBMS_OUTPUT.PUT_LINE ( 'Employee # :' p_empno); DBMS_OUTPUT.PUT_LINE ( 'Name :' p_ename); DBMS_OUTPUT.PUT_LINE ( 'Job :' p_job); DBMS_OUTPUT.PUT_LINE ( 'Manager :' p_mgr); DBMS_OUTPUT.PUT_LINE ( 'Hire Date :' p_hiredate); DBMS_OUTPUT.PUT_LINE ( 'Salary :' p_sal); DBMS_OUTPUT.PUT_LINE ( 'Commission :' p_comm); DBMS_OUTPUT.PUT_LINE ( 'Dept # :' p_deptno); DBMS_OUTPUT.PUT_LINE (' '); EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE ( 'OTHERS exception on INSERT of employee #' p_empno); DBMS_OUTPUT.PUT_LINE ( 'SQLCODE :' SQLCODE); DBMS_OUTPUT.PUT_LINE ( 'SQLERRM :' SQLERRM); END; 만약예외가발생하면프로시저에서만들어지는모든데이터베이스의변경은자동으로롤백됩니다. 이경우, WHEN OTHERS 구문의 EXCEPTION 영역의모든예외를가져옵니다. 2 가지변수가나타납니다. SQLCODE 는발생한예외를확인하는숫자입니다. SQLERRM 는오류를설명하는텍스트메시지입니다. 예외처리에대한자세한내용은 절을참조하십시오. 다음은이프로시저를실행할때출력을나타냅니다. EXEC emp_insert (9503, 'PETERSON', 'ANALYST', 7902, '31 - MAR - 05 ', 5000, NULL, 40); Added employee... Employee # : 9503 Name : PETERSON Job : ANALYST Manager : 7902 Hire Date : 31 - MAR :00:00 Salary : 5000 Dept # : SELECT * FROM emp WHERE empno = 9503; empno ename job mgr hiredate sal comm deptno PETERSON ANALYST MAR :00: (1 row) 270
271 참고 : INSERT 커맨드는 FORALL 문장에포함될수있습니다. FORALL 문장은 1 개의 INSERT 커맨드를하나이상의컬렉션에전달된값으로부터여러행을삽입하도록합니다. FORALL 문장에대한정보는 절을참조하십시오 UPDATE SQL 언어에서사용할수 UPDATE 커맨드는 SPL 프로그램에서도사용할수있습니다. SPL 언어의표현식은 SQL UPDATE 커맨드에서허용되는표현식의모든곳에서사용할수 있습니다. 따라서 SPL 변수와인자는업데이트연산에서값을전달할수있습니다. CREATE OR REPLACE PROCEDURE emp_comp_update ( p_empno IN emp.empno % TYPE, p_sal IN emp.sal % TYPE, p_comm IN emp.comm % TYPE ) IS BEGIN UPDATE emp SET sal = p_sal, comm = p_comm WHERE empno = p_empno; IF SQL % FOUND THEN DBMS_OUTPUT.PUT_LINE ( 'Updated Employee # :' p_empno); DBMS_OUTPUT.PUT_LINE ( 'New Salary :' p_sal); DBMS_OUTPUT.PUT_LINE ( 'New Commission :' p_comm); ELSE DBMS_OUTPUT.PUT_LINE ( 'Employee #' p_empno 'not found'); END IF; END; 만약행이업데이트된경우는 SQL % FOUND 조건식이 "true" 를반환하고, 그렇지않은경우는 "false" 을반환합니다. SQL % FOUND 과기타유사한표현에대한설명은 절을 참조하십시오. 다음은이프로시저를사용하여직원을갱신하고있습니다. EXEC emp_comp_update (9503, 6540, 1200); Updated Employee # : 9503 New Salary : 6540 New Commission : 1200 SELECT * FROM emp WHERE empno = 9503; empno ename job mgr hiredate sal comm deptno PETERSON ANALYST MAR :00: (1 row) 271
272 참고 : UPDATE 커맨드는 FORALL 문장에포함됩니다. FORALL 문장은 1 개의 UPDATE 커맨드에서 1 개이상의컬렉션에전달된값으로여러행을업데이트하는것을허용합니다 절에서 FORALL 문장에대한정보를참조하십시오 DELETE SQL 언어에서사용할수 DELETE 커맨드는 SPL 프로그램에서도사용할수있습니다. SPL 언어의표현은 SQL DELETE 커맨드에서허용되는표현의모든위치에서사용할수있습니다. 따라서 SPL 변수와인자는삭제연산에값을전달할수있습니다. CREATE OR REPLACE PROCEDURE emp_delete ( p_empno IN emp.empno % TYPE ) IS BEGIN DELETE FROM emp WHERE empno = p_empno; IF SQL % FOUND THEN DBMS_OUTPUT.PUT_LINE ( 'Deleted Employee # :' p_empno); ELSE DBMS_OUTPUT.PUT_LINE ( 'Employee #' p_empno 'not found'); END IF; END; 만약행을삭제한경우, SQL%FOUND 조건식이 "true" 를반환하고, 그렇지않은경우 "false" 을 반환합니다. SQL%FOUND 과기타유사한표현에대한설명은 절을참조하십시오. 다음은이프로시저를통해직원을제거합니다. EXEC emp_delete (9503); Deleted Employee # : 9503 SELECT * FROM emp WHERE empno = 9503; empno ename job mgr hiredate sal comm deptno (0 rows) 참고 : DELETE 커맨드는 FORALL 문장에포함됩니다. FORALL 문장은 1 개의 DELETE 커맨드에서 1 개이상의컬렉션에전달된값으로여러행을제거하는것을허용합니다. FORALL 문장에 대한정보는 절을참조하십시오 RETURNING INTO 구문사용 272
273 INSERT, UPDATE, DELETE 커맨드는 RETURNING INTO 구문을선택적으로사용할수있습니다. 이 구문은 SPL 프로그램이새로이추가, 변경또는삭제된값을 INSERT, UPDATE 및 DELETE 커맨드 각각의결과로볼수있도록합니다. 다음이그형식입니다. (insert update delete) RETURNING (* expr_1 [, expr_2]...) INTO ( record field_1 [, field_2]...); Insert 는효과적인 INSERT 커맨드입니다. update 는효과적인 UPDATE 커맨드입니다. delete 는효과적인 DELETE 커맨드입니다. 만약 * 가지정되면, INSERT, UPDATE 및 DELETE 커맨드에영향을받은행의값은 INTO 키워드의레코드와오른쪽필드에할당됩니다. ( 주 : * 사용은 Postgres Plus Advanced Server 의확장이며, Oracle 와호환되지않습니다. ) expr_1, expr_2... 는 INSERT, UPDATE 및 DELETE 커맨드로처리된행에대한수식입니다. 평가결과는 INTO 키워드의오른쪽필드나레코드로할당됩니다. record 는숫자와순서가일치하는필드로구성된레코드식별자에서데이터형식이 RETURNING 항목의값과일치합니다. field_1, field_2... 는숫자와순서가일치하는변수이고, 데이터형식은 RETURNING 항목의값집합과일치합니다. 만약 INSERT, UPDATE 및 DELETE 커맨드가 1 줄이상의결과집합을반환하면, SQLCODE 01422, query returned more than one row 라는예외가발생합니다. 만약결과집합에행이없으면, INTO 키워드를따르는변수는 null 로설정됩니다. 참고 : RETURNING INTO 의변형에서 BULK COLLECT 항목을사용할경우, 컬렉션에반환된 1 행 이상의결과집합을허용합니다. BULK COLLECT 항목이용방법에대한자세한내용은 절을참조하십시오. 다음은 절에서소개한 emp_comp_update 프로시저, RETURNING INTO 항목을추가하여 수정한예제입니다. CREATE OR REPLACE PROCEDURE emp_comp_update ( p_empno IN emp.empno % TYPE, p_sal IN emp.sal % TYPE, p_comm IN emp.comm % TYPE ) IS v_empno emp.empno % TYPE; v_ename emp.ename % TYPE; v_job emp.job % TYPE; v_sal emp.sal % TYPE; v_comm emp.comm % TYPE; v_deptno emp.deptno % TYPE; BEGIN UPDATE emp SET sal = p_sal, comm = p_comm WHERE empno = p_empno RETURNING 273
274 empno, ename, job, sal, comm, deptno INTO v_empno, v_ename, v_job, v_sal, v_comm, v_deptno; IF SQL % FOUND THEN DBMS_OUTPUT.PUT_LINE ( 'Updated Employee # :' v_empno); DBMS_OUTPUT.PUT_LINE ( 'Name :' v_ename); DBMS_OUTPUT.PUT_LINE ( 'Job :' v_job); DBMS_OUTPUT.PUT_LINE ( 'Department :' v_deptno); DBMS_OUTPUT.PUT_LINE ( 'New Salary :' v_sal); DBMS_OUTPUT.PUT_LINE ( 'New Commission :' v_comm); ELSE DBMS_OUTPUT.PUT_LINE ( 'Employee #' p_empno 'not found'); END IF; END; 다음은 절의 emp_insert 프로시저에의해만들어진직원 ID 9503 이아직테이블에 존재한다는것을가정한, 프로시저의출력결과입니다. EXEC emp_comp_update (9503, 6540, 1200); Updated Employee # : 9503 Name : PETERSON Job : ANALYST Department : 40 New Salary : New Commission : 다음예제는레코드형식을이용한 RETURNING INTO 구문을 절의 emp_delete 프로시저에 추가하고수정합니다. CREATE OR REPLACE PROCEDURE emp_delete ( p_empno IN emp.empno % TYPE ) IS r_emp emp % ROWTYPE; BEGIN DELETE FROM emp WHERE empno = p_empno RETURNING * INTO r_emp; 274
275 IF SQL % FOUND THEN DBMS_OUTPUT.PUT_LINE ( 'Deleted Employee # :' r_emp.empno); DBMS_OUTPUT.PUT_LINE ( 'Name :' r_emp.ename); DBMS_OUTPUT.PUT_LINE ( 'Job :' r_emp.job); DBMS_OUTPUT.PUT_LINE ( 'Manager :' r_emp.mgr); DBMS_OUTPUT.PUT_LINE ( 'Hire Date :' r_emp.hiredate); DBMS_OUTPUT.PUT_LINE ( 'Salary :' r_emp.sal); DBMS_OUTPUT.PUT_LINE ( 'Commission :' r_emp.comm); DBMS_OUTPUT.PUT_LINE ( 'Department :' r_emp.deptno); ELSE DBMS_OUTPUT.PUT_LINE ( 'Employee #' p_empno 'not found'); END IF; END; 다음은이프로시저의출력결과입니다. EXEC emp_delete (9503); Deleted Employee # : 9503 Name : PETERSON Job : ANALYST Manager : 7902 Hire Date : 31 - MAR :00:00 Salary : Commission : Department : 결과상태획득 커맨드의효과를확인하기위해사용되는몇가지특성이있습니다. SQL % FOUND 는 INSERT, UPDATE 및 DELETE 커맨드에서적어도 1 개의행이변경되거나 SELECT INTO 커맨드가 1 이상의행이검색되면 true 를반환하는 Boolean 형식입니다. 다음의익명블록은행을삽입하고, 행이삽입된것을볼수있습니다. BEGIN INSERT INTO emp (empno, ename, job, sal, deptno) VALUES ( 9001, 'JONES', 'CLERK', , 40); IF SQL % FOUND THEN DBMS_OUTPUT.PUT_LINE ( 'Row has been inserted'); END IF; END; Row has been inserted SQL % ROWCOUNT 는 INSERT, UPDATE 및 DELETE 커맨드로처리된행의수를제공합니다. 다음 예제는지금삽입된행을업데이트하여 SQL % ROWCOUNT 의값을표시합니다. BEGIN UPDATE emp SET hiredate = '03 - JUN - 07 'WHERE empno = 9001; DBMS_OUTPUT.PUT_LINE ( '# rows updated :' SQL % ROWCOUNT); 275
276 END; # rows updated : 1 SQL % NOTFOUND 는 SQL % FOUND 와반대입니다. 만약 INSERT, UPDATE 및 DELETE 커맨드가 1 행도처리하지않거나 SELECT INTO 커맨드가 1 행도찾을수없다면, SQL % NOTFOUND 는 true 를반환합니다. BEGIN UPDATE emp SET hiredate = '03 - JUN - 07 'WHERE empno = 9000; IF SQL % NOTFOUND THEN DBMS_OUTPUT.PUT_LINE ( 'No rows were updated'); END IF; END; No rows were updated 4.5 제어구조 SPL 의프로그램문장을 SQL 의절차적보완으로만드는것에대해본절에서설명합니다 IF 문장 IF 문장은조건에따라커맨드를실행시킵니다. SPL 은다음과같은 4 개의 IF 형식이 있습니다. : IF... THEN IF... THEN... ELSE IF... THEN... ELSE IF IF... THEN... ELSIF... THEN... ELSE IF - THEN IF boolean - expression THEN statements END IF; IF - THEN 문장은가장간단한 IF 형식입니다. THEN 과 END IF 사이의문장은조건이 true 일 때실행됩니다. 반대의경우, 건너뜁니다. 다음의예제에서 IF-THEN 문장은수수료를가지는직원을표시하고검사하는데사용됩니다. DECLARE v_empno emp.empno % TYPE; v_comm emp.comm % TYPE; CURSOR emp_cursor IS SELECT empno, comm FROM emp; 276
277 BEGIN OPEN emp_cursor; DBMS_OUTPUT.PUT_LINE ( 'EMPNO COMM'); DBMS_OUTPUT.PUT_LINE (' '); LOOP FETCH emp_cursor INTO v_empno, v_comm; EXIT WHEN emp_cursor % NOTFOUND; - - Test whether or not the employee gets a commission - IF v_comm IS NOT NULL AND v_comm> 0 THEN DBMS_OUTPUT.PUT_LINE (v_empno '' TO_CHAR (v_comm, '$ ')); END IF; END LOOP; CLOSE emp_cursor; END; 다음은이프로그램의출력입니다. EMPNO COMM $ $ $ IF - THEN - ELSE IF boolean - expression THEN statements ELSE statements END IF; IF - THEN - ELSE 문장은 IF - THEN 이외조건평가가 false 인경우, 대신하는문장의집합을 지정함으로써 IF-THEN 에 IF-THEN-ELSE 문장을추가할수있습니다. 다음예제는만일직원이수수료를받을수없는경우, IF - THEN - ELSE 구문은 Non - commission 텍스트를볼수있도록변경합니다. DECLARE v_empno emp.empno % TYPE; v_comm emp.comm % TYPE; CURSOR emp_cursor IS SELECT empno, comm FROM emp; BEGIN OPEN emp_cursor; DBMS_OUTPUT.PUT_LINE ( 'EMPNO COMM'); DBMS_OUTPUT.PUT_LINE (' '); LOOP FETCH emp_cursor INTO v_empno, v_comm; 277
278 EXIT WHEN emp_cursor % NOTFOUND; - - Test whether or not the employee gets a commission - IF v_comm IS NOT NULL AND v_comm> 0 THEN DBMS_OUTPUT.PUT_LINE (v_empno '' TO_CHAR (v_comm, '$ ')); ELSE DBMS_OUTPUT.PUT_LINE (v_empno '' 'Non - commission'); END IF; END LOOP; CLOSE emp_cursor; END; 다음은이프로그램의출력입니다. EMPNO COMM Non - commission 7499 $ $ Non - commission 7654 $ Non - commission 7782 Non - commission 7788 Non - commission 7839 Non - commission 7844 Non - commission 7876 Non - commission 7900 Non - commission 7902 Non - commission 7934 Non - commission IF - THEN - ELSE IF IF 문장은대신할 IF 문장을호출하기위해서중첩될수있습니다. 이는외부 IF 문장의조건이 true 인지 false 인지에따라결정됩니다. 다음예제에서는외부 IF - THEN - ELSE 문장은직원이수수료를가지고있는지여부를 테스트합니다. 내부 IF - THEN - ELSE 문은직원의총보상액이회사의평균을초과하는지 여부를테스트합니다. DECLARE v_empno emp.empno % TYPE; v_sal emp.sal % TYPE; v_comm emp.comm % TYPE; v_avg NUMBER (7,2); CURSOR emp_cursor IS SELECT empno, sal, comm FROM emp; BEGIN - - Calculate the average yearly compensation in the company - 278
279 SELECT AVG ((sal + NVL (comm, 0)) * 24) INTO v_avg FROM emp; DBMS_OUTPUT.PUT_LINE ( 'Average Yearly Compensation :' TO_CHAR (v_avg, '$ 999,999.99')); OPEN emp_cursor; DBMS_OUTPUT.PUT_LINE ( 'EMPNO YEARLY COMP'); DBMS_OUTPUT.PUT_LINE (' '); LOOP FETCH emp_cursor INTO v_empno, v_sal, v_comm; EXIT WHEN emp_cursor % NOTFOUND; - - Test whether or not the employee gets a commission - IF v_comm IS NOT NULL AND v_comm> 0 THEN - - Test if the employee 's compensation with commission exceeds the average - IF (v_sal + v_comm) * 24> v_avg THEN DBMS_OUTPUT.PUT_LINE (v_empno '' TO_CHAR ((v_sal + v_comm) * 24 '$ ') 'Exceeds Average'); ELSE DBMS_OUTPUT.PUT_LINE (v_empno '' TO_CHAR ((v_sal + v_comm) * 24 '$ ') 'Below Average'); END IF; ELSE - - Test if the employee 's compensation without commission exceeds the average - IF v_sal * 24> v_avg THEN DBMS_OUTPUT.PUT_LINE (v_empno '' TO_CHAR (v_sal * 24 '$ ') 'Exceeds Average'); ELSE DBMS_OUTPUT.PUT_LINE (v_empno '' TO_CHAR (v_sal * 24 '$ ') 'Below Average'); END IF; END IF; END LOOP; CLOSE emp_cursor; END; 참고 : 이프로그램의논리는커서정의의 SELECT 커맨드내의 NVL 함수를이용하여직원의연간 보상금액을계산함으로써간단해집니다. 그러나이예제의목적은 IF 문장을어떻게쓸 것인가를보여줍니다. 다음은이프로그램의출력입니다. Average Yearly Compensation : $ 53, EMPNO YEARLY COMP $ 19, Below Average 7499 $ 45, Below Average 7521 $ 42, Below Average 7566 $ 71, Exceeds Average 279
280 7654 $ 63, Exceeds Average 7698 $ 68, Exceeds Average 7782 $ 58, Exceeds Average 7788 $ 72, Exceeds Average 7839 $ 120, Exceeds Average 7844 $ 36, Below Average 7876 $ 26, Below Average 7900 $ 22, Below Average 7902 $ 72, Exceeds Average 7934 $ 31, Below Average 이형식을사용하면, 실제로는외부의 IF 문장의 ELSE 부분내에 IF 문을중첩합니다. 따라서 중첩된 IF 와부모 IF-ELSE 를위한 END IF 문장을필요합니다 IF - THEN - ELSIF - ELSE IF boolean - expression THEN statements [ELSIF boolean - expression THEN statements [ELSIF boolean - expression THEN statemen ts]...] [ELSE statements] END IF; IF - THEN - ELSIF - ELSE 은 1 개의문장으로많은후보를확인하는방법을제공합니다. 공식적으로이것은중첩된 IF - THEN - ELSE - IF - THEN 커맨드와같지만, END IF 가필요할때만 입니다. 다음예제는 IF - THEN - ELSIF - ELSE 문장을사용하여보상금 $ 범위에서직원수를 계산합니다. DECLARE v_empno emp.empno % TYPE; v_comp NUMBER (8,2); v_lt_25k SMALLINT : = 0; v_25k_50k SMALLINT : = 0; v_50k_75k SMALLINT : = 0; v_75k_100k SMALLINT : = 0; v_ge_100k SMALLINT : = 0; CURSOR emp_cursor IS SELECT empno (sal + NVL (comm, 0)) * 24 FROM emp; BEGIN OPEN emp_cursor; LOOP FETCH emp_cursor INTO v_empno, v_comp; EXIT WHEN emp_cursor % NOTFOUND; IF v_comp <25000 THEN 280
281 v_lt_25k : = v_lt_25k + 1; ELSIF v_comp <50000 THEN v_25k_50k : = v_25k_50k + 1; ELSIF v_comp <75000 THEN v_50k_75k : = v_50k_75k + 1; ELSIF v_comp < THEN v_75k_100k : = v_75k_100k + 1; ELSE v_ge_100k : = v_ge_100k + 1; END IF; END LOOP; CLOSE emp_cursor; DBMS_OUTPUT.PUT_LINE ( 'Number of employees by yearly compensation'); DBMS_OUTPUT.PUT_LINE ( 'Less than :' v_lt_25k); DBMS_OUTPUT.PUT_LINE (' ,9999 : ' v_25k_50k); DBMS_OUTPUT.PUT_LINE (' ,9999 : ' v_50k_75k); DBMS_OUTPUT.PUT_LINE (' ,9999 : ' v_75k_100k); DBMS_OUTPUT.PUT_LINE (' and over : ' v_ge_100k); END; 다음은이프로그램의출력입니다. Number of employees by yearly compensation Less than 25,000 : 2 25,000-49,9999 : 5 50,000-74,9999 : 6 75,000-99,9999 : 0 100,000 and over : CASE 식 CASE 표현식은표현식내의 CASE 식을대신하는값을반환합니다. CASE 식에는 2 가지형식이있습니다. 하나는검색된 CASE 로불리고, 다른하나는 selector 를 사용합니다 선택 CASE 식 선택 CASE 식은 Selector 로불리는식과 1 개이상의 WHEN 구문이일치되도록시도합니다. result 는 CASE 식이사용된내용에서형식이호환되는식입니다. 만약일치하면, THEN 항목에해당하는값이 CASE 표현식에서반환됩니다. 일치하지않으면 ELSE 에해당하는값을반환합니다. ELSE 가생략되면 CASE 식은 null 을반환합니다. CASE selector - expression WHEN match - expression THEN result [WHEN match - expression THEN result 281
282 [WHEN match - expression THEN result...] [ELSE result ] END; match - expression 은 CASE 식안에서나타난순서로평가됩니다. result 는 CASE 식을실행하는식의내용과동일식입니다. 먼저 match - expression 이 selector - expression 과일치하면, 해당 THEN 절의 result 가 CASE 문장의값으로되돌아갑니다. 만약어떤 match - expression 도 selector - expression 와일치하지않는경우, ELSE 를따르는 result 를반환합니다. ELSE 가지정되지않으면, CASE 식은 null 을반환합니다. 다음은부서번호를기반으로하는변수에부서이름을할당하기위하여선택 CASE 식을 사용하고있습니다. DECLARE v_empno emp.empno % TYPE; v_ename emp.ename % TYPE; v_deptno emp.deptno % TYPE; v_dname dept.dname % TYPE; CURSOR emp_cursor IS SELECT empno, ename, deptno FROM emp; BEGIN OPEN emp_cursor; DBMS_OUTPUT.PUT_LINE ( 'EMPNO ENAME DEPTNO DNAME'); DBMS_OUTPUT.PUT_LINE (' '); LOOP FETCH emp_cursor INTO v_empno, v_ename, v_deptno; EXIT WHEN emp_cursor % NOTFOUND; v_dname : = CASE v_deptno WHEN 10 THEN 'Accounting' WHEN 20 THEN 'Research' WHEN 30 THEN 'Sales' WHEN 40 THEN 'Operations' ELSE 'unknown' END; DBMS_OUTPUT.PUT_LINE (v_empno '' RPAD (v_ename 10) '' v_deptno '' v_dname); END LOOP; CLOSE emp_cursor; END; 다음은이프로그램의출력입니다. EMPNO ENAME DEPTNO DNAME SMITH 20 Research 7499 ALLEN 30 Sales 7521 WARD 30 Sales 7566 JONES 20 Research 282
283 7654 MARTIN 30 Sales 7698 BLAKE 30 Sales 7782 CLARK 10 Accounting 7788 SCOTT 20 Research 7839 KING 10 Accounting 7844 TURNER 30 Sales 7876 ADAMS 20 Research 7900 JAMES 30 Sales 7902 FORD 20 Research 7934 MILLER 10 Accounting 검색 CASE 식 검색 CASE 식은하나이상의 Boolean 식을사용해서리턴되는결과값을결정합니다. CASE WHEN boolean - expression THEN result [WHEN boolean - expression THEN result [WHEN boolean - expression THEN result...] [ELSE result ] END; boolean - expression 은 CASE 식안에서나온순서로평가됩니다. result 는 CASE 식을실행하는식의내용과동일식입니다. 만약첫번째 boolean expression 이 true 가아닐경우, CASE 식의값인해당 THEN 항목의값을 result 에리턴합니다. 만약 boolean-expression 중 true 가없을때는 ELSE 다음의 result 에반환합니다. ELSE 가지정되지않았다면, CASE 문장은 null 을반환합니다. 다음예제는부서번호를기반으로하는변수에부서이름을할당하기위하여검색 CASE 식을 사용하고있습니다. DECLARE v_empno emp.empno % TYPE; v_ename emp.ename % TYPE; v_deptno emp.deptno % TYPE; v_dname dept.dname % TYPE; CURSOR emp_cursor IS SELECT empno, ename, deptno FROM emp; BEGIN OPEN emp_cursor; DBMS_OUTPUT.PUT_LINE ( 'EMPNO ENAME DEPTNO DNAME'); DBMS_OUTPUT.PUT_LINE (' '); LOOP FETCH emp_cursor INTO v_empno, v_ename, v_deptno; EXIT WHEN emp_cursor % NOTFOUND; 283
284 v_dname : = CASE WHEN v_deptno = 10 THEN 'Accounting' WHEN v_deptno = 20 THEN 'Research' WHEN v_deptno = 30 THEN 'Sales' WHEN v_deptno = 40 THEN 'Operations' ELSE 'unknown' END; DBMS_OUTPUT.PUT_LINE (v_empno '' RPAD (v_ename 10) '' v_deptno '' v_dname); END LOOP; CLOSE emp_cursor; END; 다음은이프로그램의출력입니다. EMPNO ENAME DEPTNO DNAME SMITH 20 Research 7499 ALLEN 30 Sales 7521 WARD 30 Sales 7566 JONES 20 Research 7654 MARTIN 30 Sales 7698 BLAKE 30 Sales 7782 CLARK 10 Accounting 7788 SCOTT 20 Research 7839 KING 10 Accounting 7844 TURNER 30 Sales 7876 ADAMS 20 Research 7900 JAMES 30 Sales 7902 FORD 20 Research 7934 MILLER 10 Accounting CASE 문장 CASE 문장은지정된검색조건이 true 일때, 1 개이상의문장을수행합니다. CASE 문장은그 자체가독립적인문장이지만, 전에언급한바와같이 CASE 식은표현식의한부분으로 표현되어야만합니다. CASE 문장에는 2 가지형식이있습니다. 하나는검색 CASE 이고, 다른하나는선택 CASE 입니다 선택 CASE 문장 선택 CASE 문은 1 개이상의 WHEN 항목에지정되는표현식을선택하는것으로, 표현식과일치하도록시도됩니다. 일치하는문장을찾는다면, 하나나그이상의문장이실행됩니다. CASE selector - expression WHEN match - expression THEN 284
285 statements [WHEN match - expression THEN statements [WHEN match - expression THEN statements...] [ELSE statements ] END CASE; selector - expression 은각 match - expression 과같은값을반환합니다. match - expression 은 CASE 문장속에서나타나는순서대로평가됩니다. statements 는 1 개이상의 SPL 프로그램에서각각세미콜론으로종료됩니다. selector - expression 의값이처음으로 match - expression 과일치됐을때, 대응하는 THEN 절문장이실행되고, 계속해서다음 END CASE 키워드에서제어됩니다. 일치하지않을경우, ELSE 을따르는문장이실행됩니다. 일치하는항목이없거나 ELSE 항목이없는경우는예외가발생합니다. 다음예제는부서번호를기반으로하는변수에부서이름과위치를할당하기위하여선택 CASE 문장을사용하고있습니다. DECLARE v_empno emp.empno % TYPE; v_ename emp.ename % TYPE; v_deptno emp.deptno % TYPE; v_dname dept.dname % TYPE; v_loc dept.loc % TYPE; CURSOR emp_cursor IS SELECT empno, ename, deptno FROM emp; BEGIN OPEN emp_cursor; DBMS_OUTPUT.PUT_LINE ( 'EMPNO ENAME DEPTNO DNAME' 'LOC'); DBMS_OUTPUT.PUT_LINE (' ' ' '); LOOP FETCH emp_cursor INTO v_empno, v_ename, v_deptno; EXIT WHEN emp_cursor % NOTFOUND; CASE v_deptno WHEN 10 THEN v_dname : = 'Accounting'; v_loc : = 'New York'; WHEN 20 THEN v_dname : = 'Research'; v_loc : = 'Dallas'; WHEN 30 THEN v_dname : = 'Sales'; v_loc : = 'Chicago'; WHEN 40 THEN v_dname : = 'Operations'; v_loc : = 'Boston'; ELSE v_dname : = 'unknown'; v_loc : = ''; END CASE; DBMS_OUTPUT.PUT_LINE (v_empno '' RPAD (v_ename 10) '' v_deptno '' RPAD (v_dname 14) '' v_loc); END LOOP; 285
286 CLOSE emp_cursor; END; 다음은이프로그램의출력입니다. EMPNO ENAME DEPTNO DNAME LOC SMITH 20 Research Dallas 7499 ALLEN 30 Sales Chicago 7521 WARD 30 Sales Chicago 7566 JONES 20 Research Dallas 7654 MARTIN 30 Sales Chicago 7698 BLAKE 30 Sales Chicago 7782 CLARK 10 Accounting New York 7788 SCOTT 20 Research Dallas 7839 KING 10 Accounting New York 7844 TURNER 30 Sales Chicago 7876 ADAMS 20 Research Dallas 7900 JAMES 30 Sales Chicago 7902 FORD 20 Research Dallas 7934 MILLER 10 Accounting New York 검색 CASE 문장 검색 CASE 문장은하나이상 Boolean 식을실행하고결과집합을얻기문장을 결정하는데사용됩니다. CASE WHEN boolean - expression THEN statements [WHEN boolean - expression THEN statements [WHEN boolean - expression THEN statements...] [ELSE statements] END CASE; boolean - expression 은 CASE 문장에서차례로평가됩니다. 우선처음 boolean expression 이 " true" 일경우, 상응하는 THEN 구문내의문장이실행되고, 계속해서다음 END CASE 키워드에들어갑니다. 만약 boolean - expression 중 "true" 라고평가되는것이없으면, ELSE 을따르는문장이실행됩니다. 만약 boolean - expression 중 "true" 라고평가되는것이없고, ELSE 항목이없는경우는예외가발생합니다. 286
287 다음의예제는부서번호를기반으로하는변수에서부서이름과위치를할당하기위하여검색 CASE 문장을사용하고있습니다. DECLARE v_empno emp.empno % TYPE; v_ename emp.ename % TYPE; v_deptno emp.deptno % TYPE; v_dname dept.dname % TYPE; v_loc dept.loc % TYPE; CURSOR emp_cursor IS SELECT empno, ename, deptno FROM emp; BEGIN OPEN emp_cursor; DBMS_OUTPUT.PUT_LINE ( 'EMPNO ENAME DEPTNO DNAME' 'LOC'); DBMS_OUTPUT.PUT_LINE (' ' ' '); LOOP FETCH emp_cursor INTO v_empno, v_ename, v_deptno; EXIT WHEN emp_cursor % NOTFOUND; CASE WHEN v_deptno = 10 THEN v_dname : = 'Accounting'; v_loc : = 'New York'; WHEN v_deptno = 20 THEN v_dname : = 'Research'; v_loc : = 'Dallas'; WHEN v_deptno = 30 THEN v_dname : = 'Sales'; v_loc : = 'Chicago'; WHEN v_deptno = 40 THEN v_dname : = 'Operations'; v_loc : = 'Boston'; ELSE v_dname : = 'unknown'; v_loc : = ''; END CASE; DBMS_OUTPUT.PUT_LINE (v_empno '' RPAD (v_ename 10) '' v_deptno '' RPAD (v_dname 14) '' v_loc); END LOOP; CLOSE emp_cursor; END; 다음은이프로그램의출력입니다. EMPNO ENAME DEPTNO DNAME LOC SMITH 20 Research Dallas 7499 ALLEN 30 Sales Chicago 7521 WARD 30 Sales Chicago 7566 JONES 20 Research Dallas 7654 MARTIN 30 Sales Chicago 7698 BLAKE 30 Sales Chicago 7782 CLARK 10 Accounting New York 7788 SCOTT 20 Research Dallas 7839 KING 10 Accounting New York 7844 TURNER 30 Sales Chicago 7876 ADAMS 20 Research Dallas 7900 JAMES 30 Sales Chicago 7902 FORD 20 Research Dallas 287
288 7934 MILLER 10 Accounting New York 루프 LOOP, EXIT, CONTINUE, WHILE 와 FOR 문장을사용하여, SPL 프로그램에서일련의커맨드를 반복하도록계획할수있습니다 LOOP LOOP statements END LOOP; LOOP 는 EXIT 나 RETURN 문장에의해종료될때까지무한정반복되는조건없는루프를 정의합니다 EXIT EXIT [WHEN expression ]; 가장안쪽의루프가끝나면, 다음의 END LOOP 문장이실행됩니다. WHEN 이있는경우, 조건이 true 일때만루프종료가발생합니다. 그렇지않으면, EXIT 다음 줄로제어권이넘어갑니다. EXIT 는모든타입의루프로부터빠르게종료되도록사용합니다. 이는조건없는루프에서제한 없이사용할수있습니다. 아래는 10 번반복되는간단한루프의예제입니다. 그후 EXIT 문장을사용해서종료합니다. DECLARE v_counter NUMBER (2); BEGIN v_counter : = 1; LOOP EXIT WHEN v_counter> 10; DBMS_OUTPUT.PUT_LINE ( 'Iteration #' v_counter); v_counter : = v_counter + 1; END LOOP; END; 다음은이프로그램의출력결과입니다. Iteration # 1 Iteration # 2 Iteration # 3 288
289 Iteration # 4 Iteration # 5 Iteration # 6 Iteration # 7 Iteration # 8 Iteration # 9 Iteration # CONTINUE CONTINUE 문은안쪽의문장을생략하고, 바로외부루프를실행하는방법을제공합니다. CONTINUE 문장이실행되면, 가장안쪽루프다음반복이시작되고, 루프가끝날때까지 CONTINUE 문장다음의모든문장을건너뜁니다. 즉, 루프제어식 ( 만일있으면 ) 으로돌아가고, 루프본문은다시실행됩니다. WHEN 이사용되면, WHEN 구문에서지정된식이 true 일때만, 다음루프가시작됩니다. 그와 반대의경우는제어권이 CONTINUE 문장다음으로이동합니다. CONTINUE 는루프밖에서사용되는것은아닙니다. 다음예제는앞의예제를변형한것으로 CONTINUE 문장을사용하여홀수를표시를하지않고 넘어갑니다. DECLARE v_counter NUMBER (2); BEGIN v_counter : = 0; LOOP v_counter : = v_counter + 1; EXIT WHEN v_counter> 10; CONTINUE WHEN MOD (v_counter, 2) = 1; DBMS_OUTPUT.PUT_LINE ( 'Iteration #' v_counter); END LOOP; END; 다음은이프로그램의출력결과입니다. Iteration # 2 Iteration # 4 Iteration # 6 Iteration # 8 Iteration # WHILE 289
290 WHILE expression LOOP statements END LOOP; WHILE 문장은조건표현식이 true 인동안문장전체를반복합니다. 조건은루프본문에 들어가기전에만검사합니다. 다음예제는루프의종료를 EXIT 문장대신, WHILE 문장에서통제하고있다는점을제외하고 동일합니다. 참고 : 조건식은언제루프를종료해야하는지결정을변경해야합니다. EXIT 문장은그 조건식이 true 면루프를종료합니다. WHILE 문장은그조건식이 false 면루프를종료합니다. ( 또는시작되지않습니다.) DECLARE v_counter NUMBER (2); BEGIN v_counter : = 1; WHILE v_counter <= 10 LOOP DBMS_OUTPUT.PUT_LINE ( 'Iteration #' v_counter); v_counter : = v_counter + 1; END LOOP; END; 이예에서는이전예제와같은결과를얻을수있습니다. Iteration # 1 Iteration # 2 Iteration # 3 Iteration # 4 Iteration # 5 Iteration # 6 Iteration # 7 Iteration # 8 Iteration # 9 Iteration # FOR ( 정수 FOR 루프 ) FOR name IN expression.. expression LOOP statements END LOOP; 형식 FOR 는정수값의범위를반복루프하도록만듭니다. name 변수는 INTEGER 형식으로자동으로정의되며루프내부에만존재합니다. 범위를가진 2 개의식은루프에들어갈때한번만계산됩니다. 290
291 반복간격은 +1, name 은왼쪽.. expression 값으로시작하고, name 값이오른쪽.. expression 의 값을초과할경우종료됩니다. 이처럼 2 개의 expression 은다음의규칙을따릅니다. start - value.. end - value 다음은 1 에서 10 까지반복하는 FOR 루프를사용하여 WHILE 루프를보여주는예제입니다. BEGIN FOR i IN LOOP DBMS_OUTPUT.PUT_LINE ( 'Iteration #' i); END LOOP; END; 다음은 FOR 분결과입니다. Iteration # 1 Iteration # 2 Iteration # 3 Iteration # 4 Iteration # 5 Iteration # 6 Iteration # 7 Iteration # 8 Iteration # 9 Iteration # 10 시작하는값이마지막값보다크면루프시스템은전혀작동하지않습니다. 또한다음예제와 같이오류도발생하지않습니다. BEGIN FOR i IN LOOP DBMS_OUTPUT.PUT_LINE ( 'Iteration #' i); END LOOP; END; 이루프는절대실행되지않으며, 출력되지않습니다. 참고 : SPL 은 CURSOR FOR 루프를지원합니다. (4.7.7 절참조 ) 오류처리 기본적으로, SPL 프로그램에서발생한오류는프로그램실행으로중단됩니다. BEGIN 블록과 EXCEPTION 문을사용하면, 오류를포착하여복구할수있습니다. 그구문은일반적인 BEGIN 블록구문을확장합니다. [DECLARE declarations ] 291
292 BEGIN statements EXCEPTION WHEN condition [OR condition... THEN handler_statements [WHEN condition [OR condition]... THEN handler_statements]... END; 오류가발생하지않으면, 이러한형태의블록은간단하게전체 statements 를실행하고, END 다음문장으로제어권이이동됩니다. 그러나 statements 내부오류가발생하면, 향후 statements 의작업이중단되고 EXCEPTIO 리스트로제어가이동합니다. 리스트는발생한오류와일치하는첫번째 condition 을검색합니다. 일치하는것이있으면, 해당 handler_statements 를실행하고, 그런후 END 다음문장으로제어가이동합니다. 일치하는것이없는경우, EXCEPTION 구문이없더라도에러가파급됩니다. EXCEPTION 을포함하는블록은오류를잡을수있지만, 실패하면서브프로그램의처리가중단됩니다. OTHERS 라는특별한조건이름은모든에러형식에부합합니다. 조건이름은대소문자를 구분하지않습니다. 선택된 handler_statements 내부에서새로운에러가발생하면, EXCEPTION 구문은에러를포착할 수없지만오류는외부에파급됩니다. 둘러싼 EXCEPTION 구문은그오류를포착할수있습니다. 다음의테이블은사용될수있는조건이름을열거합니다. Table 4-2 예외조건이름 조건이름 CASE_NOT_FOUND 설명 CASE 문장에 case 문장이없는데 true 가되고, ELSE 조건이 없습니다. CURSOR_ALREADY_OPEN 이미열려있는커서를열려고시도합니다. INVALID_CURSOR 열려있지않은커서에접근하려고합니다. NO_DATA_FOUND 선택표준을만족하는행이없습니다. OTHERS 예외절의이전조건에서발견되지않은예외를잡습니다. TOO_MANY_ROWS 한행만이반환되는선택표준을만족하는행이하나 이상입니다. ZERO_DIVIDE 0 으로나누기를시도합니다. 292
293 4.5.6 어플리케이션에러발생 RAISE_APPLICATION_ERROR 프로시저는 SPL 프로그램에서예외의원인의처리를의도적으로중단시키는기능을제공합니다. 예외는 절에서설명한것과같은방법으로처리됩니다. 또한, RAISE_APPLICATION_ERROR 프로시저는프로그램이예외를확인하기위해사용자정의코드와오류메시지를생성할수있습니다. RAISE_APPLICATION_ERROR (error_number, message); error_number 은정수값이나프로시저의실행될때, SQLCODE 라는이름의변수에반환되는 식입니다. Message 는문자열이나 SQLERRM 라는변수에반환되는식입니다. SQLCODE 과 SQLERRM 변수에대한자세한내용은 4.10 절을참조하십시오. 다음예제는누락된정보에의존하는다른코드와메시지를표시하기위해서직원으로부터 RAISE_APPLICATION_ERROR 프로시저를사용합니다. CREATE OR REPLACE PROCEDURE verify_emp ( p_empno NUMBER ) IS v_ename emp.ename % TYPE; v_job emp.job % TYPE; v_mgr emp.mgr % TYPE; v_hiredate emp.hiredate % TYPE; BEGIN SELECT ename, job, mgr, hiredate INTO v_ename, v_job, v_mgr, v_hiredate FROM emp WHERE empno = p_empno; IF v_ename IS NULL THEN RAISE_APPLICATION_ERROR (20010, 'No name for' p_empno); END IF; IF v_job IS NULL THEN RAISE_APPLICATION_ERROR (20020, 'No job for' p_empno); END IF; IF v_mgr IS NULL THEN RAISE_APPLICATION_ERROR (20030, 'No manager for' p_empno); END IF; IF v_hiredate IS NULL THEN RAISE_APPLICATION_ERROR (20040, 'No hire date for' p_empno); END IF; DBMS_OUTPUT.PUT_LINE ( 'Employee' p_empno 'validated without errors'); EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE ( 'SQLCODE :' SQLCODE); DBMS_OUTPUT.PUT_LINE ( 'SQLERRM :' SQLERRM); END; 293
294 다음은직원레코드로부터관리자번호가없는경우의출력입니다. EXEC verify_emp (7839); SQLCODE : SQLERRM : EDB : No manager for 동적 SQL 동적 SQL 은커맨드가실행될때까지알수없는 SQL 커맨드를실행할수있는기능을제공하는기술입니다. 이전에는 SPL 프로그램에서 SQL 커맨드는정적 SQL 로표시했습니다. 정적 SQL 은전체커맨드 ( 변수의예외를제외하고 ) 로알려져있으며, 프로그램자체가실행을시작하기전, 프로그램코드화되어있습니다. 동적 SQL 을사용하면프로그램이실행중일때실행되는 SQL 을변경할수있습니다. 또한동적 SQL 은 CREATE TABLE 과같이데이터정의커맨드를 SPL 프로그램에서수행하는 유일한방법입니다. 하지만동적 SQL 의작업성능은정적 SQL 에비해느리다는것을주의하십시오. EXECUTE IMMEDIATE 커맨드는 SQL 커맨드를동적으로실행하는데사용됩니다. EXECUTE IMMEDIATE sql_expression; [INTO (variable [...] record)] [USING expression [...] sql_expression 는동적으로실행하는 SQL 커맨드를포함하는문자열식입니다. Variable 은일반적 SELECT 커맨드로부터, sql_expression 의 SQL 커맨드의결과에서생성된결과집합의출력을받습니다. 변수의수, 순서와데이터형식은결과집합필드의수, 순서, 그리고형식호환이일치해야합니다. 그대신에, 레코드는레코드의필드가집합필드의수, 순서와형식호환이일치하는만큼지정할수있습니다. INTO 항목을사용하면반드시 1 개의행이결과집합으로반환되지만, 반대의경우는예외가발생합니다. USING 항목을사용하면, expression 의값을플레이스홀더에전달할수있습니다. 플레이스홀더는변수가사용되는 sql_expression 의 SQL 커맨드안에포함되어나타납니다. 플레이스홀더는콜론 (:) 접두사 - : name 을식별자로나타냅니다. 평가한식의수, 순서, 결과의데이터형식은 sql_expression 플레이스홀더의개수, 순서, 및형식과일치해야만합니다. 플레이스홀더는 SPL 프로그램의어디서나정의되지는않습니다. sql_expression 안에서만나타납니다. 다음예제는문자열에의한기본적인동적 SQL 커맨드를보여줍니다. DECLARE v_sql VARCHAR2 (50); 294
295 BEGIN EXECUTE IMMEDIATE 'CREATE TABLE job (jobno NUMBER (3),' 'jname VARCHAR2 (9))'; v_sql : = 'INSERT INTO job VALUES (100, '' ANALYST '')'; EXECUTE IMMEDIATE v_sql; v_sql : = 'INSERT INTO job VALUES (200, '' CLERK '')'; EXECUTE IMMEDIATE v_sql; END; 다음은 SQL 문자열의 USING 절에서플레이스홀더에값을전달합니다. DECLARE v_sql VARCHAR2 (50) : = 'INSERT INTO job VALUES' '(: p_jobno : p_jname)'; v_jobno job.jobno % TYPE; v_jname job.jname % TYPE; BEGIN v_jobno : = 300; v_jname : = 'MANAGER'; EXECUTE IMMEDIATE v_sql USING v_jobno, v_jname; v_jobno : = 400; v_jname : = 'SALESMAN'; EXECUTE IMMEDIATE v_sql USING v_jobno, v_jname; v_jobno : = 500; v_jname : = 'PRESIDENT'; EXECUTE IMMEDIATE v_sql USING v_jobno, v_jname; END; 다음은 INTO 과 USING 구문을모두보여줍니다. SELECT 커맨드의마지막실행은각변수가아닌 레코드에그결과가반환됩니다. DECLARE v_sql VARCHAR2 (60); v_jobno job.jobno % TYPE; v_jname job.jname % TYPE; r_job job % ROWTYPE; BEGIN DBMS_OUTPUT.PUT_LINE ( 'JOBNO JNAME'); DBMS_OUTPUT.PUT_LINE (' '); v_sql : = 'SELECT jobno, jname FROM job WHERE jobno = : p_jobno'; EXECUTE IMMEDIATE v_sql INTO v_jobno, v_jname USING 100; DBMS_OUTPUT.PUT_LINE (v_jobno '' v_jname); EXECUTE IMMEDIATE v_sql INTO v_jobno, v_jname USING 200; DBMS_OUTPUT.PUT_LINE (v_jobno '' v_jname); EXECUTE IMMEDIATE v_sql INTO v_jobno, v_jname USING 300; DBMS_OUTPUT.PUT_LINE (v_jobno '' v_jname); EXECUTE IMMEDIATE v_sql INTO v_jobno, v_jname USING 400; DBMS_OUTPUT.PUT_LINE (v_jobno '' v_jname); EXECUTE IMMEDIATE v_sql INTO r_job USING 500; DBMS_OUTPUT.PUT_LINE (r_job.jobno '' r_job.jname); END; 다음은위의익명블록으로부터의출력입니다. 295
296 JOBNO JNAME ANALYST 200 CLERK 300 MANAGER 400 SALESMAN 500 PRESIDENT 4.7 정적커서 쿼리전체를수행하는것이아니라쿼리를캡슐화하는커서를설정하고, 쿼리결과를한번에한 행씩읽습니다. 따라서 SPL 프로그램로직결과집합로부터 1 행단위로데이터를읽고해당행 데이터를처리하고, 다음커맨드를처리하는반복가능합니다 커서선언 커서를이용하기위해서는, SPL 프로그램선언영역에서처음으로커서를선언해야합니다. 커서 선언은다음과같습니다. CURSOR name IS query; name 은커서를참조하는데사용하는식별자이며, 그결과는후에프로그램설정됩니다. query 는 SQL SELECT 커맨드에서커서의검색을지정합니다. 참고 : 파라미터를사용해서이구문을확장합니다 절에더자세히설명되어있습니다. 다음은커서선언의같은예입니다. CREATE OR REPLACE PROCEDURE cursor_example IS CURSOR emp_cur_1 IS SELECT * FROM emp; CURSOR emp_cur_2 IS SELECT empno, ename FROM emp; CURSOR emp_cur_3 IS SELECT empno, ename FROM emp WHERE deptno = 10 ORDER BY empno; BEGIN... END; 커서열기 커서를사용하여행을제거하기전에공개되어야만합니다. 이과정은 OPEN 문장을사용합니다. OPEN name; name 은 SPL 프로그램의선언영역에서미리선언된커서의식별자입니다. OPEN 문은이미 열린커서에대해서는실행되지않습니다. 그것은열린그대로존재합니다. 296
297 다음은커서를선언과대응하는 OPEN 문장을나타냅니다. CREATE OR REPLACE PROCEDURE cursor_example IS CURSOR emp_cur_3 IS SELECT empno, ename FROM emp WHERE deptno = 10 ORDER BY empno; BEGIN OPEN emp_cur_3;... END; 커서로부터행가져오기 커서가한번오픈되면, FETCH 문장을사용하여커서의결과로부터행을검색할수있습니다. FETCH name I NTO (record variable [, variable_2...); name 은사전에오픈된커서식별자입니다. record 은사전에정의한레코드 ( 예 : table % ROWTYPE 을사용하는 ) 의식별자입니다. variable, variable_2... 는반입하는행의필드데이터를받는 SPL 변수입니다. record 또는 variable, variable_2... 필드는수와순서가일치해야합니다. 필드는커서정의한검색 SEL ECT 목록을반환합니다. SELECT 목록필드의데이터형식이일치해야하며, record 필드의데이터형식과 variable, variable_2... 데이터형식과명시적으로호환되어야합니다. 참고 : FETCH INTO 에서 BULK COLLECT 항목을사용할경우에는컬렉션에반환된 1 행이상의 결과를반환합니다. FETCH INTO 문장의 BULK COLLECT 항목이용방법에대한자세한내용은 절을참조하십시오. 다음은 FETCH 문장을보여줍니다 CREATE OR REPLACE PROCEDURE cursor_example IS v_empno NUMBER (4); v_ename VARCHAR2 (10); CURSOR emp_cur_3 IS SELECT empno, ename FROM emp WHERE deptno = 10 ORDER BY empno; BEGIN OPEN emp_cur_3; FETCH emp_cur_3 INTO v_empno, v_ename;... END; 대상변수의데이터형식을명시적으로선언하는대신, %TYPE 을사용할수있습니다. 이방법은 만약데이터베이스열이변경되더라도, SPL 프로그램의대상변수선언을변경할필요가 없습니다. % TYPE 은자동으로지정된열의데이터형식을가져옵니다 CREATE OR REPLACE PROCEDURE cursor_example 297
298 IS v_empno emp.empno % TYPE; v_ename emp.ename % TYPE; CURSOR emp_cur_3 IS SELECT empno, ename FROM emp WHERE deptno = 10 ORDER BY empno; BEGIN OPEN emp_cur_3; FETCH emp_cur_3 INTO v_empno, v_ename;... END; 테이블의모든열이테이블에정의된순서대로검색하는경우, FETCH 문장이검색결과에대한 데이터를저장하는레코드를정의하기위하여 % ROWTYPE 을사용할수있습니다. 점표기법을 사용하면레코드의각필드에액세스할수있습니다. CREATE OR REPLACE PROCEDURE cursor_example IS v_emp_rec emp % ROWTYPE; CURSOR emp_cur_1 IS SELECT * FROM emp; BEGIN OPEN emp_cur_1; FETCH emp_cur_1 INTO v_emp_rec; DBMS_OUTPUT.PUT_LINE ( 'Employee Number :' v_emp_rec.empno); DBMS_OUTPUT.PUT_LINE ( 'Employee Name :' v_emp_rec.ename);... END; 커서종료 커서결과집합에서모든필요한열을검색하면, 커서는종료되어야만합니다. 한번닫히면결과 집합에더이상액세스할수없습니다. CLOSE 문장은다음과같습니다. CLOSE name; name 은현재열린커서식별자입니다. 한번커서가닫히면, 다시종료될수없습니다. 그러나커서가한번닫히면, 닫힌커서로다시 OPEN 문장을발행할수있습니다. 그리고그후에새로운쿼리결과집합을검색하기위해 FETCH 문장을사용할수있는쿼리결과세트가작성됩니다. 다음은 CLOSE 문장의사용법을설명합니다. CREATE OR REPLACE PROCEDURE cursor_example IS v_emp_rec emp % ROWTYPE; CURSOR emp_cur_1 IS SELECT * FROM emp; BEGIN OPEN emp_cur_1; FETCH emp_cur_1 INTO v_emp_rec; DBMS_OUTPUT.PUT_LINE ( 'Employee Number :' v_emp_rec.empno); DBMS_OUTPUT.PUT_LINE ( 'Employee Name :' v_emp_rec.ename); 298
299 CLOSE emp_cur_1; END; 이프로시저는실행되면다음과같은출력을생성합니다. 직원 ID 7369 의 SMITH 은결과 집합의첫번째줄입니다. EXEC cursor_example; Employee Number : 7369 Employee Name : SMITH 커서에서 % ROWTYPE 이용 % ROWTYPE 속성을이용하여커서와커서변수에서검색한모든열에해당하는필드가포함된 레코드를정의할수있습니다. 필드는해당열에대한데이터형식을갖습니다. % ROWTYPE 속성은커서이름또는커서변수이름이접두사입니다. record cursor % ROWTYPE; record 는레코드에할당된식별자입니다. cursor 는현재범위안에명시적으로선언된 커서입니다. 다음은어떤직원이어느부서에서일하고있다는정보를얻기위하여 % ROWTYPE 을커서와 함께사용하고있습니다. CREATE OR REPLACE PROCEDURE emp_info IS CURSOR empcur IS SELECT ename, deptno FROM emp; myvar empcur % ROWTYPE; BEGIN OPEN empcur; LOOP FETCH empcur INTO myvar; EXIT WHEN empcur % NOTFOUND; DBMS_OUTPUT.PUT_LINE (myvar.ename 'works in department' myvar.deptno); END LOOP; CLOSE empcur; END; 다음은이프로시저부터의출력입니다. EXEC emp_info; SMITH works in department 20 ALLEN works in department 30 WARD works in department 30 JONES works in department 20 MARTIN works in department
300 BLAKE works in department 30 CLARK works in department 10 SCOTT works in department 20 KING works in department 10 TURNER works in department 30 ADAMS works in department 20 JAMES works in department 30 FORD works in department 20 MILLER works in department 커서속성 각커서는프로그램이커서상태를시험할수있는관련속성집합을가지고있습니다. 이러한 특성은 % ISOPEN, % FOUND, % NOTFOUND 및 % ROWCOUNT 입니다. 이러한특성에대해 다음절에서설명합니다 % ISOPEN 특성 % ISOPEN 속성은커서가오픈되어있는지여부를테스트하는데사용됩니다. cursor_name % ISOPEN cursor_name 은커서이름으로커서가오픈될때, BOOLEAN 데이터형식의 "true" 가리턴됩니다. 그렇지않을경우, "false" 를리턴합니다. 다음은 % ISOPEN 를사용한예입니다. CREATE OR REPLACE PROCEDURE cursor_example IS... CURSOR emp_cur_1 IS SELECT * FROM emp;... BEGIN... IF emp_cur_1 % ISOPEN THEN NULL; ELSE OPEN emp_cur_1; END IF; FETCH emp_cur_1 INTO END; % FOUND % FOUND 속성은지정된커서의결과집합으로부터반환되는행이검색되는지여부를 테스트하는데사용됩니다. 300
301 cursor_name % FOUND cursor_name 는커서이름으로커서가 FETCH 후결과집합에서행이검색되면 BOOLEAN 데이터 형식의 "true" 을반환합니다. 결과집합에서마지막행이 FETCH 되면, 다음 FETCH 에서 % FOUND 는 "false" 을반환합니다. 결과집합행이없으면, 첫번째 FETCH 도 "false" 를반환합니다. 커서가오픈되기전이나닫힌후에 %FOUND 참고는 INVALID_CURSOR 예외가발생합니다. % FOUND 는커서가오픈되나처음 FETCH 전에는 null 을반환합니다. 다음예는 % FOUND 를사용합니다. CREATE OR REPLACE PROCEDURE cursor_example IS v_emp_rec emp % ROWTYPE; CURSOR emp_cur_1 IS SELECT * FROM emp; BEGIN OPEN emp_cur_1; DBMS_OUTPUT.PUT_LINE ( 'EMPNO ENAME'); DBMS_OUTPUT.PUT_LINE (' '); FETCH emp_cur_1 INTO v_emp_rec; WHILE emp_cur_1 % FOUND LOOP DBMS_OUTPUT.PUT_LINE (v_emp_rec.empno '' v_emp_rec.ename); FETCH emp_cur_1 INTO v_emp_rec; END LOOP; CLOSE emp_cur_1; END; 이전프로시저를실행하면결과는다음과같습니다. EXEC cursor_example; EMPNO ENAME SMITH 7499 ALLEN 7521 WARD 7566 JONES 7654 MARTIN 7698 BLAKE 7782 CLARK 7788 SCOTT 7839 KING 7844 TURNER 7876 ADAMS 7900 JAMES 7902 FORD 7934 MILLER 301
302 % NOTFOUND 속성 % NOTFOUND 속성은 % FOUND 와논리적으로반대입니다. cursor_name % NOTFOUND cursor_name 는커서이름으로커서가 FETCH 된후결과집합에서행을검색되면 BOOLEAN 데이터형식의 "false" 을반환합니다. 결과집합의마지막행이 FETCH 되면다음 FETCH 에서 % NOTFOUND 은 "true" 을반환합니다. 결과집합행이없으면첫번째 FETCH 도 "ture" 을반환합니다. 커서가오픈되기전이나닫힌후에 % NOTFOUND 참고하는것은 INVALID_CURSOR 예외가 발생합니다. % NOTFOUND 는커서가오픈되나처음 FETCH 전에는 null 을반환합니다. 다음예는 % NOTFOUND 를사용합니다. CREATE OR REPLACE PROCEDURE cursor_example IS v_emp_rec emp % ROWTYPE; CURSOR emp_cur_1 IS SELECT * FROM emp; BEGIN OPEN emp_cur_1; DBMS_OUTPUT.PUT_LINE ( 'EMPNO ENAME'); DBMS_OUTPUT.PUT_LINE (' '); LOOP FETCH emp_cur_1 INTO v_emp_rec; EXIT WHEN emp_cur_1 % NOTFOUND; DBMS_OUTPUT.PUT_LINE (v_emp_rec.empno '' v_emp_rec.ename); END LOOP; CLOSE emp_cur_1; END; 위의예제뿐아니라이프로시저를실행하면동일한결과를생성합니다. EXEC cursor_example; EMPNO ENAME SMITH 7499 ALLEN 7521 WARD 7566 JONES 7654 MARTIN 7698 BLAKE 7782 CLARK 7788 SCOTT 302
303 7839 KING 7844 TURNER 7876 ADAMS 7900 JAMES 7902 FORD 7934 MILLER % ROWCOUNT % ROWCOUNT 속성은지정된커서에서 FETCH 하는행수를나타내는정수를반환합니다. curs or_name % ROWCOUNT cursor_name 는커서의이름이고, % ROWCOUNT 는위와같이검색하는행수를반환합니다. 마지막행이처리되면커서가종료되기전까지는행수의합계가유지됩니다. 이단계에서 보면 % ROWCOUNT 는 INVALID_CURSOR 예외를던집니다. % ROWCOUNT 참조하는것은커서가오픈되기전과닫힌후에 INVALID_CURSOR 예외가 발생합니다. 커서가열리고처음 FETCH 전에보면 % ROWCOUNT 는 0 을반환합니다. 또한 % ROWCOUNT 는처음부터결과집합에행이없으면첫번째 FETCH 후 0 을반환합니다. 다음예는 % ROWCOUNT 를사용합니다. CREATE OR REPLACE PROCEDURE cursor_example IS v_emp_rec emp % ROWTYPE; CURSOR emp_cur_1 IS SELECT * FROM emp; BEGIN OPEN emp_cur_1; DBMS_OUTPUT.PUT_LINE ( 'EMPNO ENAME'); DBMS_OUTPUT.PUT_LINE (' '); LOOP FETCH emp_cur_1 INTO v_emp_rec; EXIT WHEN emp_cur_1 % NOTFOUND; DBMS_OUTPUT.PUT_LINE (v_emp_rec.empno '' v_emp_rec.ename); END LOOP; DBMS_OUTPUT.PUT_LINE ('**********************'); DBMS_OUTPUT.PUT_LINE (emp_cur_1 % ROWCOUNT 'rows were retrieved'); CLOSE emp_cur_1; END; 이프로시저는직원명부를끝까지검색하고합계를표시합니다. EXEC cursor_example; EMPNO ENAME
304 7369 SMITH 7499 ALLEN 7521 WARD 7566 JONES 7654 MARTIN 7698 BLAKE 7782 CLARK 7788 SCOTT 7839 KING 7844 TURNER 7876 ADAMS 7900 JAMES 7902 FORD 7934 MILLER ********************** 14 rows were retrieved 커서상태와특성요약 다음테이블은커서상태와커서속성에의해반환되는값을요약한것입니다. 표 4-2 커서속성 커서상태 % ISOPEN % FOUND % NOTFOUND % ROWCOUNT 오픈전 False INVALID_CURSOR 예외 INVALID_CURSOR 예외 INVALID_CURSOR 예외 오픈후하고처음 FETCH 이전처음성공했다 FETCH 다음 n 번째성공하는 FETCH 다음 ( 마지막행 ) n +1 번째 FETCH 다음 ( 마지막행다음 ) True Null Null 0 True True False 1 True True False n True False True n 닫힌후에 False INVALID_CURSOR 예외 INVALID_CURSOR 예외 INVALID_CURSOR 예외 커서 FOR 루프 304
305 커서예제와같이, 커서의결과집합을처리하기위해서는커서를여는문장과결과집합의각 행을검색, 결과집합종료테스트, 마지막으로커서를닫는문장을포함하는프로그래밍로직이 필요합니다. 커서 FOR 루프는이러한개별코드문장을배제한루프구문입니다. 커서 FOR 루프는미리선언한커서를오픈하고커서결과집합의모든행을반입하고, 커서를 닫습니다 커서 FOR 루프를생성하는형식은다음과같습니다. FOR record IN cursor LOOP statements END LOOP; record 는정의에명확하게선언된레코드에할당된식별자입니다. cursor % ROWTYPE. cursor 은미리선언된커서의이름입니다. Statements 는 1 개이상의 SPL 문장입니다. 적어도 1 문장이상이필요합니다. 다음은 절예를커서 FOR 루프를사용하여수정한것입니다. CREATE OR REPLACE PROCEDURE cursor_example IS CURSOR emp_cur_1 IS SELECT * FROM emp; BEGIN DBMS_OUTPUT.PUT_LINE ( 'EMPNO ENAME'); DBMS_OUTPUT.PUT_LINE (' '); FOR v_emp_rec IN emp_cur_1 LOOP DBMS_OUTPUT.PUT_LINE (v_emp_rec.empno '' v_emp_rec.ename); END LOOP; END; 다음출력에서보듯이같은결과를얻을수있습니다. EXEC cursor_example; EMPNO ENAME SMITH 7499 ALLEN 7521 WARD 7566 JONES 7654 MARTIN 7698 BLAKE 7782 CLARK 7788 SCOTT 7839 KING 7844 TURNER 7876 ADAMS 305
306 7900 JAMES 7902 FORD 7934 MILLER 매개변수커서 사용자는인자를받아들이는정적커서를선언하고, 커서가오픈되면, 이러한인자값을 전달합니다. 다음예제에서는 emp 테이블의급여가지정된값보다적은직원의이름과급여를 확인하는매개변수커서를선언합니다. DECLARE my_record emp % ROWTYPE; CURSOR c1 (max_wage NUMBER) IS SELECT * FROM emp WHERE sal <max_wage; BEGIN OPEN c1 (2000); LOOP FETCH c1 INTO my_record; EXIT WHEN c1 % NOTFOUND; DBMS_OUTPUT.PUT_LINE ( 'Name =' my_record.ename ', salary =' my_record.sal); END LOOP; CLOSE c1; END; 이경우 max_wage 에게 2000 값을전달하면급여가 2000 이하의모든직원들의이름과급여가 나타납니다. 이쿼리의결과는다음과같습니다. Name = SMITH, salary = Name = ALLEN, salary = Name = WARD, salary = Name = MARTIN, salary = Name = TURNER, salary = Name = ADAMS, salary = Name = JAMES, salary = Name = MILLER, salary = REF 커서와커서변수 이절에서는이전에설명한정적커서보다더유연한또다른커서를제시합니다 REF 커서개요 커서변수는실제검색결과집합에대한포인터를가진커서입니다. 결과집합은커서변수를 사용하는 OPEN FOR 문장의실행에의해결정됩니다. 306
307 커서변수는정적커서와같이하나의특정한쿼리와엮여있지않습니다. 동일한커서변수는 다른쿼리를포함하는 OPEN FOR 문장에여러차례공개됩니다. 매번쿼리로부터새로운결과 집합이생성되고, 커서변수에액세스할수있습니다. REF CURSOR 형식은저장프로시저와함수로부터인자로전달됩니다. 반환형식도 REF CURSOR 형식입니다. 이것은프로그램사이에커서변수를전달하여, 독립된프로그램으로커서작업을 모듈화하도록합니다 커서변수선언 SPL 는내장된데이터형식 SYS_REFCURSOR 과 REF CURSOR 형식을생성하고해당형식의변수를선언하는 2 가지방법으로커서변수선언을지원합니다. SYS_REFCURSOR 는 REF CURSOR 형식이며, 그것에관계하는모든결과집합을제공합니다. 이는 weakly - typed REF CURSOR 라고합니다. 단순한 SYS_REFCURSOR 선언과사용자정의 REF CURSOR 변수와는다릅니다. 여는커서및커서의검색과닫는커서와같은나머지사용법은두커서형식과동일합니다. 이장의나머지부분에서는주로 SYS_REFCURSOR 커서사용예제를다룹니다. 사용자정의 REF CURSOR 를사용하기위해예제를변경하려면선언영역을변경해야합니다. 참고 : Strongly - typed REF CURSOR 는필드의데이터형식이일치되도록선언한수와필드의 순서를필요로하며, 선택적으로결과집합을반환합니다 SYS_REFCURSOR 커서변수선언 다음은 SYS_REFCURSOR 변수를선언하는구문입니다. name SYS_REFCURSOR; name 는커서변수에할당된식별자입니다. 다음은 SYS_REFCURSOR 변수선언의예입니다. DECLARE emp_refcur SYS_REFCURSOR; 사용자정의 REF CURSOR 형변수선언 2 가지선언단계는사용자정의 REF CURSOR 를사용하기위해서수행해야합니다. 참조되는커서 TYPE 을만든다 307
308 TYPE 을바탕으로실제커서변수를선언한다 사용자정의 REF CURSOR 형식을만드는구문은다음과같습니다. TYPE cursor_type_name IS REF CURSOR [RETURN return_type]; 다음은커서변수를선언하는예입니다. DECLARE TYPE emp_cur_type IS REF CURSOR RETURN emp % ROWTYPE; my_rec emp_cur_type; 커서변수열기 한번커서변수가선언되면, 관련되는 SELECT 커맨드를가지고오픈되어야합니다. OPEN FOR 문은결과집합을생성하는데사용되는 SELECT 커맨드를지정합니다. OPEN name FOR query; name 는사전에선언된커서변수의식별자입니다. query 는문장이실행될때, 결과집합을 결정하는 SELECT 커맨드입니다. OPEN FOR 문장이실행되면커서변수의값을결과집합을 확인합니다. 다음예제는선택된부서로부터직원의수와이름의목록을담은결과집합입니다. 변수및 인자는표현식을기술할수있는어디라도 SELECT 커맨드를사용할수있는것에주의하십시요. 이경우, 인자는부서번호를같게하는테스트에사용할수있습니다. CREATE OR REPLACE PROCEDURE emp_by_dept ( p_deptno emp.deptno % TYPE ) IS emp_refcur SYS_REFCURSOR; BEGIN OPEN emp_refcur FOR SELECT empno, ename FROM emp WHERE deptno = p_deptno; 커서변수에서행가져오기 커서변수가오픈되면 FETCH 문을사용하여결과집합에서행을찾습니다. 결과집합에서행을 검색할 FETCH 문장을사용하는방법에대한자세한내용은 를참조하십시오. 다음예제는 FETCH 문장이이전예제에추가되고, 결과집합은 2 개의변수가반환되어 표시됩니다. 커서속성은커서변수와함께정적커서상태를결정하는데이용되고있었습니다. 커서속성에대한자세한내용은 를참조하십시오. CREATE OR REPLACE PROCEDURE emp_by_dept ( 308
309 p_deptno emp.deptno % TYPE ) IS emp_refcur SYS_REFCURSOR; v_empno emp.empno % TYPE; v_ename emp.ename % TYPE; BEGIN OPEN emp_refcur FOR SELECT empno, ename FROM emp WHERE deptno = p_deptno; DBMS_OUTPUT.PUT_LINE ( 'EMPNO ENAME'); DBMS_OUTPUT.PUT_LINE (' '); LOOP FETCH emp_refcur INTO v_empno, v_ename; EXIT WHEN emp_refcur % NOTFOUND; DBMS_OUTPUT.PUT_LINE (v_empno '' v_ename); END LOOP; 커서변수닫기 결과집합을릴리즈하기위해 CLOSE 문장을사용하는방법은 절에설명했습니다. 참고 : 정적커서와달리커서변수는그것을다시오픈하기전에닫을필요가없습니다. 열기 전에결과집합을잃게됩니다. 다음예제는 CLOSE 문장을추가해서완성됐습니다. CREATE OR REPLACE PROCEDURE emp_by_dept ( p_deptno emp.deptno % TYPE ) IS emp_refcur SYS_REFCURSOR; v_empno emp.empno % TYPE; v_ename emp.ename % TYPE; BEGIN OPEN emp_refcur FOR SELECT empno, ename FROM emp WHERE deptno = p_deptno; DBMS_OUTPUT.PUT_LINE ( 'EMPNO ENAME'); DBMS_OUTPUT.PUT_LINE (' '); LOOP FETCH emp_refcur INTO v_empno, v_ename; EXIT WHEN emp_refcur % NOTFOUND; DBMS_OUTPUT.PUT_LINE (v_empno '' v_ename); END LOOP; CLOSE emp_refcur; END; 다음은프로시저를실행할때출력합니다. EXEC emp_by_dept (20) EMPNO ENAME SMITH 309
310 7566 JONES 7788 SCOTT 7876 ADAMS 7902 FORD 제한사용 다음은커서변수를사용할때의제한입니다. 비교연산자는커서변수가동일하거나같지않은지, null 이거나 null 이아닌지를시험하기위해서사용할수없다. 커서변수에는 null 이할당되지않는다. 커서변수의값은데이터베이스열에포함되지않는다. 정적커서와커서변수는교환이불가능합니다. 예를들어, 정적커서는 OPEN FOR 문장에서는사용할수없다. 또한, 다음은프로시저와함수내커서변수작업에서프로시저와함수의인자로서커서변수가 된인자형태를보여줍니다. 표 4-3 된커서변수인자형태 작업 IN IN OUT OUT OPEN No Yes No FETCH Yes Yes No CLOSE Yes Yes No 따라서, 예를들어프로시저의형식인자로선언한커서변수에서 OPEN FOR, FETCH, CLOSE 3 개의모든작업을실행할경우, 해당인자는 IN OUT 형식으로선언되어야합니다 예제 다음은커서변수를사용하는예입니다 함수에서 REF 커서를반환 다음예제에서커서변수는주어진일을가진직원을조회하기위해오픈되어있습니다. 결과 집합을호출하는함수에서사용할수있도록, 커서변수는이함수의 RETURN 문장으로 지정되어있다는것을주의하십시오. CREATE OR REPLACE FUNCTION emp_by_job (p_job VARCHAR2) RETURN SYS_REFCURSOR IS 310
311 emp_refcur SYS_REFCURSOR; BEGIN OPEN emp_refcur FOR SELECT empno, ename FROM emp WHERE job = p_job; RETURN emp_refcur; END; 이함수는함수의호출을익명블록의선언영역에서커서변수에할당한다음익명블록에서 실행됩니다. 결과집합은커서변수를사용하여얻어진다음닫혀집니다. DECLARE v_empno emp.empno % TYPE; v_ename emp.ename % TYPE; v_job emp.job % TYPE : = 'SALESMAN'; v_emp_refcur SYS_REFCURSOR; BEGIN DBMS_OUTPUT.PUT_LINE ( 'EMPLOYEES WITH JOB' v_job); DBMS_OUTPUT.PUT_LINE ( 'EMPNO ENAME'); DBMS_OUTPUT.PUT_LINE (' '); v_emp_refcur : = emp_by_job (v_job); LOOP FETCH v_emp_refcur INTO v_empno, v_ename; EXIT WHEN v_emp_refcur % NOTFOUND; DBMS_OUTPUT.PUT_LINE (v_empno '' v_ename); END LOOP; CLOSE v_emp_refcur; END; 다음은이익명블록을실행한출력입니다. EMPLOYEES WITH JOB SALESMAN EMPNO ENAME ALLEN 7521 WARD 7654 MARTIN 7844 TURNER 커서연산모듈화 다음은커서변수에대한다양한연산을다른프로그램으로모듈화할수있다는것을보여줍니다. 다음과같은경우는주어진종류의모든행을검색하는 SELECT 커맨드로주어진커서변수를 오픈합니다 CREATE OR REPLACE PROCEDURE open_all_emp ( p_emp_refcur IN OUT SYS_REFCURSOR ) IS BEGIN OPEN p_emp_refcur FOR SELECT empno, ename FROM emp; END; 311
312 다음과같은경우는지정된커서변수를주어진부서가아닌모든행을검색하는 SELECT 커맨드로오픈합니다. CREATE OR REPLACE PROCEDURE open_emp_by_dept ( p_emp_refcur IN OUT SYS_REFCURSOR, p_deptno emp.deptno % TYPE ) IS BEGIN OPEN p_emp_refcur FOR SELECT empno, ename FROM emp WHERE deptno = p_deptno; END; 세번째변화는, 다른테이블에서모든행을검색하는 SELECT 커맨드로주어진커서변수를 선보였다. 함수의반환값은열린커서변수라는것을주의하십시오. CREATE OR REPLACE FUNCTION open_dept ( p_dept_refcur IN OUT SYS_REFCURSOR ) RETURN SYS_REFCURSOR IS v_dept_refcur SYS_REFCURSOR; BEGIN v_dept_refcur : = p_dept_refcur; OPEN v_dept_refcur FOR SELECT deptno, dname FROM dept; RETURN v_dept_refcur; END; 이프로시저는직원번호와이름으로구성된커서변수의결과집합을획득하고봅니다. CREATE OR REPLACE PROCEDURE fetch_emp ( p_emp_refcur IN OUT SYS_REFCURSOR ) IS v_empno emp.empno % TYPE; v_ename emp.ename % TYPE; BEGIN DBMS_OUTPUT.PUT_LINE ( 'EMPNO ENAME'); DBMS_OUTPUT.PUT_LINE (' '); LOOP FETCH p_emp_refcur INTO v_empno, v_ename; EXIT WHEN p_emp_refcur % NOTFOUND; DBMS_OUTPUT.PUT_LINE (v_empno '' v_ename); END LOOP; END; 이프로시저는부서번호와이름이저장된커서변수의결과집합을반입하여봅니다 CREATE OR REPLACE PROCEDURE fetch_dept ( p_dept_refcur IN SYS_REFCURSOR ) IS v_deptno dept.deptno % TYPE; v_dname dept.dname % TYPE; 312
313 BEGIN DBMS_OUTPUT.PUT_LINE ( 'DEPT DNAME'); DBMS_OUTPUT.PUT_LINE (' '); LOOP FETCH p_dept_refcur INTO v_deptno, v_dname; EXIT WHEN p_dept_refcur % NOTFOUND; DBMS_OUTPUT.PUT_LINE (v_deptno '' v_dname); END LOOP; END; 이프로시저는주어진커서변수를닫습니다. CREATE OR REPLACE PROCEDURE close_refcur ( p_refcur IN OUT SYS_REFCURSOR ) IS BEGIN CLOSE p_refcur; END; 다음의익명블록은이전에설명된모든프로그램을실행합니다. DECLARE gen_refcur SYS_REFCURSOR; BEGIN DBMS_OUTPUT.PUT_LINE ( 'ALL EMPLOYEES'); open_all_emp (gen_refcur); fetch_emp (gen_refcur); DBMS_OUTPUT.PUT_LINE ('****************'); DBMS_OUTPUT.PUT_LINE ( 'EMPLOYEES IN DEPT # 10'); open_emp_by_dept (gen_refcur, 10); fetch_emp (gen_refcur); DBMS_OUTPUT.PUT_LINE ('****************'); DBMS_OUTPUT.PUT_LINE ( 'DEPARTMENTS'); fetch_dept (open_dept (gen_refcur)); DBMS_OUTPUT.PUT_LINE ('*****************'); close_refcur (gen_refcur); END; 다음은익명블록의출력입니다. ALL EMPLOYEES EMPNO ENAME SMITH 7499 ALLEN 7521 WARD 7566 JONES 7654 MARTIN 7698 BLAKE 313
314 7782 CLARK 7788 SCOTT 7839 KING 7844 TURNER 7876 ADAMS 7900 JAMES 7902 FORD 7934 MILLER **************** EMPLOYEES IN DEPT # 10 EMPNO ENAME CLARK 7839 KING 7934 MILLER **************** DEPARTMENTS DEPT DNAME ACCOUNTING 20 RESEARCH 30 SALES 40 OPERATIONS ***************** REF 커서로동적쿼리 Postgres Plus Advanced Server 은 OPEN FOR USING 문장을통해동적쿼리도지원합니다. 문자열과문자열변수는 OPEN FOR USING 문장의 SELECT 커맨드로제공됩니다. OPEN name FOR dynamic_string [USING bind_arg [, bind_arg_2]...]; name 은미리선언한커서변수의식별자입니다. dynamic_string 는 SELECT 커맨드 ( 세미콜론으로끝나지않음 ) 를포함하는문자열이나문자열변수입니다. bind_arg, bind_arg_2... 는커서변수가오픈되면, SELECT 커맨드변수를플레이스홀더에전달하는데사용되는바인딩인자입니다. 플레이스홀더는콜론을접두사로하는식별자입니다. 다음은문자열을사용한동적쿼리. CREATE OR REPLACE PROCEDURE dept_query IS emp_refcur SYS_REFCURSOR; v_empno emp.empno % TYPE; v_ename emp.ename % TYPE; BEGIN OPEN emp_refcur FOR 'SELECT empno, ename FROM emp WHERE deptno = 30' 'AND sal> = 1500'; DBMS_OUTPUT.PUT_LINE ( 'EMPNO ENAME'); DBMS_OUTPUT.PUT_LINE (' '); LOOP 314
315 FETCH emp_refcur INTO v_empno, v_ename; EXIT WHEN emp_refcur % NOTFOUND; DBMS_OUTPUT.PUT_LINE (v_empno '' v_ename); END LOOP; CLOSE emp_refcur; END; 다음은이프로시저를실행할때의출력입니다. EXEC dept_query; EMPNO ENAME ALLEN 7698 BLAKE 7844 TURNER 다음예제에서는이전쿼리가쿼리매개변수에전달하는바인딩인자를사용하도록수정됩니다. CREATE OR REPLACE PROCEDURE dept_query ( p_deptno emp.deptno % TYPE, p_sal emp.sal % TYPE ) IS emp_refcur SYS_REFCURSOR; v_empno emp.empno % TYPE; v_ename emp.ename % TYPE; BEGIN OPEN emp_refcur FOR 'SELECT empno, ename FROM emp WHERE deptno = : dept' 'AND sal> = : sal'using p_deptno, p_sal; DBMS_OUTPUT.PUT_LINE ( 'EMPNO ENAME'); DBMS_OUTPUT.PUT_LINE (' '); LOOP FETCH emp_refcur INTO v_empno, v_ename; EXIT WHEN emp_refcur % NOTFOUND; DBMS_OUTPUT.PUT_LINE (v_empno '' v_ename); END LOOP; CLOSE emp_refcur; END; 다음은출력결과입니다. EXEC dept_query (30, 1500); EMPNO ENAME ALLEN 7698 BLAKE 7844 TURNER 마지막은 SELECT 를전달하는데가장유연한문자열변수가사용됩니다. CREATE OR REPLACE PROCEDURE dept_query ( 315
316 p_deptno emp.deptno % TYPE, p_sal emp.sal % TYPE ) IS emp_refcur SYS_REFCURSOR; v_empno emp.empno % TYPE; v_ename emp.ename % TYPE; p_query_string VARCHAR2 (100); BEGIN p_query_string : = 'SELECT empno, ename FROM emp WHERE' 'deptno = : dept AND sal> = : sal'; OPEN emp_refcur FOR p_query_string USING p_deptno, p_sal; DBMS_OUTPUT.PUT_LINE ( 'EMPNO ENAME'); DBMS_OUTPUT.PUT_LINE (' '); LOOP FETCH emp_refcur INTO v_empno, v_ename; EXIT WHEN emp_refcur % NOTFOUND; DBMS_OUTPUT.PUT_LINE (v_empno '' v_ename); END LOOP; CLOSE emp_refcur; END; EXEC dept_query (20, 1500); EMPNO ENAME JONES 7788 SCOTT 7902 FORD 4.9 컬렉션 컬렉션은동일한데이터형식의일정한데이터의집합입니다. 일반적으로데이터항목은스칼라 필드입니다. 그러나구조와레코드형식의필드로구성된데이터타입이집합의요소를위해 같은한레코드형식일수도있습니다.. 가장일반적으로알려져있는유형은배열입니다. Postgres Plus Advanced Server 에서지원하는 컬렉션타입은이전에 Oracle 에서 index-by table 로불렸지만, 여기서는 associative array( 연관 배열 ) 이라고합니다 연관배열 연관배열은고유키와값으로구성된컬렉션형식입니다. 일반적으로연관배열에서는키는 숫자일필요없이, 문자열일수있습니다. 연관배열은다음과같은특징을가지고있습니다. 연관배열형식은배열변수가배열형식으로선언된후에정의되어야만한다. 데이터 조작은배열변수에서이루어진다. 316
317 배열을초기화할필요가없다. 바로배열로값이할당된다. 키는 BINARY_INTEGER 이지정되어있을경우, 음수, 양수와 0 이될수있다. 배열요소수의제한은사전에정의되지않는다. 요소가추가될때마다동적으로확장된다. 배열은드문드문있을수있다. 키값의할당에간격이있을수있다. 할당되지않은요소값에대한참조는 SQLCODE 1403, access of uninitialized index 예외가 발생한다. TYPE IS TABLE INDEX BY 문장은연관배열형식의정의에사용됩니다. TYPE assoctype IS TABLE OF (datatype rectype) INDEX BY (BINARY_INTEGER VARCHAR2 (n)); assoctype 은배열형식에할당된식별자입니다. datatype 은 VARCHAR2 나 NUMBER 와같은 스칼라데이터형식입니다. rectype 은미리정의된레코드형식입니다. n 은문자형식키의 최대값입니다. 배열을사용하려면, 변수는배열형식으로선언해야합니다. 다음은배열변수를선언하는 구문입니다. array assoctype array 는관련된배열에대한식별자입니다. assoctype 은미리선언된배열형식의 식별자입니다. 배열요소는다음과같은형식으로참조됩니다. array (n). field] array 는미리선언된배열의식별자입니다. n 은정수입니다. 만약 array 의배열형식을레코드형식으로부터정의할경우,[. field] 가레코드의각각의요소를참조하는데사용됩니다. 여기서 field 는배열형식을정의한레코드형식내에선언되어있습니다. 그대신에, 모든레코드는 [. field] 를생략함으로써참조할수있습니다. 다음은 emp 테이블에서처음 10 명의직원이름을읽고, 배열에저장한다음배열로부터결과를 표시합니다. DECLARE TYPE emp_arr_typ IS TABLE OF VARCHAR2 (10) INDEX BY BINARY_INTEGER; 317
318 emp_arr emp_arr_typ; CURSOR emp_cur IS SELECT ename FROM emp WHERE ROWNUM <= 10; i INTEGER : = 0; BEGIN FOR r_emp IN emp_cur LOOP i : = i + 1; emp_arr (i) : = r_emp.ename; END LOOP; FOR j IN LOOP DBMS_OUTPUT.PUT_LINE (emp_arr (j)); END LOOP; END; 위의예제는다음과같은출력을합니다. SMITH ALLEN WARD JONES MARTIN BLAKE CLARK SCOTT KING TURNER 위의예제를배열정의레코드를사용하도록수정했습니다. DECLARE TYPE emp_rec_typ IS RECORD ( empno NUMBER (4), ename VARCHAR2 (10) ); TYPE emp_arr_typ IS TABLE OF emp_rec_typ INDEX BY BINARY_INTEGER; emp_arr emp_arr_typ; CURSOR emp_cur IS SELECT empno, ename FROM emp WHERE ROWNUM <= 10; i INTEGER : = 0; BEGIN DBMS_OUTPUT.PUT_LINE ( 'EMPNO ENAME'); DBMS_OUTPUT.PUT_LINE (' '); FOR r_emp IN emp_cur LOOP i : = i + 1; emp_arr (i). empno : = r_emp.empno; emp_arr (i). ename : = r_emp.ename; END LOOP; FOR j IN LOOP DBMS_OUTPUT.PUT_LINE (emp_arr (j). empno '' emp_arr (j). ename); END LOOP; END; 다음은이익명블록의출력입니다. EMPNO ENAME 318
319 SMITH 7499 ALLEN 7521 WARD 7566 JONES 7654 MARTIN 7698 BLAKE 7782 CLARK 7788 SCOTT 7839 KING 7844 TURNER emp_rec_typ 레코드형식대신, emp % ROWTYPE 속성을 emp_arr_typ 을정의하는데사용하는 예제입니다. DECLARE TYPE emp_arr_typ IS TABLE OF emp % ROWTYPE INDEX BY BINARY_INTEGER; emp_arr emp_arr_typ; CURSOR emp_cur IS SELECT empno, ename FROM emp WHERE ROWNUM <= 10; i INTEGER : = 0; BEGIN DBMS_OUTPUT.PUT_LINE ( 'EMPNO ENAME'); DBMS_OUTPUT.PUT_LINE (' '); FOR r_emp IN emp_cur LOOP i : = i + 1; emp_arr (i). empno : = r_emp.empno; emp_arr (i). ename : = r_emp.ename; END LOOP; FOR j IN LOOP DBMS_OUTPUT.PUT_LINE (emp_arr (j). empno '' emp_arr (j). ename); END LOOP; END; 결과는앞의예제와동일합니다. 레코드의각필드를별도로할당하는대신, r_emp 에서 emp_arr 로레코드단계지정이 가능합니다. DECLARE TYPE emp_rec_typ IS RECORD ( empno NUMBER (4), ename VARCHAR2 (10) ); TYPE emp_arr_typ IS TABLE OF emp_rec_typ INDEX BY BINARY_INTEGER; emp_arr emp_arr_typ; CURSOR emp_cur IS SELECT empno, ename FROM emp WHERE ROWNUM <= 10; i INTEGER : = 0; BEGIN DBMS_OUTPUT.PUT_LINE ( 'EMPNO ENAME'); DBMS_OUTPUT.PUT_LINE (' '); FOR r_emp IN emp_cur LOOP i : = i + 1; emp_arr (i) : = r_emp; 319
320 END LOOP; FOR j IN LOOP DBMS_OUTPUT.PUT_LINE (emp_arr (j). empno '' emp_arr (j). ename); END LOOP; END; 다음예제와같이배열의키는문자열데이터일수있습니다. DECLARE TYPE job_arr_typ IS TABLE OF NUMBER INDEX BY VARCHAR2 (9); job_arr job_arr_typ; BEGIN job_arr ( 'ANALYST') : = 100; job_arr ( 'CLERK') : = 200; job_arr ( 'MANAGER') : = 300; job_arr ( 'SALESMAN') : = 400; job_arr ( 'PRESIDENT') : = 500; DBMS_OUTPUT.PUT_LINE ( 'ANALYST :' job_arr ( 'ANALYST')); DBMS_OUTPUT.PUT_LINE ( 'CLERK :' job_arr ( 'CLERK')); DBMS_OUTPUT.PUT_LINE ( 'MANAGER :' job_arr ( 'MANAGER')); DBMS_OUTPUT.PUT_LINE ( 'SALESMAN :' job_arr ( 'SALESMAN')); DBMS_OUTPUT.PUT_LINE ( 'PRESIDENT :' job_arr ( 'PRESIDENT')); END; ANALYST : 100 CLERK : 200 MANAGER : 300 SALESMAN : 400 PRESIDENT : Collection Methods Collection methods 은컬렉션의데이터처리에편리하고, 컬렉션에대한유용한정보를제공하는 함수입니다. 다음영역에서는이들도방법을설명합니다 COUNT COUNT 는컬렉션의요소수를반환하는메소드입니다. COUNT 를사용하기위한구문은다음과 같습니다. collection. COUNT collection is the identifier of a collection variable. collection 은컬렉션변수의식별자입니다. 다음예제에서배열은간격을두고배치됩니다. ( 예를들면, 정의된요소의순서대로 " 간격 " 이 있습니다.) COUNT 는값이주어진요소에만이용할수있습니다. 320
321 DECLARE TYPE sparse_arr_typ IS TABLE OF NUMBER INDEX BY BINARY_INTEGER; sparse_arr sparse_arr_typ; BEGIN sparse_arr (-100) = -100; sparse_arr (-10) = -10; sparse_arr (0) : = 0; sparse_arr (10) : = 10; sparse_arr (100) = 100; DBMS_OUTPUT.PUT_LINE ( 'COUNT :' sparse_arr.count); END; 다음출력은 COUNT 에는 5 가지의요소가포함되어있다는것을보여줍니다. COUNT : FIRST FIRST 는컬렉션의첫번째요소의인덱스를반환하는메소드입니다. FIRST 를사용하는구문은 다음과같습니다. collection. FIRST collection 은컬렉션변수의식별자입니다. 다음은배열의첫번째요소를표시합니다. DECLARE TYPE sparse_arr_typ IS TABLE OF NUMBER INDEX BY BINARY_INTEGER; sparse_arr sparse_arr_typ; BEGIN sparse_arr (-100) = -100; sparse_arr (-10) = -10; sparse_arr (0) : = 0; sparse_arr (10) : = 10; sparse_arr (100) = 100; DBMS_OUTPUT.PUT_LINE ( 'FIRST element :' sparse_arr (sparse_arr.first)); END; FIRST element : LAST LAST 는컬렉션의마지막요소의인덱스를반환하는메소드입니다. LAST 를사용하는형식은 다음과같습니다. collection. LAST collection 은컬렉션변수의식별자입니다. 321
322 다음은배열의마지막요소를표시합니다. DECLARE TYPE sparse_arr_typ IS TABLE OF NUMBER INDEX BY BINARY_INTEGER; sparse_arr sparse_arr_typ; BEGIN sparse_arr (-100) = -100; sparse_arr (-10) = -10; sparse_arr (0) : = 0; sparse_arr (10) : = 10; sparse_arr (100) = 100; DBMS_OUTPUT.PUT_LINE ( 'LAST element :' sparse_arr (sparse_arr.last)); END; LAST element : FORALL 문장사용 컬렉션은 DELETE, INSERT 또는 UPDATE 커맨드를각각새값으로 DML 커맨드를실행하는것보다, 반복적으로수행하는모든값을한번에데이터베이스서버에전달하여 DML 커맨드를실행하기위해좀더효율적으로이용할수있습니다. DML 커맨드는 FORALL 문장에서지정한방법으로실행됩니다. 또한하나이상의컬렉션은커맨드를실행할때마다다른값을할당하고, DML 커맨드에전달합니다. FORALL index IN lower_bound.. upper_bound (ins ert update delete); Index 는컬렉션의새위치에서 lower_bound 에서 upper_bound 까지정수값으로 insert, update, delete DML 커맨드를반복합니다. 참고 : FORALL 문장반복하는동안예외가발생할경우, FORALL 문장실행으로시작한모든업데이트가자동으로롤백이됩니다. 이작업은 Oracle 과호환되지않습니다. Oracle 에서는예외가발생하기전, 업데이트를처리하거나롤백하는방법을제어하기위해 COMMIT 또는 ROLLBACK 커맨드를명시적으로사용하도록허용합니다. 다음은 FORALL 문으로 emp 테이블에 3 명의새로운직원을삽입하는 INSERT 커맨드사용 예제입니다. DECLARE TYPE empno_tbl IS TABLE OF emp.empno % TYPE INDEX BY BINARY_INTEGER; TYPE ename_tbl IS TABLE OF emp.ename % TYPE INDEX BY BINARY_INTEGER; TYPE job_tbl IS TABLE OF emp.ename % TYPE INDEX BY BINARY_INTEGER; TYPE sal_tbl IS TABLE OF emp.ename % TYPE INDEX BY BINARY_INTEGER; TYPE deptno_tbl IS TABLE OF emp.deptno % TYPE INDEX BY BINARY_INTEGER; t_empno EMPNO_TBL; t_ename ENAME_TBL; t_job JOB_TBL; 322
323 t_sal SAL_TBL; t_deptno DEPTNO_TBL; BEGIN t_empno (1) : = 9001; t_ename (1) : = 'JONES'; t_job (1) : = 'ANALYST'; t_sal (1) = ; t_deptno (1) : = 40; t_empno (2) : = 9002; t_ename (2) : = 'LARSEN'; t_job (2) : = 'CLERK'; t_sal (2) = ; t_deptno (2) : = 40; t_empno (3) : = 9003; t_ename (3) : = 'WILSON'; t_job (3) : = 'MANAGER'; t_sal (3) : = ; t_deptno (3) : = 40; FORALL i IN t_empno.first.. t_empno.last INSERT INTO emp (empno, ename, job, sal, deptno) VALUES (t_empno (i), t_ename (i), t_job (i), t_sal (i), t_deptno (i)); END; SELECT * FROM emp WHERE empno> 9000; empno ename job mgr hiredate sal comm deptno JONES ANALYST LARSEN CLERK WILSON MANAGER (3 rows) 다음은 FORALL 문장에서이 3 명의급여를갱신하고있습니다. DECLARE TYPE empno_tbl IS TABLE OF emp.empno % TYPE INDEX BY BINARY_INTEGER; TYPE sal_tbl IS TABLE OF emp.ename % TYPE INDEX BY BINARY_INTEGER; t_empno EMPNO_TBL; t_sal SAL_TBL; BEGIN t_empno (1) : = 9001; t_sal (1) = ; t_empno (2) : = 9002; t_sal (2) = ; t_empno (3) : = 9003; t_sal (3) : = ; FORALL i IN t_empno.first.. t_empno.last UPDATE emp SET sal = t_sal (i) WHERE empno = t_empno (i); END; SELECT * FROM emp WHERE empno> 9000; empno ename job mgr hiredate sal comm deptno JONES ANALYST
324 9002 LARSEN CLERK WILSON MANAGER (3 rows) 마지막예제는 FORALL 문장에서이들 3 명의직원을제거합니다. DECLARE TYPE empno_tbl IS TABLE OF emp.empno % TYPE INDEX BY BINARY_INTEGER; t_empno EMPNO_TBL; BEGIN t_empno (1) : = 9001; t_empno (2) : = 9002; t_empno (3) : = 9003; FORALL i IN t_empno.first.. t_empno.last DELETE FROM emp WHERE empno = t_empno (i); END; SELECT * FROM emp WHERE empno> 9000; empno ename job mgr hiredate sal comm deptno (0 rows) BULK COLLECT 구문사용 많은행으로구성된결과집합을반환하는 SQL 커맨드는효율적으로실행할수없습니다. 왜냐하면모든결과집합을데이터베이스서버와클라이언트사이에전송하기위해특정컨텍스트교환이발생하기때문입니다. 이러한비효율성은클라이언트가접근할수있는메모리에모든결과집합을모으는컬렉션을통해경감시킬수있습니다. BULK COLLECT 구문은컬렉션에결과집합을모으는것을지정하는데사용됩니다. BULK COLLEC 절은 SELECT INTO 및 FETCH INTO 커맨드와 DELETE, INSERT, UPDATE 커맨드의 RETURNING INTO 구문과함께사용됩니다. 각각다음절에서설명됩니다 SELECT BULK COLLECT BULK COLLECT 절은 SELECT INTO 문장과함께다음과같이사용됩니다. (SELECT INTO 문장에 대한자세한내용은 절을참조하십시오.) SELECT select_expressions BULK COLLECT INTO collection [...] FROM...; 만약 1 개의컬렉션이지정되어있으면, collection 은하나의필드컬렉션또는레코드형식의컬렉션입니다. 만약 1 개이상의컬렉션이지정되어있으면, 각 collection 은하나의필드로구성되어있어야만합니다. select_expressions 는목표커넥션에모든필드의형식호환성, 수량, 순서가일치해야합니다. 324
325 다음은원하는컬렉션이하나의필드로구성되는연관배열인 BULK COLLECT 구문의사용 방법을보여줍니다. DECLARE TYPE empno_tbl IS TABLE OF emp.empno % TYPE INDEX BY BINARY_INTEGER; TYPE ename_tbl IS TABLE OF emp.ename % TYPE INDEX BY BINARY_INTEGER; TYPE job_tbl IS TABLE OF emp.job % TYPE INDEX BY BINARY_INTEGER; TYPE hiredate_tbl IS TABLE OF emp.hiredate % TYPE INDEX BY BINARY_INTEGER; TYPE sal_tbl IS TABLE OF emp.sal % TYPE INDEX BY BINARY_INTEGER; TYPE comm_tbl IS TABLE OF emp.comm % TYPE INDEX BY BINARY_INTEGER; TYPE deptno_tbl IS TABLE OF emp.deptno % TYPE INDEX BY BINARY_INTEGER; t_empno EMPNO_TBL; t_ename ENAME_TBL; t_job JOB_TBL; t_hiredate HIREDATE_TBL; t_sal SAL_TBL; t_comm COMM_TBL; t_deptno DEPTNO_TBL; BEGIN SELECT empno, ename, job, hiredate, sal, comm, deptno BULK COLLECT INTO t_empno, t_ename, t_job, t_hiredate, t_sal, t_comm, t_deptno FROM emp; DBMS_OUTPUT.PUT_LINE ( 'EMPNO ENAME JOB HIREDATE' 'SAL' 'COMM DEPTNO'); DBMS_OUTPUT.PUT_LINE (' ' ' ' ' '); FOR i IN 1.. t_empno.count LOOP DBMS_OUTPUT.PUT_LINE (t_empno (i) '' RPAD (t_ename (i), 8) '' RPAD (t_job (i), 10) '' TO_CHAR (t_hiredate (i), 'DD - MON - YY') '' TO_CHAR (t_sal (i), ' ') ' ' TO_CHAR (NVL (t_comm (i), 0), ' ') ' ' t_deptno (i)); END LOOP; END; EMPNO ENAME JOB HIREDATE SAL COMM DEPTNO SMITH CLERK 17 - DEC ALLEN SALESMAN 20 - FEB WARD SALESMAN 22 - FEB JONES MANAGER 02 - APR MARTIN SALESMAN 28 - SEP BLAKE MANAGER 01 - MAY CLARK MANAGER 09 - JUN SCOTT ANALYST 19 - APR KING PRESIDENT 17 - NOV TURNER SALESMAN 08 - SEP ADAMS CLERK 23 - MAY JAMES CLERK 03 - DEC FORD ANALYST 03 - DEC MILLER CLERK 23 - JAN
326 다음은동일한결과를제공합니다. 그러나레코드형식의정의 % ROWTYPE 속성을사용한연관 배열을사용합니다. DECLARE TYPE emp_tbl IS TABLE OF emp % ROWTYPE INDEX BY BINARY_INTEGER; t_emp EMP_TBL; BEGIN SELECT * BULK COLLECT INTO t_emp FROM emp; DBMS_OUTPUT.PUT_LINE ( 'EMPNO ENAME JOB HIREDATE' 'SAL' 'COMM DEPTNO'); DBMS_OUTPUT.PUT_LINE (' ' ' ' ' '); FOR i IN 1.. t_emp.count LOOP DBMS_OUTPUT.PUT_LINE (t_emp (i). empno '' RPAD (t_emp (i). ename, 8) '' RPAD (t_emp (i). job, 10) '' TO_CHAR (t_emp (i). hiredate, 'DD - MON - YY') '' TO_CHAR (t_emp (i). sal, ' ') ' ' TO_CHAR (NVL (t_emp (i). comm, 0), ' ') ' ' t_emp (i). deptno); END LOOP; END; EMPNO ENAME JOB HIREDATE SAL COMM DEPTNO SMITH CLERK 17 - DEC ALLEN SALESMAN 20 - FEB WARD SALESMAN 22 - FEB JONES MANAGER 02 - APR MARTIN SALESMAN 28 - SEP BLAKE MANAGER 01 - MAY CLARK MANAGER 09 - JUN SCOTT ANALYST 19 - APR KING PRESIDENT 17 - NOV TURNER SALESMAN 08 - SEP ADAMS CLERK 23 - MAY JAMES CLERK 03 - DEC FORD ANALYST 03 - DEC MILLER CLERK 23 - JAN FETCH BULK COLLECT BULK COLLECT 절은 FETCH 문장과함께사용할수있습니다. (FETCH 문장에대한자세한내용은 절을참조하십시오.) 한번에하나의행을결과집합에서반환하는대신, FETCH BULK COLLECT 은 LIMIT 절제약이아니라면, 결과집합에서즉시모든행을지정된컬렉션으로반환합니다. FETCH name BULK COLLECT INTO collection [...] [LIMIT n]; 만일하나의컬렉션이지정된경우, collection 은하나의필드거나레코드형식의컬렉션입니다. 만약 1 개이상의컬렉션이지정되면, 각 collection 은하나의필드로구성되어야합니다. name 326
327 에지정된커서 SELECT 목록의표현식은목표의컬렉션의모든필드의형식호환성과수량, 순서가일치해야합니다. 만약 LIMIT n 가지정되면, 각 FETCH 를실행하여컬렉션에반환되는 행의수는 n 을초과할수없습니다. 다음은배열로행을회수하는데 FETCH BULK COLLECT 문장을사용하고있습니다. DECLARE TYPE emp_tbl IS TABLE OF emp % ROWTYPE INDEX BY BINARY_INTEGER; t_emp EMP_TBL; CURSOR emp_cur IS SELECT * FROM emp; BEGIN OPEN emp_cur; FETCH emp_cur BULK COLLECT INTO t_emp; CLOSE emp_cur; DBMS_OUTPUT.PUT_LINE ( 'EMPNO ENAME JOB HIREDATE' 'SAL' 'COMM DEPTNO'); DBMS_OUTPUT.PUT_LINE (' ' ' ' ' '); FOR i IN 1.. t_emp.count LOOP DBMS_OUTPUT.PUT_LINE (t_emp (i). empno '' RPAD (t_emp (i). ename, 8) '' RPAD (t_emp (i). job, 10) '' TO_CHAR (t_emp (i). hiredate, 'DD - MON - YY') '' TO_CHAR (t_emp (i). sal, ' ') ' ' TO_CHAR (NVL (t_emp (i). comm, 0), ' ') ' ' t_emp (i). deptno); END LOOP; END; EMPNO ENAME JOB HIREDATE SAL COMM DEPTNO SMITH CLERK 17 - DEC ALLEN SALESMAN 20 - FEB WARD SALESMAN 22 - FEB JONES MANAGER 02 - APR MARTIN SALESMAN 28 - SEP BLAKE MANAGER 01 - MAY CLARK MANAGER 09 - JUN SCOTT ANALYST 19 - APR KING PRESIDENT 17 - NOV TURNER SALESMAN 08 - SEP ADAMS CLERK 23 - MAY JAMES CLERK 03 - DEC FORD ANALYST 03 - DEC MILLER CLERK 23 - JAN RETURNING BULK COLLEC T BULK COLLECT 절을 DELETE, INSERT, UPDATE 커맨드의 RETURNING INTO 구문에추가할수 있습니다. (RETURNING INTO 항목에대한자세한내용은 절을참조하십시오.) (insert update delete) 327
328 RETURNING (* expr_1 [, expr_2]...) BULK COLLECT INTO collection [...]; Insert, update, delete 는각각 INSERT, UPDATE, DELETE 커맨드이며, 4.4.4, 4.4.5, 절에서설명하고있습니다. 만약 1 개의컬렉션이지정된경우, collection 은단일필드로구성된레코드형식의컬렉션입니다. 만약하나이상의컬렉션이지정되면, 각 collection 은하나의필드로구성되어있어야합니다. RETURNING 키워드를따르는표현식은대상컬렉션의모든필드의형식호환성과수량, 순서가동일해야합니다. 만약 * 가지정되면, 영향받는테이블의모든열이반환됩니다. (* 의이용은 Postgres Plus Advanced Server 확장으로서 Oracle 과호환되지않습니다.) emp 테이블을복사하여만든 clerkemp 테이블은다음절의예제에서사용됩니다. CREATE TABLE clerkemp AS SELECT * FROM emp WHERE job = 'CLERK'; SELECT * FROM clerkemp; empno ename job mgr hiredate sal comm deptno SMITH CLERK DEC :00: ADAMS CLERK MAY :00: JAMES CLERK DEC :00: MILLER CLERK JAN :00: (4 rows) 다음은전체의급여를 1.5 로나누고, 직원번호와이름, 새로운급여를연관배열에저장하며 마지막으로배열의내용을표시합니다. DECLARE TYPE empno_tbl IS TABLE OF emp.empno % TYPE INDEX BY BINARY_INTEGER; TYPE ename_tbl IS TABLE OF emp.ename % TYPE INDEX BY BINARY_INTEGER; TYPE sal_tbl IS TABLE OF emp.sal % TYPE INDEX BY BINARY_INTEGER; t_empno EMPNO_TBL; t_ename ENAME_TBL; t_sal SAL_TBL; BEGIN UPDATE clerkemp SET sal = sal * 1.5 RETURNING empno, ename, sal BULK COLLECT INTO t_empno, t_ename, t_sal; DBMS_OUTPUT.PUT_LINE ( 'EMPNO ENAME SAL'); DBMS_OUTPUT.PUT_LINE (' '); FOR i IN 1.. t_empno.count LOOP DBMS_OUTPUT.PUT_LINE (t_empno (i) '' RPAD (t_ename (i), 8) '' TO_CHAR (t_sal (i), ' ')); END LOOP; END; EMPNO ENAME SAL SMITH 1,
329 7876 ADAMS 1, JAMES 1, MILLER 1, 다음은이전예제와같은기능을제공하지만, 직원번호와이름, 새로운급여를저장하는레코드 형식을가진정의된컬렉션을사용합니다. DECLARE TYPE emp_rec IS RECORD ( empno emp.empno % TYPE, ename emp.ename % TYPE, sal emp.sal % TYPE ); TYPE emp_tbl IS TABLE OF emp_rec INDEX BY BINARY_INTEGER; t_emp EMP_TBL; BEGIN UPDATE clerkemp SET sal = sal * 1.5 RETURNING empno, ename, sal BULK COLLECT INTO t_emp; DBMS_OUTPUT.PUT_LINE ( 'EMPNO ENAME SAL'); DBMS_OUTPUT.PUT_LINE (' '); FOR i IN 1.. t_emp.count LOOP DBMS_OUTPUT.PUT_LINE (t_emp (i). empno '' RPAD (t_emp (i). ename, 8) '' TO_CHAR (t_emp (i). sal, '99, ')); END LOOP; END; EMPNO ENAME SAL SMITH 1, ADAMS 1, JAMES 1, MILLER 1, 다음은 clerkemp 테이블에서모든행을삭제하고, 배열로삭제된행정보를반환하고표시합니다. DECLARE TYPE emp_rec IS RECORD ( empno emp.empno % TYPE, ename emp.ename % TYPE, job emp.job % TYPE, hiredate emp.hiredate % TYPE, sal emp.sal % TYPE, comm emp.comm % TYPE, deptno emp.deptno % TYPE ); TYPE emp_tbl IS TABLE OF emp_rec INDEX BY BINARY_INTEGER; r_emp EMP_TBL; BEGIN DELETE FROM clerkemp RETURNING empno, ename, job, hiredate, sal, comm, deptno BULK COLLECT INTO r_emp; DBMS_OUTPUT.PUT_LINE ( 'EMPNO ENAME JOB HIREDATE' 'SAL' 'COMM DEPTNO'); DBMS_OUTPUT.PUT_LINE (' ' 329
330 ' ' ' '); FOR i IN 1.. r_emp.count LOOP DBMS_OUTPUT.PUT_LINE (r_emp (i). empno '' RPAD (r_emp (i). ename, 8) '' RPAD (r_emp (i). job, 10) '' TO_CHAR (r_emp (i). hiredate, 'DD - MON - YY') '' TO_CHAR (r_emp (i). sal, ' ') ' ' TO_CHAR (NVL (r_emp (i). comm, 0), ' ') ' ' r_emp (i). deptno); END LOOP; END; EMPNO ENAME JOB HIREDATE SAL COMM DEPTNO SMITH CLERK 17 - DEC ADAMS CLERK 23 - MAY JAMES CLERK 03 - DEC MILLER CLERK 23 - JAN 에러메시지 메시지를출력하기위해서는 DBMS_OUTPUT.PUT_LINE 문장을사용합니다. DBMS_OUTPUT.PUT_LINE (message); Message 는문자열로평가되는식입니다. 이예제는사용자의출력화면에메시지가나타납니다. DBMS_OUTPUT.PUT_LINE ( 'My name is John'); 특별한변수 SQLCODE 과 SQLERRM 은각각숫자코드와문자메시지를가지고있습니다. 그것은마지막으로실행된 SQL 커맨드를실행합니다. 만약프로그램에서 0 으로나누기와같은 다른에러가발생하면, 이변수는에러에대한정보를갖게됩니다. 제 5 장트리거 이장에서는 Postgres Plus Advanced Server 에있는트리거를설명합니다. 프로시저와함수와마 찬가지로트리거는 SPL 언어입니다. 5.1 개요 330
331 트리거는이름이부여되고, 결합된테이블과관련된데이터베이스에저장된 SPL 코드블록입니다. 이벤트가테이블에발생하면 SPL 코드블록이실행됩니다. 트리거는코드블록이실행되면 시작됩니다. 트리거를시작하는이벤트는직접또는간접적인삽입, 업데이트및복원어떤조합에도테이블에대해실행되는경우발생합니다. 테이블이 SQL INSERT, UPDATE, DELETE 명령의대상이면해당인서트, 업데이트및복원이벤트를트리거이벤트로정의하면, 트리거를직접시작할수있습니다. 트리거를시작하는이벤트는 CREATE TRIGGER 명령으로정의합니다. 다른테이블에서이벤트가시작된것은트리거이벤트가발생하면트리거는간접적으로시작할수있습니다. 예를들면, ON DELETE CASCADE 조항에정의된외부키가있는테이블에트리거가정의되면부모테이블의행이삭제되면부모테이블의모든자식테이블만큼삭제됩니다. 삭제가자식테이블의트리거이벤트라면자식테이블의삭제는트리거를시작합니다. 5.2 트리거의유형 Postgres Plus Advanced Server 는 row-level 와 statement-level 트리거를지원하고있습니다. rowlevel 트리거는트리거이벤트에따라영향을받는각라인마다한번발행합니다. 예를들면, 삭제가테이블의트리거이벤트로정의되고테이블에서 5 행삭제단일 DELETE 명령이실행되면, 트리거는각라인마다한번, 총 5 회시작합니다. 대조적으로, statement-level 는트리거이벤트에영향을받은행의개수에상관없이트리거 명령문마다한번시작합니다. 하나의 DELETE 명령 5 행삭제위의예에서는문을트리거는한 번만시작합니다. 그것이명령문수준트리거의경우트리거코드블록을트리거성명에서 " 전 " 또는 " 다음 " 을, row-level 트리거의경우트리거명령문에영향을받는각행의 " 이전 " 또는 " 후 " 실행여부에 대한일련의동작을정의할수있습니다. Row-level 전트리거는각영향을받는줄에트리거동작이이루어지기전에트리거코드블록이 실행됩니다. 문수준이전트리거는트리거문이열리는동작전에트리거코드블록이 실행됩니다. 이후 row-level 유발, 각영향을받는줄에트리거동작이일어난다후트리거코드블록이 실행됩니다. 문수준다음트리거는트리거문이열리는동작후에트리거코드블록이 실행됩니다. 5.3 트리거발생 331
332 CREATE TRIGGER 명령은데이터베이스에저장된트리거의정의및명령입니다. CREATE [OR REPLACE] TRIGGER name (BEFORE AFTER) (INSERT UPDATE DELETE) [OR...] ON table [FOR EACH ROW] [DECLARE declarations ] BEGIN statements END; name 은트리거이름입니다. [OR REPLACE ] 이지정한동일한이름의트리거가이미스키마에존재하는경우에, 새로운트리거는기존의것으로대체합니다. [OR REPLACE ] 이지정되지않는경우, 새로운트리거는같은스키마에같은이름의기존하는것으로대체것은아닙니다. BEFORE 가지정되어있으면이전트리거로트리거가정의됩니다. AFTER 가정의되었다면, 다음트리거로트리거가정의됩니다. INSERT, UPDATE 및 DELETE 중하나는각각삽입, 업데이트, 삭제트리거이벤트에대한정의로지정되어있어야합니다. 하나또는잔여트리거이벤트키워드양측은 OR 키워드로구분정의해야합니다. 이경우이들도트리거이벤트로정의됩니다. table 은트리거이벤트가트리거를시작하는테이블의이름입니다. [ FOR EACH ROW ] 를사용하면트리거는 row-level 트리거로정의됩니다. [FOR EACH ROW ] 이생략되면트리거는명령문을트리거로정의됩니다. declarations 커서또는형식선언변수입니다. statements 는 SPL 프로그램명령문입니다. BEGIN - END 블록은 EXCEPTION 섹션을포함합니다. 트리거발생에대한자세한내용은 CREATE TRIGGER 명령을참조하십시오. 5.4 트리거변수 트리거코드블록에서일부특수변수를사용할수있습니다. NEW NEW 는 row-level 트리거삽입및업데이트작업에서새테이블행을가리키는임시 기록입니다. 이변수는문수준트리거와 row-level 트리거로제거작업에는적용되지않습니다. 사용방법 : NEW. column, column 는트리거가정의된테이블의열이름입니다. 332
333 : NEW. column 초기내용을삽입하는새로운행또는 row-level 전트리거에서사용된오래된 것으로대체할새줄에서열이름값입니다. 이후 row-level 트리거로사용하면영향을받는 행에서동작하도록이미일어나고있기때문에이값은이미테이블에저장됩니다. 트리거코드블록은 : NEW. column 는다른변수와같은방식으로사용됩니다. 값지정은 : NEW. column 은 row-level 전트리거코드블록에서줄새로운삽입및갱신되는값이지정됩니다. OLD OLD 은 row-level 트리거업데이트및삭제작업에오래된테이블행을가리키는임시 기록입니다. 이변수는문수준트리거와 row-level 트리거로삽입작업에는적용되지않습니다. 사용방법 : OLD. column, column 는트리거가정의된테이블의열이름입니다. : OLD. column 초기내용은삭제된행또는 row-level 전트리거에서사용된새로운것으로 대체되는이전행에열이름값입니다. 이후 row-level 트리거로사용하면영향을받는행에서 동작하도록이미일어나고있기때문에이값은테이블에저장되는것은아닙니다. 트리거코드블록은 : OLD. column 은다른변수들과같은방식으로사용됩니다. : OLD. column 값을지정은트리거동작에영향을받지않습니다. IN SERTING INSERTING 은구문으로삽입작업트리거를시작하면참 (true) 을반환합니다. 그렇지않다면 거짓 (false) 을반환합니다. UPDATING UPDATING 은구문으로업데이트작업을트리거를시작하면 (true) 을반환합니다. 그렇지않다면 거짓 (false) 을반환합니다. DELETING DELETING 은구문으로삭제작업을트리거를시작하면참 (true) 을반환합니다. 그렇지않다면 거짓 (false) 을반환합니다. 5.5 트랜잭션과예외처리 트리거는트리거링문이실행중인동일한거래의일환으로항상실행됩니다. 트리거코드 블록에서예외가발생없으면커밋된트리거링문이거래에포함되어있는경우에만트리거에 333
334 있는모든 DML 명령의결과는커밋됩니다. 따라서, 트랜잭션이롤백되면트리거에있는모든 DML 명령의결과는롤백됩니다. 예외로, 트리거코드블록에낼경우트리거에있는모든 DML 명령의결과가아직롤백되고 있는데도, 그것은예외처리구역으로파악처리됩니다. 그러나트리거문자체는거래캡슐화 작용힘롤백하지않은경우롤백되지않습니다. 처리되지않은예외가트리거코드블록에낼경우트리거를캡슐화하는거래가중단롤백 합니다. 그래서트리거에있는모든 DML 명령및트리거링문의결과는자체적으로모든롤백 합니다. 5.6 트리거예제 다음섹션에서는각유형의트리거의예를설명합니다 명령문수준이전트리거 다음은 emp 테이블에삽입작업이전에메시지를표시하는간단한문수준이전트리거 예제입니다. CREATE OR REPLACE TRIGGER emp_alert_trig BEFORE INSERT ON emp BEGIN DBMS_OUTPUT.PUT_LINE ( 'New employees are about to be added'); END; 다음은몇가지새로운행이명령단일실행에삽입되는것과같이, INSERT 가구성되어있습니다 에서 7999 까지직원 ID 의각행에 1000 증가되는직원 ID 에해당하는행이삽입됩니다. 그아래는새 3 행이삽입된명령실행결과입니다. INSERT INTO emp (empno, ename, deptno) SELECT empno , ename, 40 FROM emp WHERE empno BETWEEN 7900 AND 7999; New employees are about to be added SELECT empno, ename, deptno FROM emp WHERE empno BETWEEN 8900 AND 8999; EMPNO ENAME DEPTNO JAMES FORD MILLER 40 "New employees are about to be added" 메시지는결과가새로운 3 행추가되는트리거의 시작이기도한번만나타납니다. 334
335 5.6.2 statement-level 이후 다음은 statement-level 후에트리거의예제입니다. emp 테이블에삽입, 업데이트, 삭제작업이 일어날때마다날짜, 사용자활동기록 empauditlog 테이블에행이추가됩니다. CREATE TABLE empauditlog ( audit_date DATE, audit_user VARCHAR2 (20), audit_desc VARCHAR2 (20) ); CREATE OR REPLACE TRIGGER emp_audit_trig AFTER INSERT OR UPDATE OR DELETE ON emp DECLARE v_action VARCHAR2 (20); BEGIN IF INSERTING THEN v_action : = 'Added employee (s)'; ELSIF UPDATING THEN v_action : = 'Updated employee (s)'; ELSIF DELETING THEN v_action : = 'Deleted employee (s)'; END IF; INSERT INTO empauditlog VALUES (SYSDATE, USER, v_action); END; 다음명령시퀀스는 2 행 2 개의 INSERT 명령을사용하여 emp 테이블에넣습니다. sal 과 comm 쌍방의행렬은 1 개의 UPDATE 명령으로업데이트됩니다. 그리고두줄은 1 개의 DELETE 명령으로삭제됩니다. INSERT INTO emp VALUES (9001, 'SMITH', 'ANALYST', 7782, SYSDATE, NULL, NULL, 10); INSERT INTO emp VALUES (9002, 'JONES', 'CLERK', 7782, SYSDATE, NULL, NULL, 10); UPDATE emp SET sal = , comm = WHERE empno IN (9001, 9002); DELETE FROM emp WHERE empno IN (9001, 9002); SELECT TO_CHAR (AUDIT_DATE, 'DD - MON - YY HH24 : MI : SS') AS "AUDIT DATE" audit_user, audit_desc FROM empauditlog ORDER BY 1 ASC; AUDIT DATE AUDIT_USER AUDIT_DESC MAR :59:48 SYSTEM Added employee (s) 31 - MAR :00:07 SYSTEM Added employee (s) 31 - MAR :00:19 SYSTEM Updated employee (s) 31 - MAR :00:34 SYSTEM Deleted employee (s) 335
336 empauditlog 테이블의내용은많은시간트리거가시작했는지보여줍니다. 하나는 2 회삽입 하나의갱신 (2 행갱신후 ), 그리고하나의제거 (2 행이삭제후 ) row-level 전트리거 다음은 30 개부서에소속신입사원의비율을산출하고, emp 테이블에삽입으로다수준이전 트리거의예입니다. CREATE OR REPLACE TRIGGER emp_comm_trig BEFORE INSERT ON emp FOR EACH ROW BEGIN IF : NEW.deptno = 30 THEN : NEW.comm : = : NEW.sal *.4; END IF; END; 다음은두명의직원을추가하고트리거가비율을산출하고, 새로운직원행들의일부로 추가되었다는것을의미합니다. INSERT INTO emp VALUES (9005, 'ROBERS', 'SALESMAN', 7782, SYSDATE, , NULL, 30); INSERT INTO emp VALUES (9006, 'ALLEN', 'SALESMAN', 7782, SYSDATE, , NULL, 30); SELECT * FROM emp WHERE empno IN (9005, 9006); EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO ROBERS SALESMAN APR ALLEN SALESMAN APR row-level 트리거이후 아래는 row-level 후에트리거의예입니다. 새로운직원행이삽입되는경우트리거는직원의 jobhist 테이블에새행을추가합니다. 기존직원이업데이트가되는경우트리거는최신 jobhist 행 enddate 열 (enddate 는 null 로오고하나인추정 ) 를현재날짜로설정하고직원에해당하는정보에해당 jobhist 줄을삽입합니다. 마지막으로트리거는 empchglog 테이블행작동묘사와함께추가합니다. CREATE TABLE empchglog ( chg_date DATE, chg_desc VARCHAR2 (30) ); CREATE OR REPLACE TRIGGER emp_chg_trig AFTER INSERT OR UPDATE OR DELETE ON emp FOR EACH ROW DECLARE v_empno emp.empno % TYPE; 336
337 v_deptno emp.deptno % TYPE; v_dname dept.dname % TYPE; v_action VARCHAR2 (7); v_chgdesc jobhist.chgdesc % TYPE; BEGIN IF INSERTING THEN v_action : = 'Added'; v_empno : = : NEW.empno; v_deptno : = : NEW.deptno; INSERT INTO jobhist VALUES (: NEW.empno, SYSDATE, NULL, : NEW.job : NEW.sal : NEW.comm : NEW.deptno, 'New Hire'); ELSIF UPDATING THEN v_action : = 'Updated'; v_empno : = : NEW.empno; v_deptno : = : NEW.deptno; v_chgdesc : = ''; IF NVL (: OLD.ename, '- null -')! = NVL (: NEW.ename, '- null -') THEN v_chgdesc : = v_chgdesc 'name'; END IF; IF NVL (: OLD.job, '- null -')! = NVL (: NEW.job, '- null -') THEN v_chgdesc : = v_chgdesc 'job'; END IF; IF NVL (: OLD.sal, -1)! = NVL (: NEW.sal, -1) THEN v_chgdesc : = v_chgdesc 'salary'; END IF; IF NVL (: OLD.comm, -1)! = NVL (: NEW.comm, -1) THEN v_chgdesc : = v_chgdesc 'commission,'; END IF; IF NVL (: OLD.deptno, -1)! = NVL (: NEW.deptno, -1) THEN v_chgdesc : = v_chgdesc 'department,'; END IF; v_chgdesc : = 'Changed' RTRIM (v_chgdesc ','); UPDATE jobhist SET enddate = SYSDATE WHERE empno = : OLD.empno AND enddate IS NULL; INSERT INTO jobhist VALUES (: NEW.empno, SYSDATE, NULL, : NEW.job : NEW.sal : NEW.comm : NEW.deptno, v_chgdesc); ELSIF DELETING THEN v_action : = 'Deleted'; v_empno : = : OLD.empno; v_deptno : = : OLD.deptno; END IF; INSERT INTO empchglog VALUES (SYSDATE, v_action 'employee #' v_empno); END; 하단에있는명령의첫시퀀스안에두명의직원은두개의개별 INSERT 명령을사용하여 추가되고양측은하나의 UPDATE 명령을사용하여업데이트됩니다. jobhist 테이블의내용은 각각의영향을받은행트리거동작을보여줍니다. 두개의새로운직원을위한새로운신입 사원항목과두명의직원비율갱신을위한두개의비율기록을변화합니다. empchglog 테이블에트리거가총 4 회시작되고 2 개의행에한번각동작도보여주고 있습니다. INSERT INTO emp VALUES (9003, 'PETERS', 'ANALYST', 7782, SYSDATE, , NULL, 40); 337
338 INSERT INTO emp VALUES (9004, 'AIKENS', 'ANALYST', 7782, SYSDATE, , NULL, 40); UPDATE emp SET comm = sal * 1.1 WHERE empno IN (9003, 9004); SELECT * FROM jobhist WHERE empno IN (9003, 9004); EMPNO STARTDATE ENDDATE JOB SAL COMM DEPTNO CHGDESC MAR MAR - 05 ANALYST New Hire MAR MAR - 05 ANALYST New Hire MAR - 05 ANALYST Changed commission MAR - 05 ANALYST Changed commission SELECT * FROM empchglog; CHG_DATE CHG_DESC MAR - 05 Added employee # MAR - 05 Added employee # MAR - 05 Updated employee # MAR - 05 Updated employee # 9004 마지막으로, 두직원이하나의 DELETE 명령으로삭제됩니다. empchglog 테이블은각직원의 제거에트리거가 2 회시작되었음을현재보여줍니다. DELETE FROM emp WHERE empno IN (9003, 9004); SELECT * FROM empchglog; CHG_DATE CHG_DESC MAR - 05 Added employee # MAR - 05 Added employee # MAR - 05 Updated employee # MAR - 05 Updated employee # MAR - 05 Deleted employee # MAR - 05 Deleted employee # 9004 제 6 장패키지 이장에서는 Postgres Plus Advanced Serve 의패키지개념을설명합니다. 패키지는함수, 프로시저, 변수, 커서, 사용자정의레코드형식레코드를수집하는이름으로, 일반적인한정자 - 패키지 ID 를사용하여참조됩니다. 패키지에는다음과같은특징이있습니다. 패키지는관련된목표를수행편성된함수나프로시저의편리한방법을제공합니다. 패키지 함수나프로시저를사용하는권한은모든패키지에주어진 1 개의권한에따라달라집니다. 모든패키지프로그램은일반적인명칭으로는언급되고있지않습니다. 338
339 패키지에있는몇가지함수프로시저변수형식등은 public 으로선언될수있습니다. 공용요소는참조되며패키지 EXECUTE 권한이있는다른프로그램에서볼수있습니다. 공용함수와프로시저내용은그서명 ( 프로그램이름, 만약있다면매개변수, 함수의반환형식 ) 만보입니다. 이함수와프로시저의 SPL 코드는다른사람이액세스할수없습니다. 따라서, 패키지를이용하는응용프로그램은서명된정보에의존합니다. ( 자체적으로프로시저논리안에는없습니다 ). 패키지에있는다른함수프로시저변수형식등은 Private 선언할수있습니다. 개인요소는찾아볼수패키지의기능과프로시저에의해사용될수있습니다. 다른외부응용프로그램은없습니다. 개인요소는패키지프로그램에만사용합니다. 함수와프로시저이름은패키지에 overloading 수있습니다. 하나이상의함수 / 프로시저는서로다른서명에동일한이름으로정의할수있습니다. 다른종류의입력에서동일한작업을수행하는같은이름의프로그램을만들기위한기능을제공합니다. 6.1 패키지구성요소 패키지는 2 개의주요부분으로구성됩니다 : 패키지규격 : 공용인터페이스 ( 이들은패키지외부에서볼수있는부분입니다 ). 패키지 사양범위에속하는모든데이터베이스개체를공개합니다. 패키지본체패키지사양에서선전한모든데이터베이스개체의실제구현을포함합니다. 패키지본문은패키지사양내역을구현합니다. 구현세부사항및애플리케이션에는보이지않는개인선언을포함합니다. 따라서, 사양변경없이, 디버그기능강화, 교체가가능합니다. 마찬가지로구현세부정보가응용프로그램에는보이지않기때문에프로그램을부르고다시컴파일하지않고본체를변경할수있습니다 패키지사양구문 다음은패키지사양구문입니다 : CREATE [OR REPLACE] PACKAGE package_name [AUTHID (DEFINER CURRENT_USER)] (IS AS) [ declaration; ]... [(PROCEDURE proc_name [(parm1 [IN IN OUT OUT] datatype1 [, parm2 [IN IN OUT OUT] datatype2]...); FUNCTION func_name [(parm1 [IN IN OUT OUT] datatype1 [, parm2 [IN IN OUT OUT] datatype2...) RETURN return_type;)...] END [ package_name ]; 339
340 package_name 은패키지에할당된 ID 입니다. AUTHID 항이생략되거나 DEFINER 이지정되면패키지소유자의권리및검색경로는데이터객체에대한액세스권한을결정하고무조건데이터베이스객체참조를결정하기위해각각사용됩니다. CURRENT_USER 의지정이완료되면패키지의프로그램을실행하는현재사용자의권리및검색경로는권한을결정하고무조건개체참조를결정하는데사용됩니다. declaration 공용변수의식별자입니다. 공용변수는 package_name.variable 구문을사용하여패키지외부에서접근할수있습니다. 지정되지않은하나이상의공용변수가있을가능성이있습니다. 공용변수정의는프로시저와함수선언전에해야합니다. declaration 다음중하나에있습니다. 변수선언 ( 섹션 4.3 를참조하시기바랍니다 ) 레코드선언 ( 섹션 를참조하십시오 ) 배열선언 ( 섹션 를참조하십시오 ) REF CURSOR 로커서변수선언 ( 섹션 4.8 를참조하시기바랍니다 ) TYPE 기록, 모음과 REF CURSOR 를정의합니다. proc_name 는공용프로시저식별자입니다. 공용프로시저는구문 package_name.proc_name [(...)] 를사용하여패키지외부에서시작할수있습니다. 프로시저형식매개변수는 parm1, parm2... 입니다. datatype1, datatyp e2,..., parm1, parm2... 은데이터형식입니다. IN, IN OUT, 그리고 OUT 각형식매개변수모드입니다. 아무것도지정하지않으면기본값은 IN 입니다. func_name 은공용함수의 ID 입니다. 공용함수는구문 package_name.func_name [(...)] 를사용하여패키지외부에서시작할수있습니다. 함수의형식매개변수, parm1, parm2... 입니다. datatype1, datatype2... parm1, parm2... 은데이터형식입니다. IN, IN OUT, 과 OUT 각형식매개변수매개변수모드입니다. 아무것도지정하지않으면기본값은 IN 입니다. return_type 은함수의반환데이터형식입니다. IN 매개변수를지정실수 IN 매개변수를대신사용하는기본값으로초기화할수있습니다 패키지본문의구문 다음은패키지본문의구문입니다 : CREATE [OR REPLACE] PACKAGE BODY package_name (IS AS) [ private_declaration; ]... [(PROCEDURE proc_name [(parm1 [IN IN OUT OUT] datatype1 [, parm2 [IN IN OUT OUT] datatype2...) (IS AS) [proc_declaration]... BEGIN statement;... [EXCEPTION WHEN... THEN statement;...] 340
341 END; FUNCTION func_name [(parm1 [IN IN OUT OUT] datatype1 [, parm2 [IN IN OUT OUT] datatype2...) RETURN return_type (IS AS) [func_declaration]... BEGIN statement;... [EXCEPTION WHEN... THEN statement;...] END; }...] [BEGIN init_statement;...] END [ package_name ]; package_name 이것이패키지본문이있는패키지의이름입니다. 기존패키지사양과동일한 이름입니다. private_declaration 패키지의모든기능및프로시저를통해액세스할수있는전용변수의 식별자입니다. 항상하나이상의공용변수가있을수있습니다. private_declaration 다음중 하나에있습니다. 변수선언 ( 섹션 4.3 를참조하시기바랍니다 ) 레코드선언 ( 섹션 를참조하십시오 ) 배열선언 ( 섹션 4.9 를참조하십시오 ) REF CURSOR 로커서변수선언 ( 섹션 4.8 를참조하시기바랍니다 ) TYPE 기록, 모음과 REF CURSOR 를정의합니다 proc_name 이패키지사양중선언한공용프로시저식별자와동일형식매개변수이름 (parm1, parm2,...), 데이터유형 (datatype1, datatype2,...) 매개변수형태, 형식매개변수의순서와형식매개변수 ) 의서명이공용프로시저선언의서명과정확하게일치하는경우 proc_name 이공용프로시저의본문을정의합니다. 앞의단락으로작성된조건이참이아닌경우 proc_name 은공용프로시저를정의합니다. parm1, parm2,... 는프로시저형식의매개변수입니다. datatype1, datatype2... 은각 parm1, parm2... 의자료유형입니다. IN, IN OUT 다고 OUT 는각형식매개변수매개변수모드입니다. 아무것도지정되지않는경우, 기본값은 IN 입니다. IN 매개변수는지정실수 IN 매개변수를대신사용하는기본값으로초기화됩니다. proc_variable 는 proc_name 의프로시저내에서만액세스할수있는변수의식별자입니다. 항상하나이상의변수가있을수있습니다. Datatype 은 proc_variable 자료유형입니다. statement 는 SPL 프로그램문장입니다. 341
342 func _name 이패키지사양안에선언된공용함수의식별자와동일형식매개변수이름 (parm1, parm2,...), 데이터유형 (datatype1, datatype2,...) 매개변수형태, 형식매개변수의순서와형식매개변수 ) 의서명이공용프로시저선언의서명과정확하게일치하는경우, func _name 이공용함수의본문을정의합니다. 앞의단락으로작성된조건이완전하지않을경우, func _name 공용함수정의합니다. parm1, parm2... 함수형식매개변수입니다. datatype1, datatype2... 은각 parm1, parm2... 자료 유형입니다. IN, IN OUT 과 OUT 는각형식매개변수매개변수모드입니다. 아무것도 지정하지않으면기본값은 IN 입니다. return_type 은함수의반환데이터형식입니다. func_variable 는 func _name 함수내에서만액세스할수있는변수의식별자입니다. 항상하나 이상의변수가있을수있습니다. datatype 는 func_variable 자료유형입니다. statement, SPL 프로그램문장입니다. init_statement 는패키지시스템초기화부문장입니다. 초기화부분을지정하는경우, 적어도 1 개의문장포함해야합니다. 우선패키지를참조하면초기화부문장은사용자세션마다한 번씩실행됩니다 6.2 패키지구성 여기서는패키지를생성하고데이터베이스에저장하십시오. 여기서패키지는실행가능한코드가아닐수있습니다. 좀더정확히말하면, 그들은사용되는코드창고입니다. 패키지를사용하면실제로패키지요소에대한참조를실행하거나만들수있습니다. 이정보는패키지사양에포함됩니다 패키지생성사용 패키지규격은패키지에외부에서참조할수있는모든요소에대한정의를포함하고있습니다. 이것은패키지공용성분이라는동작이패키지로제공됩니다. 다음은패키지사양입니다. - - Package specification for the 'emp_admin'packa ge. - CREATE OR REPLACE PACKAGE emp_admin IS FUNCTION get_dept_name ( p_deptno NUMBER DEFAULT 10 ) RETURN VARCHAR2; FUNCTION update_emp_sal ( 342
343 p_empno NUMBER, p_raise NUMBER ) RETURN NUMBER; PROCEDURE hire_emp ( p_empno NUMBER, p_ename VARCHAR2, p_job VARCHAR2, p_sal NUMBER, p_hiredate DATE DEFAULT sysdate, p_comm NUMBER DEFAULT 0, p_mgr NUMBER, p_deptno NUMBER DEFAULT 10 ); PROCEDURE fire_emp ( p_empno NUMBER ); END emp_admin; 여기서는패키지사양 emp_admi 를만들었습니다. 이패키지사양은두함수와두저장형 프로시저로구성됩니다. 편의상 OR REPLACE 절을 CREATE PACK AGE 문장에추가할수 있습니다 패키지본문생성 패키지본문은패키지사양뒤에있는실제구현을포함합니다. 위의패키지사양 emp_admin 이사양을구현하는패키지본문을만듭니다. 본체는사양에함수와저장형프로시저구현을 포함합니다. - - Package body for the 'emp_admin'package. - CREATE OR REPLACE PACKAGE BODY emp_admin IS - - Function that queries the 'dept'table based on the department - number and returns the corresponding department name. - FUNCTION get_dept_name ( p_deptno IN NUMBER DEFAULT 10 ) RETURN VARCHAR2 IS v_dname VARCHAR2 (14); BEGIN SELECT dname INTO v_dname FROM dept WHERE deptno = p_deptno; RETURN v_dname; EXCEPTION WHEN NO_DATA_FOUND THEN DBMS_OUTPUT.PUT_LINE ( 'Invalid department number' p_deptno); RETURN ''; END; - 343
344 - Function that updates an employee 's salary based on the - employee number and salary increment / decrement passed - as IN parameters. Upon successful completion the function - returns the new updated salary. - FUNCTION update_emp_sal ( p_empno IN NUMBER, p_raise IN NUMBER ) RETURN NUMBER IS v_sal NUMBER : = 0; BEGIN SELECT sal INTO v_sal FROM emp WHERE empno = p_empno; v_sal : = v_sal + p_raise; UPDATE emp SET sal = v_sal WHERE empno = p_empno; RETURN v_sal; EXCEPTION WHEN NO_DATA_FOUND THEN DBMS_OUTPUT.PUT_LINE ( 'Employee' p_empno 'not found'); RETURN -1; WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE ( 'The following is SQLERRM :'); DBMS_OUTPUT.PUT_LINE (SQLERRM); DBMS_OUTPUT.PUT_LINE ( 'The following is SQLCODE :'); DBMS_OUTPUT.PUT_LINE (SQLCODE); RETURN -1; END; - - Procedure that inserts a new employee record into the 'emp'table. - PROCEDURE hire_emp ( p_empno NUMBER, p_ename VARCHAR2, p_job VARCHAR2, p_sal NUMBER, p_hiredate DATE DEFAULT sysdate, p_comm NUMBER DEFAULT 0, p_mgr NUMBER, p_deptno NUMBER DEFAULT 10 ) AS BEGIN INSERT INTO emp (empno, ename, job, sal, hiredate, comm, mgr, deptno) VALUES (p_empno, p_ename, p_job, p_sal, p_hiredate, p_comm, p_mgr, p_deptno); END; - - Procedure that deletes an employee record from the 'emp'table based - on the employee number. - PROCEDURE fire_emp ( p_empno NUMBER ) AS BEGIN DELETE FROM emp WHERE empno = p_empno; END; END; 344
345 6.3 패키지참조 유형항목, 하위프로그램의참조는패키지사양사이선언된점표기법을사용합니다. 예를 들면 : package_name. type_name package_name. item_name package_name. subprogram_name 패키지사양 emp_admin 에서함수를시작하려면다음 SQL 명령을실행합니다. SELECT emp_admin.get_dept_name(10) FROM DUAL; 여기서는패키지 emp_admin 안에서선언한 get_dept_name 함수를시작합니다. 부서번호를 논점화해서기능으로전달, 부서이름을반환합니다. 반환값은 ACCOUNTING 에서부서번호 10 에해당합니다. 6.4 사용자정의유형패키지사양 다음은패키지의문맥사이앞장에서설명하는사용자정의유형을포함합니다. emp_rpt 패키지규격은레코드유형 emprec_typ 약화형식 REF CURSOR 의 emp_refcur 을두 함수와두프로시저와함께액세스할수있는선언을보여줍니다. 함수 open_emp_by_dept 는 REF CURSOR 유형 EMP_REFCUR 을반환합니다. 프로시저 fetch_emp 과 close_refcur 은형식 매개변수의약점형식의 REF CURSOR 를선언합니다. 레코드유형과 REF CURSOR 정보는각 섹션 과 4.8 을참조하십시오. CREATE OR REPLACE PACKAGE emp_rpt IS TYPE emprec_typ IS RECORD ( empno NUMBER (4), ename VARCHAR (10) ); TYPE emp_refcur IS REF CURSOR; FUNCTION get_dept_name ( p_deptno IN NUMBER ) RETURN VARCHAR2; FUNCTION open_emp_by_dept ( p_deptno IN emp.deptno % TYPE ) RETURN EMP_REFCUR; PROCEDURE fetch_emp ( p_refcur IN OUT SYS_REFCURSOR ); PROCEDURE close_refcur ( 345
346 p_refcur IN OUT SYS_REFCURSOR ); END emp_rpt; 패키지본문은어떤개인변수 ( 정적커서 dept_cur 테이블유형 depttab_typ 테이블변수 t_dept 정수변수 t_dept_max, 레코드변수 r_emp) 선언을나타냅니다. 정적커서, 배열, 레코드변수에 대한자세한내용은해당섹션 4.7, 4.9.1, 를참조하십시오. CREATE OR REPLACE PACKAGE BODY emp_rpt IS CURSOR dept_cur IS SELECT * FROM dept; TYPE depttab_typ IS TABLE of dept % ROWTYPE INDEX BY BINARY_INTEGER; t_dept DEPTTAB_TYP; t_dept_max INTEGER : = 1; r_emp EMPREC_TYP; FUNCTION get_dept_name ( p_deptno IN NUMBER ) RETURN VARCHAR2 IS BEGIN FOR i IN 1.. t_dept_max LOOP IF p_deptno = t_dept (i). deptno THEN RETURN t_dept (i). dname; END IF; END LOOP; RETURN 'Unknown'; END; FUNCTION open_emp_by_dept ( p_deptno IN emp.deptno % TYPE ) RETURN EMP_REFCUR IS emp_by_dept EMP_REFCUR; BEGIN OPEN emp_by_dept FOR SELECT empno, ename FROM emp WHERE deptno = p_deptno; RETURN emp_by_dept; END; PROCEDURE fetch_emp ( p_refcur IN OUT SYS_REFCURSOR ) IS BEGIN DBMS_OUTPUT.PUT_LINE ( 'EMPNO ENAME'); DBMS_OUTPUT.PUT_LINE (' '); LOOP FETCH p_refcur INTO r_emp; EXIT WHEN p_refcur % NOTFOUND; DBMS_OUTPUT.PUT_LINE (r_emp.empno '' r_emp.ename); END LOOP; END; PROCEDURE close_refcur ( 346
347 p_refcur IN OUT SYS_REFCURSOR ) IS BEGIN CLOSE p_refcur; END; BEGIN OPEN dept_cur; LOOP FETCH dept_cur INTO t_dept (t_dept_max); EXIT WHEN dept_cur % NOTFOUND; t_dept_max : = t_dept_max + 1; END LOOP; CLOSE dept_cur; t_dept_max : = t_dept_max - 1; END emp_rpt; 이패키지는전용테이블변수 t_dept 개인정적커서를사용합니다 dept_cur 초기화부분을 포함하고있습니다. t_dept 는 get_dept_name 함수부서이름참조테이블로유용합니다. open_emp_by_dept 함수는사원번호와부서이름을결과로설정된 REF CURSOR 변수를반환합니다. 그리고 REF CURSOR 변수는개별행을결과목록의검색및명부를하기위하여 fetch_emp 프로시저에전달할수있습니다. 마지막으로 close_refcur 절차는이결과목록에관련된 RE F CURSOR 변수를닫는데사용할수있습니다. 다음익명블록은패키지의기능과프로시저를수행합니다. 익명블록의선언부분은커서변수 v_emp_cur 패키지공용 REF CURSOR 유형 EMP_REFCUR 선언에유의하시기바랍니다. v_emp_cur 패키지함수와프로시저간에전달되는결과목록에대한포인터를포함하고 있습니다. DECLARE v_deptno dept.deptno % TYPE DEFAULT 30; v_emp_cur emp_rpt.emp_refcur; BEGIN v_emp_cur : = emp_rpt.open_emp_by_dept (v_deptno); DBMS_OUTPUT.PUT_LINE ( 'EMPLOYEES IN DEPT #' v_deptno ':' emp_rpt.get_dept_name (v_deptno)); emp_rpt.fetch_emp (v_emp_cur); DBMS_OUTPUT.PUT_LINE ('**********************'); DBMS_OUTPUT.PUT_LINE (v_emp_cur % ROWCOUNT 'rows were retrieved'); emp_rpt.close_refcur (v_emp_cur); END; 다음은익명블록의결과입니다. EMPLOYEES IN DEPT # 30 : SALES EMPNO ENAME ALLEN 7521 WARD 7654 MARTIN 7698 BLAKE 347
348 7844 TURNER 7900 JAMES ********************** 6 rows were retrieved 다음익명블록에서는동일한결과를얻을수있을것입니다. 다른방법을설명합니다. 패키지 프로시저의 fetch_emp 와 close_refcur 를사용하는대신, 이프로그램논리는익명블록에직접 코드화할수있습니다. 익명블록선언부분에서는레코드변수 r_emp 패키지공용레코드 유형을사용하여선언한 EMPREC_TYP 추가주의하십시오. DECLARE v_deptno dept.deptno % TYPE DEFAULT 30; v_emp_cur emp_rpt.emp_refcur; r_emp emp_rpt.emprec_typ; BEGIN v_emp_cur : = emp_rpt.open_emp_by_dept (v_deptno); DBMS_OUTPUT.PUT_LINE ( 'EMPLOYEES IN DEPT #' v_deptno ':' emp_rpt.get_dept_name (v_deptno)); DBMS_OUTPUT.PUT_LINE ( 'EMPNO ENAME'); DBMS_OUTPUT.PUT_LINE (' '); LOOP FETCH v_emp_cur INTO r_emp; EXIT WHEN v_emp_cur % NOTFOUND; DBMS_OUTPUT.PUT_LINE (r_emp.empno '' r_emp.ename); END LOOP; DBMS_OUTPUT.PUT_LINE ('**********************'); DBMS_OUTPUT.PUT_LINE (v_emp_cur % ROWCOUNT 'rows were retrieved'); CLOSE v_emp_cur; END; 다음은이익명블록의결과입니다. EMPLOYEES IN DEPT # 30 : SALES EMPNO ENAME ALLEN 7521 WARD 7654 MARTIN 7698 BLAKE 7844 TURNER 7900 JAMES ********************** 6 rows were retrieved 6.5 패키지제거 모든패키지또는간단하게패키지본문을삭제하는구문은다음과같습니다 : DROP PACKA GE [BODY] package_name; 348
349 키워드 BODY 가생략되면패키지사양및패키지본문모두삭제됩니다. 즉전체패키지를 제거합니다. 키워드 BODY 가지정되면패키지본문만이삭제됩니다. 패키지규격은그대로 유지됩니다. package_name 는제거할패키지의 ID 입니다. 다음문장은 emp_admin 패키지본체단지해제합니다 : DROP PACKAGE BODY emp_admin; 다음문장은 emp_admin 패키지전체를삭제합니다 : DROP PACKAGE emp_admin; 제 7 장 통합패키지 이장은 Postgres Plus Advanced Server에서제공되는통합패키지를설명합니다. 특정패키지는, 슈퍼유저가아닌사용자는패키지의함수나프로시저를사용하기전에명시적으로패키지의 EXECUTE 권한을부여받아야합니다. 대부분의통합패키지는, EXECUTE 권한은기본값으로 PUBLIC에부여받습니다. 권한부여는 GRANT 명령을참조하십시오. 전체통합패키지는, 통합패키지에권한을부여하거나해제할때, 지정된특별한시스템사용자에의해소유됩니다. 7.1 DBMS_ALERT DBMS_ALERT 패키지는경고의송수신을등록하는기능을제공합니다. DBMS_ALERT 패키지에서사용가능한프로시저와함수는다음표와같습니다. Table 7-1 DBMS_ALERT 함수 / 프로시저 함수 / 프로시저 반환형식설명 REGISTER(name) n/a 경고를받을수있도록 name을등록한다. REMOVE(name) n/a 경고 name를등록을취소한다. REMOVEALL n/a 모든경고를제거한다. SIGNAL(name, message) n/a message 함께경고 name 알림 WAITANY(name OUT, message OUT, status OUT, timeout) n/a 등록된경고의발생을기다린다. WAITONE(name, message OUT, status n/a 지정경고 name의발생을기다린다. OUT, timeout) 349
350 7.1.1 REGISTER REGISTER 프로시저는현재세션에서지정된경고의알림을받을수있도록합니다. REGISTER (name VARCHAR2) 매개변수 name 등록된경고명. 예 다음익명블록은지정된경고, alert_test 를등록하고신호를기다립니다. DECLARE v_name VARCHAR2 (30) : = 'alert_test'; v_msg VARCHAR2 (80); v_status INTEGER; v_timeout NUMBER (3) : = 120; BEGIN DBMS_ALERT.REGISTER (v_name); DBMS_OUTPUT.PUT_LINE ( 'Registered for alert' v_name); DBMS_OUTPUT.PUT_LINE ( 'Waiting for signal...'); DBMS_ALERT.WAITONE (v_name, v_msg, v_status, v_timeout); DBMS_OUTPUT.PUT_LINE ( 'Alert name :' v_name); DBMS_OUTPUT.PUT_LINE ( 'Alert msg :' v_msg); DBMS_OUTPUT.PUT_LINE ( 'Alert status :' v_status); DBMS_OUTPUT.PUT_LINE ( 'Alert timeout :' v_timeout 'seconds'); DBMS_ALERT.REMOVE (v_name); END; Registered for alert alert_test Waiting for signal REMOVE REMOVE 프로시저는지정된경고세션의등록을취소합니다. REMOVE (name VARCHAR2) 매개변수 name 등록을취소하는경고의명칭 REMOVEALL REMOVEALL 프로시저는모든경고세션의등록을취소합니다. REMOVEALL SIGNAL SIGNAL 절차는지정된경고의발생을알립니다. 350
351 SIGNAL (name VARCHAR2, message VARCHAR2) 매개변수 name 경고의이름. message 경고와함께정보를전달. 예 다음익명블록은 alert_test 경고를알립니다. DECLARE v_name VARCHAR2 (30) : = 'alert_test'; BEGIN DBMS_ALERT.SIGNAL (v_name, 'This is the message from' v_name); DBMS_OUTPUT.PUT_LINE ( 'Issued alert for' v_name); END; Issued alert for alert_test WAITANY WAITANY 프로시저는등록된경고들중하나의경고의발생을기다립니다. WAITANY (name OUT VARCHAR2, message OUT VARCHAR2, status OUT INTEGER, timeout NUMBER) 매개변수 name message status timeo ut 예 경고의이름을받는변수이다. SIGNAL 프로시저통해보내진메시지를받는변수이다. 연산에서반환된상태코드입니다. 가능한값 : 0 - 경고발생 ; 1 -. 타임아웃발생. 초단위의경고를기다리는시간. 다음익명블록은 WAITANY 프로시저로지정된경고 alert_test 또는 any_alert 을받습니다. DECLARE v_name VARCHAR2 (30); v_msg VARCHAR2 (80); v_status INTEGER; v_timeout NUMBER (3) : = 120; BEGIN DBMS_ALERT.REGISTER ( 'alert_test'); DBMS_ALERT.REGISTER ( 'any_alert'); DBMS_OUTPUT.PUT_LINE ( 'Registered for alert alert_test and any_alert'); DBMS_OUTPUT.PUT_LINE ( 'Waiting for signal...'); DBMS_ALERT.WAITANY (v_name, v_msg, v_status, v_timeout); 351
352 DBMS_OUTPUT.PUT_LINE ( 'Alert name :' v_name); DBMS_OUTPUT.PUT_LINE ( 'Alert msg :' v_msg); DBMS_OUTPUT.PUT_LINE ( 'Alert status :' v_status); DBMS_OUTPUT.PUT_LINE ( 'Alert timeout :' v_timeout 'seconds'); DBMS_ALERT.REMOVEALL; END; Registered for alert alert_test and any_alert Waiting for signal... 익명블록의다음세션에서는 any_alert 에신호를발행합니다. DECLARE v_name VARCHAR2 (30) : = 'any_alert'; BEGIN DBMS_ALERT.SIGNAL (v_name, 'This is the message from' v_name); DBMS_OUTPUT.PUT_LINE ( 'Issued alert for' v_name); END; Issued alert for any_alert 제어는처음익명블록을반환하고, 코드의나머지부분이실행됩니다. Registered for alert alert_test and any_alert Waiting for signal... Alert name : any_alert Alert msg : This is the message from any_alert Alert status : 0 Alert timeout : 120 seconds WAITONE WAITONE 프로시저는지정된등록된경고발생을기다립니다. WAITONE (name VARCHAR2, message OUT VARCHAR2, status OUT INTEGER, timeout NUMBER) 매개변수 name message status timeout 예 경고명. SIGNAL 프로시저를통해보내진메시지를받는변수이다. 작업에서반환하는상태코드입니다. 가능한값 : 0 - 경고발생 ; 1 -. 타임아웃발생. 초단위의경고를기다리는시간. 다음익명블록은 WAITONE 프로시저로지정된경고 alert_test 을받는것을제외하고, WAITANY 의경우와비슷합니다. DECLARE v_name VARCHAR2 (30) : = 'alert_test'; 352
353 v_msg VARCHAR2 (80); v_status INTEGER; v_timeout NUMBER (3) : = 120; BEGIN DBMS_ALERT.REGISTER (v_name); DBMS_OUTPUT.PUT_LINE ( 'Registered for alert' v_name); DBMS_OUTPUT.PUT_LINE ( 'Waiting for signal...'); DBMS_ALERT.WAITONE (v_name, v_msg, v_status, v_timeout); DBMS_OUTPUT.PUT_LINE ( 'Alert name :' v_name); DBMS_OUTPUT.PUT_LINE ( 'Alert msg :' v_msg); DBMS_OUTPUT.PUT_LINE ( 'Alert status :' v_status); DBMS_OUTPUT.PUT_LINE ( 'Alert timeout :' v_timeout 'seconds'); DBMS_ALERT.REMOVE (v_name); END; Registered for alert alert_test Waiting for signal... 두번째세션의익명블록을통해보내진 alert_test 에보낸신호 : DECLARE v_name VARCHAR2 (30) : = 'alert_test'; BEGIN DBMS_ALERT.SIGNAL (v_name, 'This is the message from' v_name); DBMS_OUTPUT.PUT_LINE ( 'Issued alert for' v_name); END; Issued alert for alert_test 첫번째세션은경고되고, 제어는익명블록에반환하고, 코드의나머지부분이실행됩니다. Registered for alert alert_test Waiting for signal... Alert name : alert_test Alert msg : This is the message from alert_test Alert status : 0 Alert timeout : 120 seconds 종합적인예다음의예에서는, dept 테이블이나 emp 테이블이변경되는경우, 경고를보내는두개의트리거를사용합니다. 익명블록은이경고를기다리고경고를받은후메시지를표시합니다. 다음은 dept과 emp 테이블의트리거입니다.: CREATE OR REPLACE TRIGGER dept_alert_trig AFTER INSERT OR UPDATE OR DELETE ON dept DECLARE v_action VARCHAR2 (25); BEGIN 353
354 IF INSERTING THEN v_action : = 'added department (s)'; ELSIF UPDATING THEN v_action : = 'updated department (s)'; ELSIF DELETING THEN v_action : = 'deleted department (s)'; END IF; DBMS_ALERT.SIGNAL ( 'dept_alert', USER v_action 'on' SYSDATE); END; CREATE OR REPLACE TRIGGER emp_alert_trig AFTER INSERT OR UPDATE OR DELETE ON emp DECLARE v_action VARCHAR2 (25); BEGIN IF INSERTING THEN v_action : = 'added employee (s)'; ELSIF UPDATING THEN v_action : = 'updated employee (s)'; ELSIF DELETING THEN v_action : = 'deleted employee (s)'; END IF; DBMS_ALERT.SIGNAL ( 'emp_alert', USER v_action 'on' SYSDATE); END; dept 과 emp 테이블에갱신이다른세션에서발생하는동안다음익명블록이세션에서실행됩니 다. DECLARE v_dept_alert VARCHAR2 (30) : = 'dept_alert'; v_emp_alert VARCHAR2 (30) : = 'emp_alert'; v_name VARCHAR2 (30); v_msg VARCHAR2 (80); v_status INTEGER; v_timeout NUMBER (3) : = 60; BEGIN DBMS_ALERT.REGISTER (v_dept_alert); DBMS_ALERT.REGISTER (v_emp_alert); DBMS_OUTPUT.PUT_LINE ( 'Registered for alerts dept_alert and emp_alert'); DBMS_OUTPUT.PUT_LINE ( 'Waiting for signal...'); LOOP DBMS_ALERT.WAITANY (v_name, v_msg, v_status, v_timeout); EXIT WHEN v_status! = 0; DBMS_OUTPUT.PUT_LINE ( 'Alert name :' v_name); DBMS_OUTPUT.PUT_LINE ( 'Alert msg :' v_msg); DBMS_OUTPUT.PUT_LINE ( 'Alert status :' v_status); DBMS_OUTPUT.PUT_LINE (' ' ' '); END LOOP; DBMS_OUTPUT.PUT_LINE ( 'Alert status :' v_status); DBMS_ALERT.REMOVEALL; END; Registered for alerts dept_alert and emp_alert Waiting for signal
355 다음의변화가사용자 mary 통해이루어집니다. : INSERT INTO dept VALUES (50, 'FINANCE', 'CHICAGO'); INSERT INTO emp (empno, ename, deptno) VALUES (9001, 'JONES', 50); INSERT INTO emp (empno, ename, deptno) VALUES (9002, 'ALICE', 50); 다음의변화가사용자 john 을통해이루어집니다. : INSERT INTO dept VALUES (60, 'HR', 'LOS ANGELES'); 다음은트리거의신호를받은익명블록에의해실행되는출력입니다. : Registered for alerts dept_alert and emp_alert Waiting for signal... Alert name : dept_alert Alert msg : mary added department (s) on 25 - OCT :41:01 Alert status : Alert name : emp_alert Alert msg : mary added employee (s) on 25 - OCT :41:02 Alert status : Alert name : dept_alert Alert msg : john added department (s) on 25 - OCT :41:22 Alert status : Alert status : DBMS_OUTPUT DBMS_OUTPUT 패키지는메시지버퍼에서메시지를검색하거나메시지버퍼또는메시지 ( 텍스트라인 ) 송수신기능을제공합니다. 메시지버퍼는단일세션에한정됩니다. 세션에서메시지전송을하려면 DBMS_PIPE 패키지를사용하십시오. DBMS_OUTPUT 패키지에서사용가능한프로시저와함수는다음표와같습니다. 표 7-2 DBMS_OUTPUT 함수 / 프로시저 함수 / 프로시저 반환형식설명 DISABLE n/a 메시지송수신기능을해제한다. ENABLE(buffer_size) n/a 메시지송수신기능을활성화한다. GET_LINE(line OUT, status OUT) n/a 메시지버퍼로부터라인을가져온다. GET_LINES(lines OUT, numlines IN OUT) n/a 메시지버퍼로부터복수의라인을가져온 다. NEW_LINE n/a 라인종료에문자시퀀스를넣는다. PUT(item) n/a 라인종료에문자시퀀스없이부분적라 인을넣는다. 355
356 PUT_LINE(item) n/a 라인종료에문자시퀀스와완전한라인을넣는다. SERVEROUTPUT(stdout) n/a PUT, PUT_LINE, 또는 NEW_LINE에서의표준출력또는메시지버퍼중하나를직접메시지로한다. 다음의표는 the DBMS_OUTPUT 패키지에사용가능한공용변수의리스트입니다. Table 7-3 DBMS_OUTPUT 공용변수 공용변수 데이터형값 설명 chararr TABLE 메시지라인 CHARARR CHARARR 는복수의메시지라인을저장합니다. TYPE chararr IS TABLE OF VARCHAR2(32767) INDEX BY BINARY_INTEGER; DISABLE DISABLE 프로시저는메시지버퍼를제거합니다. DISABLE 프로시저가실행되었을때버퍼메시지 는접근할수없게됩니다. PUT, PUT_LINE 또는 N EW_LINE 프로시저에서나중에보내진메시지 는삭제됩니다. PUT, PUT_LINE 또는 NEW_LINE 프로시저가실행되고메시지가잘못되면오류가 반환되지않습니다. 메시지의송수신을다시허용하려면 ENABLE 프로시저또는 SERVEROUTPUT (TRUE) 프로시저를 이용하세요. DISABLE 예 다음익명블록은현재세션에서메시지송수신을해제합니다. BEGIN DBMS_OUTPUT.DISABLE; END; ENABLE ENABLE 프로시저는메시지버퍼에대한메시지전송및메시지버퍼에서메시지수신기능을활성화합니다. SERVEROUTPUT (TRUE) 실행도내재적으로 ENABLE 프로시저를수행합니다. PUT, PUT_LINE 또는 NEW_LINE에서보내진메시지의대상은 SERVEROUTPUT 상태에따라달라집니다. SERVEROUTPUT 마지막상태가 " 참 (true)" 의경우메시지는명령라인표준출력으로이동합니다. SERVEROUTPUT 마지막상태가 " 거짓 (false)" 의경우메시지는메시지버퍼로이동합니다. ENABLE [(length INTEGER) 356
357 매개변수 length 메시지버퍼바이트의최대길이. length 2000 미만이지정되면버퍼크기는 2000 으로설정됩니다. 예 다음익명블록은메시지를사용합니다. SERVEROUTPUT (TRUE) 을지정하고표준출력합니다. BEGIN DBMS_OUTPUT.ENABLE; DBMS_OUTPUT.SERVEROUTPUT (TRUE); DBMS_OUTPUT.PUT_LINE ( 'Messages enabled'); END; Messages enabled 간단하게 SERVEROUTPUT (TRUE) 을사용하면같은결과를얻을수있습니다. BEGIN DBMS_OUTPUT.SERVEROUTPUT (TRUE); DBMS_OUTPUT.PUT_LINE ('Messages enabled'); END; Messages enabled 다음익명블록은메시지를사용합니다. 그러나 SERVEROUTPUT (FALSE) 지정메시지를메시지버 퍼에맞춥니다. BEGIN DBMS_OUTPUT.ENABLE; DBMS_OUTPUT.SERVEROUTPUT (FALSE); DBMS_OUTPUT.PUT_LINE ('Message sent to buffer'); END; GET_LINE GET_LINE 프로시저는메시지버퍼텍스트라인을회복하는기능을제공합니다. 라인종료문자시퀀스로종료된텍스트는회복됩니다. 그것은 PUT_LINE 또는일련의 NEW_LINE 호출후에 PUT 호출을사용하여생성된완전한라인입니다. GET_LINE (line OUT VARCHAR2, status OUT INTEGER) 매개변수 line 메시지버퍼에서텍스트라인을받는변수이다. status 메시지버퍼라인이반환되면 1, 상환라인이없다면 0. 이값은 Oracle 호환이아니므로유의하시기바랍니다. Oracle는메시지버퍼라인이반환되면 0, 상환라인이없다면 1을반환합니다. 357
358 예 다음익명블록은각라인의쉼표로구분된문자열을메시지버퍼에 emp 테이블을내보냅니다. DECLARE v_emprec VARCHAR2 (120); CURSOR emp_cur IS SELECT * FROM emp ORDER BY empno; BEGIN DBMS_OUTPUT.SERVEROUTPUT (FALSE); FOR i IN emp_cur LOOP v_emprec : = i.empno ',' i.ename ',' i.job ',' NVL (LTRIM (TO_CHAR (i.mgr, '9999 ')),'') ',' i.hiredate ',' i.sal ',' NVL (LTRIM (TO_CHAR (i.comm, ' ')),'') ',' i.deptno; DBMS_OUTPUT.PUT_LINE (v_emprec); END LOOP; END; 다음익명블록은메시지버퍼를읽고, 앞의예제를통해명령을내보낸라인을표시합니다. DECLARE v_line VARCHAR2 (100); v_status INTEGER : = 1; BEGIN DBMS_OUTPUT.SERVEROUTPUT (TRUE); WHILE v_status = 1 LOOP DBMS_OUTPUT.GET_LINE (v_line, v_status); DBMS_OUTPUT.PUT_LINE (v_line); END LOOP; END; 7499, ALLEN, SALESMAN,7698,20 - FEB :00:00, ,300.00, , WARD, SALESMAN,7698,22 - FEB :00:00, ,500.00, , JONES, MANAGER,7839,02 - APR :00:00, , , MARTIN, SALESMAN,7698,28 - SEP :00:00, , , , BLAKE, MANAGER,7839,01 - MAY :00:00, , , CLARK, MANAGER,7839,09 - JUN :00:00, , , SCOTT, ANALYST,7566,19 - APR :00:00, , , KING, PRESIDENT,,17 - NOV :00:00, , , TURNER, SALESMAN,7698,08 - SEP :00:00, ,0.00, , ADAMS, CLERK,7788,23 - MAY :00:00, , , JAMES, CLERK,7698,03 - DEC :00: , , FORD, ANALYST,7566,03 - DEC :00:00, , , MILLER, CLERK,7782,23 - JAN :00:00, , , SMITH, CLERK,7902,17 - DEC :00: , GET_LINES GET_LINES 프로시저는집합에메시지버퍼로부터하나이상의텍스트라인의회복기능을제공합니다. 라인종료문자시퀀스에의해종료된텍스트만이회복됩니다. 그것은 PUT_LINE 또는일련의 NEW_LINE 호출후에 PUT 호출을사용하여생성된완전한라인입니다. GET_LINES(lines OUT CHARARR, numlines IN OUT INTEGER) 매개변수 lines 358
359 메시지버퍼로부터텍스트의라인을받는테이블. 라인의설명으로 CHARARR 를보세요. numlines IN 메시지버퍼로부터회수된라인의수 numlines OUT 메시지버퍼로부터회수된실제라인의수. 입력값이 numlines의출력값보다더적을경우, 메시지버퍼에남은라인은더이상없습니다. 실제라인의수는메시지버퍼로부터회복됩니다. Numlines의출력값이입력값보다작은경우, 더이상메시지버퍼에왼쪽라인은없습니다. 예다음의예는, 정렬내의메시지버퍼에대체된 emp 테이블의행을저장하는 GET_LINES 프로시저를사용합니다. EXEC DBMS_OUTPUT.SERVEROUTPUT(FALSE); DECLARE v_emprec VARCHAR2(120); CURSOR emp_cur IS SELECT * FROM emp ORDER BY empno; BEGIN DBMS_OUTPUT.ENABLE; FOR i IN emp_cur LOOP v_emprec := i.empno ',' i.ename ',' i.job ',' NVL(LTRIM(TO_CHAR(i.mgr,'9999')),'') ',' i.hiredate ',' i.sal ',' NVL(LTRIM(TO_CHAR(i.comm,' ')),'') ',' i.deptno; DBMS_OUTPUT.PUT_LINE(v_emprec); END LOOP; END; DECLARE v_lines DBMS_OUTPUT.CHARARR; v_numlines INTEGER := 14; v_status INTEGER := 0; BEGIN DBMS_OUTPUT.GET_LINES(v_lines,v_numlines); FOR i IN 1..v_numlines LOOP INSERT INTO messages VALUES(v_numlines, v_lines(i)); END LOOP; END; SELECT msg FROM messages; msg ,SMITH,CLERK,7902,17-DEC-80 00:00:00,800.00,, ,ALLEN,SALESMAN,7698,20-FEB-81 00:00:00, ,300.00, ,WARD,SALESMAN,7698,22-FEB-81 00:00:00, ,500.00, ,JONES,MANAGER,7839,02-APR-81 00:00:00, ,, ,MARTIN,SALESMAN,7698,28-SEP-81 00:00:00, , , ,BLAKE,MANAGER,7839,01-MAY-81 00:00:00, ,, ,CLARK,MANAGER,7839,09-JUN-81 00:00:00, ,, ,SCOTT,ANALYST,7566,19-APR-87 00:00:00, ,,20 359
360 7839,KING,PRESIDENT,,17-NOV-81 00:00:00, ,, ,TURNER,SALESMAN,7698,08-SEP-81 00:00:00, ,0.00, ,ADAMS,CLERK,7788,23-MAY-87 00:00:00, ,, ,JAMES,CLERK,7698,03-DEC-81 00:00:00,950.00,, ,FORD,ANALYST,7566,03-DEC-81 00:00:00, ,, ,MILLER,CLERK,7782,23-JAN-82 00:00:00, ,,10 (14 rows) NEW_LINE NEW_LINE 프로시저는메시지버퍼의라인종료문자시퀀스에기록합니다. NEW_LINE PUT PUT 프로시저는메시지버퍼에문자열을기록합니다. 문자열의라인종료문자시퀀스에기록됩니다. 라인종료문자시퀀스에추가하기위해 NEW_LINE 프로시저를사용합니다. PUT (string VARCHAR2) 매개변수 string 메시지버퍼에기록되는텍스트입니다. 예 다음예제는 emp 테이블에서직원의쉼표로구분된목록을보기위해 PUT 프로시저를사용합니 다. DECLARE CURSOR emp_cur IS SELECT * FROM emp ORDER BY empno; BEGIN FOR i IN emp_cur LOOP DBMS_OUTPUT.PUT (i.empno); DBMS_OUTPUT.PUT (','); DBMS_OUTPUT.PUT (i.ename); DBMS_OUTPUT.PUT (','); DBMS_OUTPUT.PUT (i.job); DBMS_OUTPUT.PUT (','); DBMS_OUTPUT.PUT (i.mgr); DBMS_OUTPUT.PUT (','); DBMS_OUTPUT.PUT (i.hiredate); DBMS_OUTPUT.PUT (','); DBMS_OUTPUT.PUT (i.sal); DBMS_OUTPUT.PUT (','); DBMS_OUTPUT.PUT (i.comm); DBMS_OUTPUT.PUT (','); DBMS_OUTPUT.PUT (i.deptno); DBMS_OUTPUT.NEW_LINE; END LOOP; END; 7369, SMITH, CLERK,7902,17 - DEC :00: , , ALLEN, SALESMAN,7698,20 - FEB :00:00, ,300.00,30 360
361 7521, WARD, SALESMAN,7698,22 - FEB :00:00, ,500.00, , JONES, MANAGER,7839,02 - APR :00:00, , , MARTIN, SALESMAN,7698,28 - SEP :00:00, , , , BLAKE, MANAGER,7839,01 - MAY :00:00, , , CLARK, MANAGER,7839,09 - JUN :00:00, , , SCOTT, ANALYST,7566,19 - APR :00:00, , , KING, PRESIDENT,,17 - NOV :00:00, , , TURNER, SALESMAN,7698,08 - SEP :00:00, ,0.00, , ADAMS, CLERK,7788,23 - MAY :00:00, , , JAMES, CLERK,7698,03 - DEC :00: , , FORD, ANALYST,7566,03 - DEC :00:00, , , MILLER, CLERK,7782,23 - JAN :00:00, , PUT_LINE PUT_LINE 프로시저를라인종료문자시퀀스가포함된메시지버퍼, 1 라인을씁니다. PUT_LINE (line VARCHAR2) 매개변수 line 메시지버퍼에기록되는텍스트입니다. 예 다음예제는 emp 테이블에서직원의쉼표로구분된목록을보기위해 PUT_LINE 프로시저를사 용합니다. DECLARE v_emprec VARCHAR2 (120); CURSOR emp_cur IS SELECT * FROM emp ORDER BY empno; BEGIN FOR i IN emp_cur LOOP v_emprec : = i.empno ',' i.ename ',' i.job ',' NVL (LTRIM (TO_CHAR (i.mgr, '9999 ')),'') ',' i.hiredate ',' i.sal ',' NVL (LTRIM (TO_CHAR (i.comm, ' ')),'') ',' i.deptno; DBMS_OUTPUT.PUT_LINE (v_emprec); END LOOP; END; 7369, SMITH, CLERK,7902,17 - DEC :00: , , ALLEN, SALESMAN,7698,20 - FEB :00:00, ,300.00, , WARD, SALESMAN,7698,22 - FEB :00:00, ,500.00, , JONES, MANAGER,7839,02 - APR :00:00, , , MARTIN, SALESMAN,7698,28 - SEP :00:00, , , , BLAKE, MANAGER,7839,01 - MAY :00:00, , , CLARK, MANAGER,7839,09 - JUN :00:00, , , SCOTT, ANALYST,7566,19 - APR :00:00, , , KING, PRESIDENT,,17 - NOV :00:00, , , TURNER, SALESMAN,7698,08 - SEP :00:00, ,0.00, , ADAMS, CLERK,7788,23 - MAY :00:00, , , JAMES, CLERK,7698,03 - DEC :00: , , FORD, ANALYST,7566,03 - DEC :00:00, , , MILLER, CLERK,7782,23 - JAN :00:00, , SERVEROUTPUT SERVEROUTPUT 프로시저는명령라인의표준출력또는메시지버퍼로메시지를보내는기능을 361
362 제공합니다. SERVEROUTPUT (TRUE) 설정도 ENABLE의내재적인실행을합니다. SERVEROUTPUT의기본값설정은실행에의존합니다. 예를들면, Oracle SQL * Plus에서, SERVEROUTPUT (FALSE) 은초기값입니다. PSQL에서는 SERVEROUTPUT (TRUE) 이초기값입니다. 또한 Oracle SQL * Plus는, Postgres Plus Advanced Server 에구현된것처럼, 저장된프로시저가아닌, SQL * Plus의 SET 명령을사용하여설정이제어되는것을기억하십시오. SERVEROUTPUT (stdout BOOLEAN) 매개변수 stdout PUT, PUT_LINE 과 NEW_LINE 명령이명령라인의표준출력에텍스트를보내기위해 " 참 (true)" 으 로설정합니다. 메시지버퍼에텍스트를보내려면, " 거짓 (false)" 으로설정한다. 예 다음익명블록은첫번째메시지를명령라인에보내고, 두번째메시지를메시지버퍼에전송 합니다. BEGIN DBMS_OUTPUT.SERVEROUTPUT (TRUE); DBMS_OUTPUT.PUT_LINE ( 'This message goes to the command line'); DBMS_OUTPUT.SERVEROUTPUT (FALSE); DBMS_OUTPUT.PUT_LINE ( 'This message goes to the message buffer'); END; This message goes to the command line 같은세션에서다음과익명의블록이실행되는경우, 위예제의메시지버퍼에저장된메시지는 플래시되고새로운메시지와마찬가지로명령라인에표시됩니다. BEGIN DBMS_OUTPUT.SERVEROUTPUT (TRUE); DBMS_OUTPUT.PUT_LINE ( 'Flush messages from the buffer'); END; This message goes to the message buffer Flush messages from the buffer 7.3 DBMS_PIPE DBMS_PIPE 패키지는파이프를통해동일한데이터베이스클러스터에연결된세션내에서또는세션사이에메시지를보내는기능을제공합니다. DBMS_PIPE 패키지에서사용할수있는함수와프로시저는다음표와같다. 표 7-3 DBMS_PIPE 함수 / 프로시저 함수 / 프로시저 반환형식설명 CREATE_PIPE(pipename [maxpipesize ] INTEGER Private 이참인경우개인파이프 ( 기본값 ), 362
363 [,private ]) Private 이거짓인경우공용파이프를명 시적으로생성한다. NEXT_ITEM_TYPE INTEGER 수신메시지의다음항목의데이터유형을결정한다 PACK_MESSAGE (dataitem) n / a 세션의로컬메시지버퍼에 dataitem을사용한다. PURGE (pipename) n / a 지정된파이프에서받지못한메시지를지운다. RECEIVE_MESSAGE(pipename [,timeout ]) INTEGER 지정된파이프에서메시지를검색한다. REMOVE_PIPE(pipename) INTEGER 명시적으로만든파이프제거한다. RESET_BUFFER n / a 로컬메시지버퍼를다시설정한다. SEND_MESSAGE(pipename [,timeout ] [,maxpipesize ]) INTEGER 파이프에메세지를보낸다. UNIQUE_SESSION_NAME VARCHAR2 고유세션이름을가져온다. UNPACK_MESSAGE(item OUT) n / a 호환가능한변수, item 의메시지에서다음데이터항목을회복한다파이프는암시혹은명시로분류됩니다. CREATE_PIPE 함수가생성한파이프이름이먼저만들어진경우암시적파이프가만들어집니다. 예를들면, 존재하지않는파이프이름을사용하여 SEND_MESSAGE 함수를실행하면새암시적파이프는그명칭으로만들어집니다. 명시적파이프는첫번째매개변수가새로운파이프이름을지정하는 CREATE_PIPE 함수를사용하여만들어집니다. 파이프는공개또는비공개로분류됩니다. 개인파이프는파이프를만들기사용자만접근할수있습니다. 다른사용자에의해만들어진파이프는슈퍼유저조차접근할수없습니다. DBMS_PIPE 패키지를방문한사용자는공용파이프에접근할수있습니다. 공용파이프는 CREATE_PIPE 함수의세번째매개변수가 " 거짓 (false)" 으로설정된경우에만만들어집니다. CREATE_PIPE 함수는세번째매개변수를 " 참 (true)" 으로설정되거나생략될경우에는개인파이프를만들수있습니다. 전체암시적파이프는개인전용입니다. 메시지의개별데이터항목또는 " 라인 " 은, 현재세션에유일한로컬메시지버퍼에처음으로작성됩니다. PACK_MESSAGE 프로시저는세션로컬메시지버퍼메시지를작성합니다. SEND_MESSAGE 함수는파이프를통해메시지를보내는데사용됩니다. 메시지수신은역방향연산이포함되고있습니다. RECEIVE_MESSAGE 함수는지정된파이프에서메시지를받는데사용됩니다. 메시지는세션의로컬메시지버퍼에기록됩니다. U NPACK_MESSAGE 프로시저는메시지버퍼의프로그램변수에서메시지데이터항목으로의전송에사용됩니다. 파이프에여러메시지가포함되어있는경우, RECEIVE_MESSAGE은 FIFO (First In - 363
364 First Out) 순으로메시지를받고있습니다. 각세션은 PACK_MESSAGE 프로시저로작성된메시지및 RECEIVE_MESSAGE 함수에의해회복된개별메시지버퍼를유지합니다. 따라서, 메시지는모두같은세션에서회복될수있습니다. 그러나연속 RECEIVE_MESSAGE 호출이실행되면, 마지막 RECEIVE_MESSAGE 호출에서메시지만로컬메시지버퍼가유지됩니다 CREATE_PIPE CREATE_PIPE 함수는지정된이름으로명시적공용파이프또는명시적개인파이프를생성합니 다. status INTEGER CREATE_PIPE (name VARCHAR2 [, length INTEGER] [, private BOOLEAN) 매개변수 name length private status 예 파이프의명칭. 바이트매개변수로파이프의최대허용량. 기본값은 8192 바이트. " 거짓 (false)" 지정공용파이프를생성. " 참 (true)" 지정전용파이프를생성. 이것은기본값입니다. 연산에의한반환상태코드. 0 은생성의성공을나타냅니다. 개인파이프 messages 생성 : DECLARE v_status INTEGER; BEGIN v_status : = DBMS_PIPE.CREATE_PIPE ( 'messages'); DBMS_OUTPUT.PUT_LINE ( 'CREATE_PIPE status :' v_status); END; CREATE_PIPE status : 0 공용파이프 mailbox 생성 : DECLARE v_status INTEGER; BEGIN v_status : = DBMS_PIPE.CREATE_PIPE ( 'mailbox', 8192, FALSE); DBMS_OUTPUT.PUT_LINE ( 'CREATE_PIPE status :' v_status); END; CREATE_PIPE status : NEXT_ITEM_TYPE 364
365 NEXT_ITEM_TYPE 함수는세션로컬메시지버퍼에회수된메시지중데이터유형의다음데이터항목을식별하는정수코드를반환합니다. 항목이각각 UNPACK_MESSAGE 프로시저에서로컬메시지버퍼로이동하는동시에, NEXT_ITEM_TYPE 함수는다음이용가능한항목을위해데이터유형코드를반환합니다. 항목이메시지에더이상남아있지않으면 0 코드가반환됩니다. typecode INTEGER NEXT_ITEM_TYPE 매개변수 typecode 표 7-4에서보여지는것처럼다음데이터항목의데이터형식을식별하는고유코드. 표 7-4 NEXT_ITEM_TYPE 데이터형식코드 유형코드 데이터형식 0 더이상데이터항목이없는 9 NUMBER 11 VARCHAR2 13 DATE 23 RAW * 참고 표의유형코드목록은 Oracle 과호환성이없습니다. 할당하고있습니다. 예 Oracle 다른번호순서를데이터유형에 다음은 NUMBER 항목, VARCHAR2 항목, DATE 항목, RAW 항목을포함하는파이프를보여줍니다. 두번째익명블록은각항목의유형코드를보여주는 NEXT_ITEM_TYPE 함수를사용합니다. DECLARE v_number NUMBER : = 123; v_varchar VARCHAR2 (20) : = 'Character data'; v_date DATE : = SYSDATE; v_raw RAW (4) : = ' '; v_status INTEGER; BEGIN DBMS_PIPE.PACK_MESSAGE (v_number); DBMS_PIPE.PACK_MESSAGE (v_varchar); DBMS_PIPE.PACK_MESSAGE (v_date); DBMS_PIPE.PACK_MESSAGE (v_raw); v_status : = DBMS_PIPE.SEND_MESSAGE ( 'datatypes'); DBMS_OUTPUT.PUT_LINE ( 'SEND_MESSAGE status :' v_status); EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE ( 'SQLERRM :' SQLERRM); DBMS_OUTPUT.PUT_LINE ( 'SQLCODE :' SQLCODE); END; SEND_MESSAGE status : 0 DECLARE v_number NUMBER; 365
366 v_varchar VARCHAR2 (20); v_date DATE; v_timestamp TIMESTAMP; v_raw RAW (4); v_status INTEGER; BEGIN v_status : = DBMS_PIPE.RECEIVE_MESSAGE ( 'datatypes'); DBMS_OUTPUT.PUT_LINE ( 'RECEIVE_MESSAGE status :' v_status); DBMS_OUTPUT.PUT_LINE (' '); v_status : = DBMS_PIPE.NEXT_ITEM_TYPE; DBMS_OUTPUT.PUT_LINE ( 'NEXT_ITEM_TYPE :' v_status); DBMS_PIPE.UNPACK_MESSAGE (v_number); DBMS_OUTPUT.PUT_LINE ( 'NUMBER Item :' v_number); DBMS_OUTPUT.PUT_LINE (' '); v_status : = DBMS_PIPE.NEXT_ITEM_TYPE; DBMS_OUTPUT.PUT_LINE ( 'NEXT_ITEM_TYPE :' v_status); DBMS_PIPE.UNPACK_MESSAGE (v_varchar); DBMS_OUTPUT.PUT_LINE ( 'VARCHAR2 Item :' v_varchar); DBMS_OUTPUT.PUT_LINE (' '); v_status : = DBMS_PIPE.NEXT_ITEM_TYPE; DBMS_OUTPUT.PUT_LINE ( 'NEXT_ITEM_TYPE :' v_status); DBMS_PIPE.UNPACK_MESSAGE (v_date); DBMS_OUTPUT.PUT_LINE ( 'DATE Item :' v_date); DBMS_OUTPUT.PUT_LINE (' '); v_status : = DBMS_PIPE.NEXT_ITEM_TYPE; DBMS_OUTPUT.PUT_LINE ( 'NEXT_ITEM_TYPE :' v_status); DBMS_PIPE.UNPACK_MESSAGE (v_raw); DBMS_OUTPUT.PUT_LINE ( 'RAW Item :' v_raw); DBMS_OUTPUT.PUT_LINE (' '); v_status : = DBMS_PIPE.NEXT_ITEM_TYPE; DBMS_OUTPUT.PUT_LINE ( 'NEXT_ITEM_TYPE :' v_status); DBMS_OUTPUT.PUT_LINE (' '); EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE ( 'SQLERRM :' SQLERRM); DBMS_OUTPUT.PUT_LINE ( 'SQLCODE :' SQLCODE); END; RECEIVE_MESSAGE status : NEXT_ITEM_TYPE : 9 NUMBER Item : NEXT_ITEM_TYPE : 11 VARCHAR2 Item : Character data NEXT_ITEM_TYPE : 13 DATE Item : 02 - OCT :11: NEXT_ITEM_TYPE : 23 RAW Item : NEXT_ITEM_TYPE : 0 366
367 7.3.3 PACK_MESSAGE PACK_MESSAGE 프로시저는세션로컬메시지버퍼데이터항목을위치시킵니다. PACK_MESSAGE 은 SEND_MESSAGE을호출하기전에적어도한번실행됩니다. PACK_MESSAGE (dataitem (DATE NUMBER VARCHAR2 RAW)) RECEIVE_MESSAGE 호출을사용해메시지가회복되면데이터항목을얻기위해 UNPACK_MESSAGE 프로시저를이용하세요. 매개변수 dataitem 적절한매개변수의데이터유형을나타내는평가. 세션로컬메시지버퍼에값이추가됩니다 PURGE PURGE 프로시저는지정된암시적파이프로부터받지못한메시지를삭제합니다. PURGE (name VARCHAR2) 명시적파이프를제거하려면 REMOVE_PIPE 함수를사용하십시오. 매개변수 name 예 파이프의명칭. 두개의메시지가파이프로전송됩니다. DECLARE v_status INTEGER; BEGIN DBMS_PIPE.PACK_MESSAGE ( 'Message # 1'); v_status : = DBMS_PIPE.SEND_MESSAGE ( 'pipe'); DBMS_OUTPUT.PUT_LINE ( 'SEND_MESSAGE status :' v_status); DBMS_PIPE.PACK_MESSAGE ( 'Message # 2'); v_status : = DBMS_PIPE.SEND_MESSAGE ( 'pipe'); DBMS_OUTPUT.PUT_LINE ( 'SEND_MESSAGE status :' v_status); END; SEND_MESSAGE status : 0 SEND_MESSAGE status : 0 첫메시지를받고해독합니다 : DECLARE v_item VARCHAR2 (80); v_status INTEGER; BEGIN v_status : = DBMS_PIPE.RECEIVE_MESSAGE ( 'pipe', 1); DBMS_OUTPUT.PUT_LINE ( 'RECEIVE_MESSAGE status :' v_status); DBMS_PIPE.UNPACK_MESSAGE (v_item); DBMS_OUTPUT.PUT_LINE ( 'Item :' v_item); END; RECEIVE_MESSAGE status : 0 Item : Message # 1 367
368 파이프를삭제합니다. EXEC DBMS_PIPE.PURGE ( 'pipe'); 다음메시지회수를시도합니다. RECEIVE_MESSAGE 호출을사용할수있는메시지가없어, 시간 초과했음을나타내는상태코드 1 을반환합니다. DECLARE v_item VARCHAR2 (80); v_status INTEGER; BEGIN v_status : = DBMS_PIPE.RECEIVE_MESSAGE ( 'pipe', 1); DBMS_OUTPUT.PUT_LINE ( 'RECEIVE_MESSAGE status :' v_status); END; RECEIVE_MESSAGE status : RECEIVE_MESSAGE RECEIVE_MESSAGE 함수는지정된파이프에서메시지를가져옵니다. status INTEGER RECEIVE_MESSAGE (name VARCHAR2 [,timeout INTEGER) 매개변수 name 파이프의명칭. timeout 대기시간 ( 초 ). 기본값은 (1000 일 ). status 작업에서반환하는상태코드입니다. 가능한상태코드 : Table 7-5 RECEIVE_MESSAGE 상태코드 상태코드 설명 0 성공 1 시간초과 2 버퍼에메시지가너무큼 REMOVE_PIPE REMOVE_PIPE 함수는명시적개인파이프또는명시적공용파이프를제거합니다. status INTEGER REMOVE_PIPE (name VARCHAR2) 명시적으로만든파이프 (CREATE_PIPE 함수에의해생성된파이프 ) 를제거하기위해 368
369 REMOVE_PIPE 함수를사용합니다. 매개변수 name 파이프의명칭. status 작업에서반환하는상태코드입니다. 지정된파이프가존재하지않고, 0의상태코드가반환됩니다. 예두개의메시지가파이프로전송됩니다. DECLARE v_status INTEGER; BEGIN v_status : = DBMS_PIPE.CREATE_PIPE ( 'pipe'); DBMS_OUTPUT.PUT_LINE ( 'CREATE_PIPE status :' v_status); DBMS_PIPE.PACK_MESSAGE ( 'Message # 1'); v_status : = DBMS_PIPE.SEND_MESSAGE ( 'pipe'); DBMS_OUTPUT.PUT_LINE ( 'SEND_MESSAGE status :' v_status); DBMS_PIPE.PACK_MESSAGE ( 'Message # 2'); v_status : = DBMS_PIPE.SEND_MESSAGE ( 'pipe'); DBMS_OUTPUT.PUT_LINE ( 'SEND_MESSAGE status :' v_status); END; CREATE_PIPE status : 0 SEND_MESSAGE status : 0 SEND_MESSAGE status : 0 첫메시지를받고해독합니다. : DECLARE v_item VARCHAR2 (80); v_status INTEGER; BEGIN v_status : = DBMS_PIPE.RECEIVE_MESSAGE ( 'pipe', 1); DBMS_OUTPUT.PUT_LINE ( 'RECEIVE_MESSAGE status :' v_status); DBMS_PIPE.UNPACK_MESSAGE (v_item); DBMS_OUTPUT.PUT_LINE ( 'Item :' v_item); END; RECEIVE_MESSAGE status : 0 Item : Message # 1 파이프를제거합니다. SELECT DBMS_PIPE.REMOVE_PIPE ( 'pipe') FROM DUAL; remove_pipe
370 (1 row) 다음메시지회수를시도합니다. RECEIVE_MESSAGE 호출은파이프를삭제한것에따른시간변 경을나타내는상태코드 1 을반환합니다. DECLARE v_item VARCHAR2 (80); v_status INTEGER; BEGIN v_status : = DBMS_PIPE.RECEIVE_MESSAGE ( 'pipe', 1); DBMS_OUTPUT.PUT_LINE ( 'RECEIVE_MESSAGE status :' v_status); END; RECEIVE_MESSAGE status : RESET_BUFFER RESET_BUFFER 프로시저는세션의로컬메시지버퍼 " 포인터 (pointer)" 를버퍼의처음으로돌려 보내도록다시설정합니다. 이것은 RESET_BUFFER 호출보다이전에존재하는메시지버퍼의데이 터항목에덮어쓰도록, 다음 PACK_MESSAGE 호출하는결과의원인이되는효과를가집니다. RESET_BUFFER 예 John 에게메시지가로컬메시지버퍼에쓰이고있습니다. 그것은 RESET_BUFFER 를호출하여 Bob 에게메시지로대체됩니다. 메시지는파이프로전송됩니다. DECLARE v_status INTEGER; BEGIN DBMS_PIPE.PACK_MESSAGE ( 'Hi, John'); DBMS_PIPE.PACK_MESSAGE ( 'Can you attend a meeting at 3:00, today?'); DBMS_PIPE.PACK_MESSAGE ( 'If not, is tomorrow at 8:30 ok with you?'); DBMS_PIPE.RESET_BUFFER; DBMS_PIPE.PACK_MESSAGE ( 'Hi, Bob'); DBMS_PIPE.PACK_MESSAGE ( 'Can you attend a meeting at 9:30, tomorrow?'); v_status : = DBMS_PIPE.SEND_MESSAGE ( 'pipe'); DBMS_OUTPUT.PUT_LINE ( 'SEND_MESSAGE status :' v_status); END; SEND_MESSAGE status : 0 받은메시지에 Bob 에게보내는메시지가있습니다. DECLARE v_item VARCHAR2 (80); v_status INTEGER; BEGIN v_status : = DBMS_PIPE.RECEIVE_MESSAGE ( 'pipe', 1); DBMS_OUTPUT.PUT_LINE ( 'RECEIVE_MESSAGE status :' v_status); DBMS_PIPE.UNPACK_MESSAGE (v_item); DBMS_OUTPUT.PUT_LINE ( 'Item :' v_item); DBMS_PIPE.UNPACK_MESSAGE (v_item); DBMS_OUTPUT.PUT_LINE ( 'Item :' v_item); 370
371 END; RECEIVE_MESSAGE status : 0 Item : Hi, Bob Item : Can you attend a meeting at 9:30, tomorrow? SEND_MESSAGE SEND_MESSAGE 함수는세션의로컬메시지버퍼지정된파이프에메시지를보냅니다. status SEND_MESSAGE (name VARCHAR2 ', timeout INTEGER] [, length INTEGER) 매개변수 name 파이프의명칭. timeout 대기시간 ( 초 ). 기본값은 (1000 일 ). length 파이프바이트의용량. 기본값은 8192 바이트. status 작업에서반환하는상태코드입니다. 가능한상태코드 : Table 7-6 SEND_MESSAGE 상태코드 상태코드 설명 0 성공 1 시간제한 3 함수의붕괴 UNIQUE_SESSION_NAME UNIQUE_SESSION_NAME 함수는이름 ( 현재세션과관련된 ) 을반환합니다. name VARCHAR2 UNIQUE_SESSION_NAME 매개변수 name Examples 독특한세션이름. 다음익명블록은독특한세션이름을회수하고표시합니다. DECLARE v_session VARCHAR2 (30); 371
372 BEGIN v_session : = DBMS_PIPE.UNIQUE_SESSION_NAME; DBMS_OUTPUT.PUT_LINE ( 'Session Name :' v_session); END; Session Name : PG $ PIPE $ 5 $ UNPACK_MESSAGE UNPACK_MESSAGE 프로시저는로컬루멧세지버퍼에서지정된프로그램변수까지메시지의데이터항목을복사합니다. 메시지는 UNPACK_MESSAGE를사용하기전에 RECEIVE_MESSAGE 함수로컬메시지버퍼에배치됩니다. UNPACK_MESSAGE (dataitem OUT (DATE NUMBER VARCHAR2 RAW)) 매개변수 dataitem 로컬메시지버퍼에서데이터항목을받는호환가능한변수 종합적인예 다음예제에서는파이프를 " 사서함 " 으로사용합니다. 의메시지를사서함 (3 항목까지 ) 에추가합니다. 용을볼수있습니다. CREATE OR REPLACE PACKAGE mailbox IS PROCEDURE create_mailbox; PROCEDURE add_message ( p_mailbox VARCHAR2, p_item_1 VARCHAR2, p_item_2 VARCHAR2 DEFAULT 'END', p_item_3 VARCHAR2 DEFAULT 'END' ); PROCEDURE empty_mailbox ( p_mailbox VARCHAR2, p_waittime INTEGER DEFAULT 10 ); END mailbox; 프로시저는사서함을생성하고, 여러항목 패키지이름 mailbox 에있는사서함의전체내 CREATE OR REPLACE PACKAGE BODY mailbox IS PROCEDURE create_mailbox IS v_mailbox VARCHAR2 (30); v_status INTEGER; BEGIN v_mailbox : = DBMS_PIPE.UNIQUE_SESSION_NAME; v_status : = DBMS_PIPE.CREATE_PIPE (v_mailbox, 1000, FALSE); IF v_status = 0 THEN DBMS_OUTPUT.PUT_LINE ( 'Created mailbox :' v_mailbox); ELSE DBMS_OUTPUT.PUT_LINE ( 'CREATE_PIPE failed - status :' v_status); END IF; 372
373 END create_mailbox; PROCEDURE add_message ( p_mailbox VARCHAR2, p_item_1 VARCHAR2, p_item_2 VARCHAR2 DEFAULT 'END', p_item_3 VARCHAR2 DEFAULT 'END' ) IS v_item_cnt INTEGER : = 0; v_status INTEGER; BEGIN DBMS_PIPE.PACK_MESSAGE (p_item_1); v_item_cnt : = 1; IF p_item_2! = 'END'THEN DBMS_PIPE.PACK_MESSAGE (p_item_2); v_item_cnt : = v_item_cnt + 1; END IF; IF p_item_3! = 'END'THEN DBMS_PIPE.PACK_MESSAGE (p_item_3); v_item_cnt : = v_item_cnt + 1; END IF; v_status : = DBMS_PIPE.SEND_MESSAGE (p_mailbox); IF v_status = 0 THEN DBMS_OUTPUT.PUT_LINE ( 'Added message with' v_item_cnt 'item (s) to mailbox' p_mailbox); ELSE DBMS_OUTPUT.PUT_LINE ( 'SEND_MESSAGE in add_message failed -' 'status :' v_status); END IF; END add_message; PROCEDURE empty_mailbox ( p_mailbox VARCHAR2, p_waittime INTEGER DEFAULT 10 ) IS v_msgno INTEGER DEFAULT 0; v_itemno INTEGER DEFAULT 0; v_item VARCHAR2 (100); v_status INTEGER; BEGIN v_status : = DBMS_PIPE.RECEIVE_MESSAGE (p_mailbox, p_waittime); WHILE v_status = 0 LOOP v_msgno : = v_msgno + 1; DBMS_OUTPUT.PUT_LINE ('****** Start message # ' v_msgno '******'); BEGIN LOOP v_status : = DBMS_PIPE.NEXT_ITEM_TYPE; EXIT WHEN v_status = 0; DBMS_PIPE.UNPACK_MESSAGE (v_item); v_itemno : = v_itemno + 1; DBMS_OUTPUT.PUT_LINE ( 'Item #' v_itemno ':' v_item); END LOOP; DBMS_OUTPUT.PUT_LINE ('******* End message # ' v_msgno '*******'); DBMS_OUTPUT.PUT_LINE ('*'); 373
374 v_itemno : = 0; v_status : = DBMS_PIPE.RECEIVE_MESSAGE (p_mailbox, 1); END; END LOOP; DBMS_OUTPUT.PUT_LINE ( 'Number of messages received :' v_msgno); v_status : = DBMS_PIPE.REMOVE_PIPE (p_mailbox); IF v_status = 0 THEN DBMS_OUTPUT.PUT_LINE ( 'Deleted mailbox' p_mailbox); ELSE DBMS_OUTPUT.PUT_LINE ( 'Could not delete mailbox - status :' v_status); END IF; END empty_mailbox; END mailbox; 다음은 mailbox 에서프로시저의실행을설명합니다. 첫번째프로시저에서는 UNIQUE_SESSION_NAME 함수에의해생성된이름을사용하여공용파이프를만듭니다. EXEC mailbox.create_mailbox; Created mailbox : PG $ PIPE $ 13 $ 3940 사서함이름을사용하고, mailbox 패키지와 DBMS_PIPE 패키지에접근하는동일한데이터베이스 관리자는메시지를추가할수있습니다 : EXEC mailbox.add_message ( 'PG $ PIPE $ 13 $ 3940', 'Hi, John', 'Can you attend a meeting at 3:00, today?','-- Mary'); Added message with 3 item (s) to mailbox PG $ PIPE $ 13 $ 3940 EXEC mailbox.add_message ( 'PG $ PIPE $ 13 $ 3940', 'Don''t forget to submit your report', 'Thanks,','-- Joe'); Added message with 3 item (s) to mailbox PG $ PIPE $ 13 $ 3940 마지막으로, 사서함내용은비워둘수있습니다 : EXEC mailbox.empty_mailbox ( 'PG $ PIPE $ 13 $ 3940'); ****** Start message # 1 ****** Item # 1 : Hi, John Item # 2 : Can you attend a meeting at 3:00, today? Item # 3 : - Mary ******* End message # 1 ******* * ****** Start message # 2 ****** Item # 1 : Don't forget to submit your report Item # 2 : Thanks, Item # 3 : Joe ******* End message # 2 ******* * Number of messages received : 2 Deleted mailbox PG $ PIPE $ 13 $
375 7.4 UTL_FILE UTL_FILE 패키지는운영체제의파일시스템에서파일읽기및쓰기기능을제공합니다. 비슈퍼유저는패키지의함수와프로시저를사용하기전에슈퍼유저를 UTL_FILE 패키지의 EXECUTE 권한을부여해야합니다. 예를들어, 다음명령은 mary에권한을부여합니다 : GRANT EXECUTE ON PACKAGE SYS.UTL_FILE TO mary; 또한운영체제의사용자이름 enterprisedb는, UTL_FILE 함수나프로시저를사용하여디렉토리와파일에접근하기위해적절한읽기 / 쓰기허가를얻어야합니다. 필요한파일권한이적시에없으면, UTL_FILE 함수나프로시저중예외가발생합니다. 파일쓰기및읽기작업은파일참조를사용합니다. file handle 은 UTL_FILE 패키지의공용변수 UTL_FILE.FILE_TYPE 로정의됩니다. FOPEN 함수호출에서반환되는파일핸들을받으려면 FILE_TYPE 변수를선언해야합니다. 그리고, 파일핸들은이후의모든파일작업에사용됩니다. 파일시스템의디렉토리검색은 CREATE DIRECTORY 명령을사용하여디렉토리에할당된별칭이나디렉토리이름을사용합니다. UTL_FILE 패키지에서사용가능한프로시저와함수를다음표에열거합니다. Table 7-7 UTL_FILE 함수 / 프로시저 함수 / 프로시저 반환형식설명 FCLOSE(file IN OUT) n/a File 에의해식별된지정된파일을닫는다. FCLOSE_ALL n/a 모든열린파일을닫는다. FCOPY(location, filename, dest_dir, dest_file [, start_line [, end_line ] ]) n/a 그리고 Location에의해파일에식별된디렉토리, dest_file, dest_dir, 시작라인부터, start_line, end_line으로부터 Filename을복사한다 FFLUSH(file) n/a 버퍼의데이터가 file에의해식별된파일내의디스크에기록되게한다.. FOPEN(location, filename, open_mode FILE_TYPE location 에의해식별된디렉토리의파일, [,max_linesize ]) filename을연다. FREMOVE(location, filename) n/a 파일시스템으로부터지정된파일을제거한다. FRENAME(location, filename, dest_dir, dest_file [,overwrite ]) n/a 지정된파일을이름을다시짓는다. GET_LINE(file, buffer OUT) n/a Reads a line of text into variable, buffer, from the file identified by file. file로식별된파일로부터, 변수, buffer, 의 375
376 텍스트라인을읽는다. IS_OPEN(file) BOOLEAN 주어진파일을열것인지아닌지결정한 다. NEW_LINE(file [, lines ]) n/a 파일에라인종료문자시퀀스를작성한다. PUT(file, buffer) n/a 주어진파일에 buffer를작성한다. PUT은라인종료문자시퀀스를작성하지않는다. PUT_LINE(file, buffer) n/a 주어진파일에 buffer를작성한다라인종료문자시퀀스는 PUT_LINE 프로시저에의해더해진다. PUTF(file, format [, arg1 ] [,...]) n/a 주어진파일에서식화된문자열을작성한다. 다섯개까지, 치환매개변수, arg1,...arg5 는 format에대체로지정된다 FCLOSE FCLOSE 프로시저는오픈파일을닫습니다. FCLOSE (filetype FILE_TYPE) 매개변수 filetype 닫혀져야할파일의파일핸들을포함하는변수형식 FILE_TYPE FCLOSE_ALL FLCLOSE_ALL 프로시저는열려있는모든파일을닫습니다. 닫아야할열린파일이없어도프로시저실행이성공합니다. FCLOSE_ALL FCOPY FCOPY 함수는파일의텍스트를다른파일에복사합니다. VOID FCOPY (dirname VARCHAR2, filename VARCHAR2, destdir VARCHAR2, destfile VARCHAR2 [, begin INTEGER [, end INTEGER]) EnterpriseDB 의 FCOPY 은 Oracle 와호환되지않는것을주의하십시오. Oracle 에서는 FCOPY 은함 376
377 수가아닌프로시저로구현됩니다. 매개변수 dirname 복사할파일을포함하는디렉토리, pg_catalog.edb_ dir.dirname에저장된디렉토리이름. filename 복사할원본파일이름. destdir 파일이복사되는디렉토리, pg_catalog.edb_dir.dirname 에저장된디렉토리이름. destfile 대상파일이름. begin 복사가시작되는소스파일의라인번호. 기본값은 1. end 복사할원본파일의마지막라인번호. 생략또는해제된경우파일의마지막라인까지복사합니다. 예다음은 emp 테이블에서직원쉼표로구분된목록이포함된파일 C : \ TEMP \ EMPDIR \ empfile.csv 사본을만듭니다. 그런다음복사 empcopy.csv가나열됩니다. FCOPY은유효함수이므로 PERFORM 명령을사용해시작된다는점에주의하십시오. PERFORM 명령은 Oracle 호환이아닙니다. CREATE DIRECTORY empdir AS 'C : \ TEMP / EMPDIR'; DECLARE v_empfile UTL_FILE.FILE_TYPE; v_src_dir VARCHAR2 (50) : = 'empdir'; v_src_file VARCHAR2 (20) : = 'empfile.csv'; v_dest_dir VARCHAR2 (50) : = 'empdir'; v_dest_file VARCHAR2 (20) : = 'empcopy.csv'; v_emprec VARCHAR2 (120); v_count INTEGER : = 0; BEGIN PERFORM UTL_FILE.FCOPY (v_src_dir, v_src_file, v_dest_dir, v_dest_file); v_empfile : = UTL_FILE.FOPEN (v_dest_dir, v_dest_file, 'r'); DBMS_OUTPUT.PUT_LINE ( 'The following is the destination file, ''' v_dest_file ''''); LOOP UTL_FILE.GET_LINE (v_empfile, v_emprec); DBMS_OUTPUT.PUT_LINE (v_emprec); v_count : = v_count + 1; END LOOP; EXCEPTION WHEN NO_DATA_FOUND THEN UTL_FILE.FCLOSE (v_empfile); DBMS_OUTPUT.PUT_LINE (v_count 'records retrieved'); WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE ( 'SQLERRM :' SQLERRM); DBMS_OUTPUT.PUT_LINE ( 'SQLCODE :' SQLCODE); 377
378 END; The following is the destination file, 'empcopy.csv' 7369, SMITH, CLERK,7902,17 - DEC - 80, 800, , ALLEN, SALESMAN,7698,20 - FEB - 81, 1600,300, , WARD, SALESMAN,7698,22 - FEB - 81, 1250,500, , JONES, MANAGER,7839,02 - APR - 81, 2975, , MARTIN, SALESMAN,7698,28 - SEP - 81, 1250,1400, , BLAKE, MANAGER,7839,01 - MAY - 81, 2850, , CLARK, MANAGER,7839,09 - JUN - 81, 2450, , SCOTT, ANALYST,7566,19 - APR - 87, 3000, , KING, PRESIDENT,,17 - NOV - 81, 5000, , TURNER, SALESMAN,7698,08 - SEP - 81, 1500,0, , ADAMS, CLERK,7788,23 - MAY - 87, 1100, , JAMES, CLERK,7698,03 - DEC - 81, 950, , FORD, ANALYST,7566,03 - DEC - 81, 3000, , MILLER, CLERK,7782,23 - JAN - 82, 1300, records retrieved FFLUSH FFLUSH 프로시저는쓰기버퍼파일에기록되지않은데이터를플래시합니다. FFLUSH (filetype FILE_TYPE) 매개변수 filetype 예 파일핸들을포함하는변수형식 FILE_TYPE NEW_LINE 프로시저가호출된후, 각라인이플래시됩니다. DECLARE v_empfile UTL_FILE.FILE_TYPE; v_directory VARCHAR2 (50) : = 'empdir'; v_filename VARCHAR2 (20) : = 'empfile.csv'; CURSOR emp_cur IS SELECT * FROM emp ORDER BY empno; BEGIN v_empfile : = UTL_FILE.FOPEN (v_directory, v_filename, 'w'); FOR i IN emp_cur LOOP UTL_FILE.PUT (v_empfile, i.empno); UTL_FILE.PUT (v_empfile,','); UTL_FILE.PUT (v_empfile, i.ename); UTL_FILE.PUT (v_empfile,','); UTL_FILE.PUT (v_empfile, i.job); UTL_FILE.PUT (v_empfile,','); UTL_FILE.PUT (v_empfile, i.mgr); UTL_FILE.PUT (v_empfile,','); UTL_FILE.PUT (v_empfile, i.hiredate); UTL_FILE.PUT (v_empfile,','); UTL_FILE.PUT (v_empfile, i.sal); UTL_FILE.PUT (v_empfile,','); UTL_FILE.PUT (v_empfile, i.comm); UTL_FILE.PUT (v_empfile,','); UTL_FILE.PUT (v_empfile, i.deptno); UTL_FILE.NEW_LINE (v_empfile); UTL_FILE.FFLUSH (v_empfile); END LOOP; DBMS_OUTPUT.PUT_LINE ( 'Created file :' v_filename); 378
379 UTL_FILE.FCLOSE (v_empfile); END; FOPEN FOPEN 함수는 I / O 를위해파일을엽니다. filetype FILE_TYPE FOPEN (dirname VARCHAR2, filename VARCHAR2, mode VARCHAR2 ', linesize INTEGER) 매개변수 dirname filename mode linesize filetype 열릴파일을포함하는디렉토리, pg_catalog.edb_dir.dirname 에저장된디렉토리이름. 열릴파일이름. 열릴파일을형태. 형태는다음과같다 : a - 파일에추가, r - 파일에서읽기, w - 파일에내보낼. 라인의최대길이. 읽기모드에서는 max_linesize 를초과하는라인을읽으려시도하면 예외가발생합니다. 쓰기, 추가모드에서는 max_linesize 를넘는라인을기록하려고하면 예외가발생합니다. 라인종료문자는최대라인의크기가초과여부결정에포함되지 않습니다. 이행동은 Oracle 호환이되지않습니다. 합니다 FREMOVE 열린파일핸들을포함하는변수형식 FILE_TYPE FREMOVE 함수는시스템에서파일을삭제합니다. VOID FREMOVE (dirname VARCHAR2, filename VARCHAR2) 삭제된파일이없으면예외가발생합니다. 매개변수 location filename 예 Oracle 은라인종료문자를카운트 제거될디렉토리에포함된파일의 pg_catalog.edb_dir.dirname 에저장된디렉토리의이름 입니다. 삭제되는파일이름입니다. 다음은파일 empfile.csv 를삭제합니다. DECLARE v_directory VARCHAR2 (50) : = 'empdir'; v_filename VARCHAR2 (20) : = 'empfile.csv'; BEGIN PERFORM UTL_FILE.FREMOVE (v_directory, v_filename); 379
380 DBMS_OUTPUT.PUT_LINE ( 'Removed file :' v_filename); EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE ( 'SQLERRM :' SQLERRM); DBMS_OUTPUT.PUT_LINE ( 'SQLCODE :' SQLCODE); END; Removed file : empfile.csv FRENAME FRENAME 프로시저는지정된파일이름을변경합니다. 이것은한위치에서다른위치로파일을 효과적으로이동합니다. FRENAME(location VARCHAR2, filename VARCHAR2, dest_dir VARCHAR2, dest_file VARCHAR2, [ overwrite BOOLEAN ]) 매개변수 location pg_catalog.edb_dir.dirname에저장된, 이름이변경될파일을포함하는디렉토리명 filename 변경될소스파일의이름 dest_dir pg_catalog.edb_dir.dirname에저장된, 이름이변경된파일에존재하기위한디렉토리명 dest_file 원래파일의새이름 overwrite 참으로설정되면, dest_dir 에있는 dest_file 라는이름으로존재하는파일을대체한다. 거짓으로설정되면, 예외로한다. 이것은기본값이다. 예 다음은, emp 테이블로부터쉼표로구분된직원의목록을포함하는 C:\TEMP\EMPDIR\empfile.csv 파일의이름을변경합니다. 이름이변경된파일 C:\TEMP\NEWDIR\newemp.csv 는열거됩니다. CREATE DIRECTORY "newdir" AS 'C:/TEMP/NEWDIR'; DECLARE v_empfile UTL_FILE.FILE_TYPE; v_src_dir VARCHAR2(50) := 'empdir'; v_src_file VARCHAR2(20) := 'empfile.csv'; v_dest_dir VARCHAR2(50) := 'newdir'; v_dest_file VARCHAR2(50) := 'newemp.csv'; v_replace BOOLEAN := FALSE; v_emprec VARCHAR2(120); v_count INTEGER := 0; BEGIN 380
381 UTL_FILE.FRENAME(v_src_dir,v_src_file,v_dest_dir, v_dest_file,v_replace); v_empfile := UTL_FILE.FOPEN(v_dest_dir,v_dest_file,'r'); DBMS_OUTPUT.PUT_LINE('The following is the renamed file, ''' v_dest_file ''''); LOOP UTL_FILE.GET_LINE(v_empfile,v_emprec); DBMS_OUTPUT.PUT_LINE(v_emprec); v_count := v_count + 1; END LOOP; EXCEPTION WHEN NO_DATA_FOUND THEN UTL_FILE.FCLOSE(v_empfile); DBMS_OUTPUT.PUT_LINE(v_count ' records retrieved'); WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('SQLERRM: ' SQLERRM); DBMS_OUTPUT.PUT_LINE('SQLCODE: ' SQLCODE); END; The following is the renamed file, 'newemp.csv' 7369,SMITH,CLERK,7902,17-DEC-80 00:00:00,800.00,, ,ALLEN,SALESMAN,7698,20-FEB-81 00:00:00, ,300.00, ,WARD,SALESMAN,7698,22-FEB-81 00:00:00, ,500.00, ,JONES,MANAGER,7839,02-APR-81 00:00:00, ,, ,MARTIN,SALESMAN,7698,28-SEP-81 00:00:00, , , ,BLAKE,MANAGER,7839,01-MAY-81 00:00:00, ,, ,CLARK,MANAGER,7839,09-JUN-81 00:00:00, ,, ,SCOTT,ANALYST,7566,19-APR-87 00:00:00, ,, ,KING,PRESIDENT,,17-NOV-81 00:00:00, ,, ,TURNER,SALESMAN,7698,08-SEP-81 00:00:00, ,0.00, ,ADAMS,CLERK,7788,23-MAY-87 00:00:00, ,, ,JAMES,CLERK,7698,03-DEC-81 00:00:00,950.00,, ,FORD,ANALYST,7566,03-DEC-81 00:00:00, ,, ,MILLER,CLERK,7782,23-JAN-82 00:00:00, ,,10 14 records retrieved GET_LINE GET_LINE 프로시저는라인종료터미네이터를포함하지않고, 주어진파일로부터텍스트라인을 읽습니다. A NO_DATA_FOUND 예외는더이상읽을라인이없을때주어집니다. GET_LINE(file FILE_TYPE, buffer OUT VARCHAR2) 매개변수 file 열린파일의파일핸들러를포함하는 FILE_TYPE 형의변수 buffer 파일로부터라인을받기위한변수예다음의익명블록은 empfile.csv 파일에서레코드를표시하고읽습니다. 381
382 DECLARE v_empfile UTL_FILE.FILE_TYPE; v_directory VARCHAR2(50) := 'empdir'; v_filename VARCHAR2(20) := 'empfile.csv'; v_emprec VARCHAR2(120); v_count INTEGER := 0; BEGIN v_empfile := UTL_FILE.FOPEN(v_directory,v_filename,'r'); LOOP UTL_FILE.GET_LINE(v_empfile,v_emprec); DBMS_OUTPUT.PUT_LINE(v_emprec); v_count := v_count + 1; END LOOP; EXCEPTION WHEN NO_DATA_FOUND THEN UTL_FILE.FCLOSE(v_empfile); DBMS_OUTPUT.PUT_LINE('End of file ' v_filename ' - ' v_count ' records retrieved'); WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('SQLERRM: ' SQLERRM); DBMS_OUTPUT.PUT_LINE('SQLCODE: ' SQLCODE); END; 7369,SMITH,CLERK,7902,17-DEC-80 00:00:00,800.00,, ,ALLEN,SALESMAN,7698,20-FEB-81 00:00:00, ,300.00, ,WARD,SALESMAN,7698,22-FEB-81 00:00:00, ,500.00, ,JONES,MANAGER,7839,02-APR-81 00:00:00, ,, ,MARTIN,SALESMAN,7698,28-SEP-81 00:00:00, , , ,BLAKE,MANAGER,7839,01-MAY-81 00:00:00, ,, ,CLARK,MANAGER,7839,09-JUN-81 00:00:00, ,, ,SCOTT,ANALYST,7566,19-APR-87 00:00:00, ,, ,KING,PRESIDENT,,17-NOV-81 00:00:00, ,, ,TURNER,SALESMAN,7698,08-SEP-81 00:00:00, ,0.00, ,ADAMS,CLERK,7788,23-MAY-87 00:00:00, ,, ,JAMES,CLERK,7698,03-DEC-81 00:00:00,950.00,, ,FORD,ANALYST,7566,03-DEC-81 00:00:00, ,, ,MILLER,CLERK,7782,23-JAN-82 00:00:00, ,,10 End of file empfile.csv - 14 records retrieved IS_OPEN IS_OPEN 함수는주어진파일을열지, 열지않을것인지결정합니다. status BOOLEAN IS_OPEN(file FILE_TYPE) 매개변수 file 테스트될파일의파일핸들러를포함하는 FILE_TYPE 형의변수 status True if the given file is open, false otherwise. 주어진파일을열면 참, 그렇지않으면 거짓 382
383 NEW_LINE NEW_LINE 프로시저는파일에라인종료문자시퀀스를씁니다. NEW_LINE(file FILE_TYPE [, lines INTEGER ]) 매개변수 file lines 예 라인종료문자시퀀스가쓰여진파일의파일핸들러를포함하는 FILE_TYPE 형의변수 쓰여진라인종료문자시퀀스의수. 기본값은 1. 직원의두줄간격목록을포함하는파일이쓰여집니다. DECLARE v_empfile UTL_FILE.FILE_TYPE; v_directory VARCHAR2(50) := 'empdir'; v_filename VARCHAR2(20) := 'empfile.csv'; CURSOR emp_cur IS SELECT * FROM emp ORDER BY empno; BEGIN v_empfile := UTL_FILE.FOPEN(v_directory,v_filename,'w'); FOR i IN emp_cur LOOP UTL_FILE.PUT(v_empfile,i.empno); UTL_FILE.PUT(v_empfile,','); UTL_FILE.PUT(v_empfile,i.ename); UTL_FILE.PUT(v_empfile,','); UTL_FILE.PUT(v_empfile,i.job); UTL_FILE.PUT(v_empfile,','); UTL_FILE.PUT(v_empfile,i.mgr); UTL_FILE.PUT(v_empfile,','); UTL_FILE.PUT(v_empfile,i.hiredate); UTL_FILE.PUT(v_empfile,','); UTL_FILE.PUT(v_empfile,i.sal); UTL_FILE.PUT(v_empfile,','); UTL_FILE.PUT(v_empfile,i.comm); UTL_FILE.PUT(v_empfile,','); UTL_FILE.PUT(v_empfile,i.deptno); UTL_FILE.NEW_LINE(v_empfile,2); END LOOP; DBMS_OUTPUT.PUT_LINE('Created file: ' v_filename); UTL_FILE.FCLOSE(v_empfile); END; Created file: empfile.csv 파일이보여집니다. C:\TEMP\EMPDIR>TYPE empfile.csv 7369,SMITH,CLERK,7902,17-DEC-80 00:00:00,800.00,, ,ALLEN,SALESMAN,7698,20-FEB-81 00:00:00, ,300.00, ,WARD,SALESMAN,7698,22-FEB-81 00:00:00, ,500.00,30 383
384 7566,JONES,MANAGER,7839,02-APR-81 00:00:00, ,, ,MARTIN,SALESMAN,7698,28-SEP-81 00:00:00, , , ,BLAKE,MANAGER,7839,01-MAY-81 00:00:00, ,, ,CLARK,MANAGER,7839,09-JUN-81 00:00:00, ,, ,SCOTT,ANALYST,7566,19-APR-87 00:00:00, ,, ,KING,PRESIDENT,,17-NOV-81 00:00:00, ,, ,TURNER,SALESMAN,7698,08-SEP-81 00:00:00, ,0.00, ,ADAMS,CLERK,7788,23-MAY-87 00:00:00, ,, ,JAMES,CLERK,7698,03-DEC-81 00:00:00,950.00,, ,FORD,ANALYST,7566,03-DEC-81 00:00:00, ,, ,MILLER,CLERK,7782,23-JAN-82 00:00:00, ,, PUT PUT 프로시저는문자열을주어진파일에씁니다. 라인종료문자시퀀스는문자열의끝에쓰여지지않습니다. 라인종료문자시퀀스에추가하기위해서 NEW_LINE 프로시저를사용하세요. PUT(file FILE_TYPE, buffer { DATE NUMBER TIMESTAMP VARCHAR2 }) 매개변수 file buffer 예 주어진문자열이작성될파일의파일핸들러를포함하는 FILE_TYPE 형의변수 지정된파일에작성될텍스트 다음의예는 emp 테이블로부터직원의쉼표처리된파일을생성하기위해 PUT 프로시저를사 용합니다. DECLARE v_empfile UTL_FILE.FILE_TYPE; v_directory VARCHAR2(50) := 'empdir'; v_filename VARCHAR2(20) := 'empfile.csv'; CURSOR emp_cur IS SELECT * FROM emp ORDER BY empno; BEGIN v_empfile := UTL_FILE.FOPEN(v_directory,v_filename,'w'); FOR i IN emp_cur LOOP UTL_FILE.PUT(v_empfile,i.empno); UTL_FILE.PUT(v_empfile,','); UTL_FILE.PUT(v_empfile,i.ename); UTL_FILE.PUT(v_empfile,','); UTL_FILE.PUT(v_empfile,i.job); 384
385 UTL_FILE.PUT(v_empfile,','); UTL_FILE.PUT(v_empfile,i.mgr); UTL_FILE.PUT(v_empfile,','); UTL_FILE.PUT(v_empfile,i.hiredate); UTL_FILE.PUT(v_empfile,','); UTL_FILE.PUT(v_empfile,i.sal); UTL_FILE.PUT(v_empfile,','); UTL_FILE.PUT(v_empfile,i.comm); UTL_FILE.PUT(v_empfile,','); UTL_FILE.PUT(v_empfile,i.deptno); UTL_FILE.NEW_LINE(v_empfile); END LOOP; DBMS_OUTPUT.PUT_LINE('Created file: ' v_filename); UTL_FILE.FCLOSE(v_empfile); END; Created file: empfile.csv 다음은위에서생성된 empfile.csv 의내용입니다. C:\TEMP\EMPDIR>TYPE empfile.csv 7369,SMITH,CLERK,7902,17-DEC-80 00:00:00,800.00,, ,ALLEN,SALESMAN,7698,20-FEB-81 00:00:00, ,300.00, ,WARD,SALESMAN,7698,22-FEB-81 00:00:00, ,500.00, ,JONES,MANAGER,7839,02-APR-81 00:00:00, ,, ,MARTIN,SALESMAN,7698,28-SEP-81 00:00:00, , , ,BLAKE,MANAGER,7839,01-MAY-81 00:00:00, ,, ,CLARK,MANAGER,7839,09-JUN-81 00:00:00, ,, ,SCOTT,ANALYST,7566,19-APR-87 00:00:00, ,, ,KING,PRESIDENT,,17-NOV-81 00:00:00, ,, ,TURNER,SALESMAN,7698,08-SEP-81 00:00:00, ,0.00, ,ADAMS,CLERK,7788,23-MAY-87 00:00:00, ,, ,JAMES,CLERK,7698,03-DEC-81 00:00:00,950.00,, ,FORD,ANALYST,7566,03-DEC-81 00:00:00, ,, ,MILLER,CLERK,7782,23-JAN-82 00:00:00, ,, PUT_LINE PUT_LINE 프로시저는라인종료문자시퀀스를포함하는주어진파일에하나의라인을씁니다. PUT_LINE(file FILE_TYPE, buffer { DATE NUMBER TIMESTAMP VARCHAR2 }) 매개변수 file 주어진라인이작성될파일의파일핸들러를포함하는 FILE_TYPE 형의변수 buffer 지정된파일에작성될텍스트예다음의예는 emp 테이블로부터직원의쉼표처리된파일을생성하기위해 PUT_LINE 프로시저를 385
386 사용합니다. DECLARE v_empfile UTL_FILE.FILE_TYPE; v_directory VARCHAR2(50) := 'empdir'; v_filename VARCHAR2(20) := 'empfile.csv'; v_emprec VARCHAR2(120); CURSOR emp_cur IS SELECT * FROM emp ORDER BY empno; BEGIN v_empfile := UTL_FILE.FOPEN(v_directory,v_filename,'w'); FOR i IN emp_cur LOOP v_emprec := i.empno ',' i.ename ',' i.job ',' NVL(LTRIM(TO_CHAR(i.mgr,'9999')),'') ',' i.hiredate ',' i.sal ',' NVL(LTRIM(TO_CHAR(i.comm,' ')),'') ',' i.deptno; UTL_FILE.PUT_LINE(v_empfile,v_emprec); END LOOP; DBMS_OUTPUT.PUT_LINE('Created file: ' v_filename); UTL_FILE.FCLOSE(v_empfile); END; 다음은위에서생성된 empfile.csv 의내용입니다. C:\TEMP\EMPDIR>TYPE empfile.csv 7369,SMITH,CLERK,7902,17-DEC-80 00:00:00,800.00,, ,ALLEN,SALESMAN,7698,20-FEB-81 00:00:00, ,300.00, ,WARD,SALESMAN,7698,22-FEB-81 00:00:00, ,500.00, ,JONES,MANAGER,7839,02-APR-81 00:00:00, ,, ,MARTIN,SALESMAN,7698,28-SEP-81 00:00:00, , , ,BLAKE,MANAGER,7839,01-MAY-81 00:00:00, ,, ,CLARK,MANAGER,7839,09-JUN-81 00:00:00, ,, ,SCOTT,ANALYST,7566,19-APR-87 00:00:00, ,, ,KING,PRESIDENT,,17-NOV-81 00:00:00, ,, ,TURNER,SALESMAN,7698,08-SEP-81 00:00:00, ,0.00, ,ADAMS,CLERK,7788,23-MAY-87 00:00:00, ,, ,JAMES,CLERK,7698,03-DEC-81 00:00:00,950.00,, ,FORD,ANALYST,7566,03-DEC-81 00:00:00, ,, ,MILLER,CLERK,7782,23-JAN-82 00:00:00, ,, PUTF PUTF 프로시저는서식화된문자열을주어진파일에작성합니다. PUTF(file FILE_TYPE, format VARCHAR2 [, arg1 VARCHAR2] [,...]) 매개변수 file 서식화된라인이작성될파일의파일핸들러를포함하는 FILE_TYPE 형의변수 format 386
387 arg1 파일에작성된텍스트를서식화하는문자열. 특별한문자시퀀스, %s, 는 arg 값에의해대체됩니다. 특별한문자시퀀스, \n, 는새로운라인을가리킵니다. 그러나 Postgres Plus Advanced 서버에, 새로운라인문자는한개의- \\n 대신두개의연속적인백슬래시가지정됩니다. 이특성은 Oracle 호환성이없습니다. 각 %s 의발생에대체되는문자열서식에 5개인자, arg1,...arg5 첫번째 arg는첫번째 %s 발생에대체되고, 두번째 arg는두번째 %s의발생에대체됩니다. 예다음의익명블록은 emp 테이블로부터데이터를포함하는서식화된출력물을산출합니다. Oracle 호환성이없는문자열서식에새로운라인문자시퀀스에, E 리터럴구문의사용과두개의백슬러시를사용합니다. DECLARE v_empfile UTL_FILE.FILE_TYPE; v_directory VARCHAR2(50) := 'empdir'; v_filename VARCHAR2(20) := 'empfile.csv'; v_format VARCHAR2(200); CURSOR emp_cur IS SELECT * FROM emp ORDER BY empno; BEGIN v_format := E'%s %s, %s\\nsalary: $%s Commission: $%s\\n\\n'; v_empfile := UTL_FILE.FOPEN(v_directory,v_filename,'w'); FOR i IN emp_cur LOOP UTL_FILE.PUTF(v_empfile,v_format,i.empno,i.ename,i.job,i.sal, NVL(i.comm,0)); END LOOP; DBMS_OUTPUT.PUT_LINE('Created file: ' v_filename); UTL_FILE.FCLOSE(v_empfile); EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('SQLERRM: ' SQLERRM); DBMS_OUTPUT.PUT_LINE('SQLCODE: ' SQLCODE); END; Created file: empfile.csv 다음은위에서생성된 empfile.csv 의내용입니다. C:\TEMP\EMPDIR>TYPE empfile.csv 7369 SMITH, CLERK Salary: $ Commission: $ ALLEN, SALESMAN Salary: $ Commission: $ WARD, SALESMAN Salary: $ Commission: $
388 7566 JONES, MANAGER Salary: $ Commission: $ MARTIN, SALESMAN Salary: $ Commission: $ BLAKE, MANAGER Salary: $ Commission: $ CLARK, MANAGER Salary: $ Commission: $ SCOTT, ANALYST Salary: $ Commission: $ KING, PRESIDENT Salary: $ Commission: $ TURNER, SALESMAN Salary: $ Commission: $ ADAMS, CLERK Salary: $ Commission: $ JAMES, CLERK Salary: $ Commission: $ FORD, ANALYST Salary: $ Commission: $ MILLER, CLERK Salary: $ Commission: $0 8 장오픈클라이언트라이브러리 오픈클라이언트라이브러리 (Open Client Library) 은오라클호출인터페이스 (OCI) 와애플리케이션의상호운용성을제공합니다. 그동안오라클 잠금상태 " 로되어응용프로그램이응용프로그램코드에약간의수정또는그대로 Postgres Plus Advanced Server 또는 Oracle 데이터베이스에서다동작할수있다. 오픈클라이언트라이브러리 (OCL) 은처음부터 C 언어로만들어졌습니다. 다음그림은오픈클라이언트라이브러리와오라클호출인터페이스애플리케이션구조의 비교입니다. 388
389 그림 6 오픈클라이언트라이브러리 다음은오픈클라이언트라이브러리에서지원되는함수목록입니다. 거의모든헤더파일은 사용자가제공할수있습니다. Postgres Plus Advanced Server 는그런파일은제공하지않습니다. Table 8-1 연결, 인증, 초기화 함수 설명 OCIEnvCreate OCI 환경을생성. OCIEnvInit OCI 환경핸들초기화. OCIInitialize OCI 환경초기화. OCILogoff 세션의개방. OCILogon 접속연결발생. OCILogon2 다양한모드세션접속발생. OCIServerAttach 데이터소스에접근경로의설립. OCIServerDetach 데이터소스에액세스경로개방. OCISessionBegin 사용자세션생성. OCISessionEnd 사용자세션종료. OCISessionGet 세션풀에서세션받음. OCISessionRelease 세션의개방. 389
13주-14주proc.PDF
12 : Pro*C/C++ 1 2 Embeded SQL 3 PRO *C 31 C/C++ PRO *C NOT! NOT AND && AND OR OR EQUAL == = SQL,,, Embeded SQL SQL 32 Pro*C C SQL Pro*C C, C Pro*C, C C 321, C char : char[n] : n int, short, long : float
More informationDBMS & SQL Server Installation Database Laboratory
DBMS & 조교 _ 최윤영 } 데이터베이스연구실 (1314 호 ) } 문의사항은 cyy@hallym.ac.kr } 과제제출은 dbcyy1@gmail.com } 수업공지사항및자료는모두홈페이지에서확인 } dblab.hallym.ac.kr } 홈페이지 ID: 학번 } 홈페이지 PW:s123 2 차례 } } 설치전점검사항 } 설치단계별설명 3 Hallym Univ.
More information단답형 (26 회기출문제 ) 1. 아래와같은테이블이있을때아래의 SQL 결과에대해서 Oracle, SQL Server 순서로적으시오 TAB1 COL1 CHAR(10) COL2 CHAR(10) INSERT INTO TAB1 VALUES ('1',''); INSERT INT
Study Room Doc.03 : SQLD 예상문제 ( 단답형 ) 네이버 Cafe : 데이터베이스전문가포럼 Study Room http://cafe.naver.com/sqlpd SQLD 26,25,24,21 회기출문제를바탕으로작성 작성자 : 월야루 도움 : 빙수민외카페댓글 2017-11-30 단답형 (26 회기출문제 ) 1. 아래와같은테이블이있을때아래의 SQL
More information목차 BUG 문법에맞지않는질의문수행시, 에러메시지에질의문의일부만보여주는문제를수정합니다... 3 BUG ROUND, TRUNC 함수에서 DATE 포맷 IW 를추가지원합니다... 5 BUG ROLLUP/CUBE 절을포함하는질의는 SUBQUE
ALTIBASE HDB 6.3.1.10.1 Patch Notes 목차 BUG-45710 문법에맞지않는질의문수행시, 에러메시지에질의문의일부만보여주는문제를수정합니다... 3 BUG-45730 ROUND, TRUNC 함수에서 DATE 포맷 IW 를추가지원합니다... 5 BUG-45760 ROLLUP/CUBE 절을포함하는질의는 SUBQUERY REMOVAL 변환을수행하지않도록수정합니다....
More informationI T C o t e n s P r o v i d e r h t t p : / / w w w. h a n b i t b o o k. c o. k r
I T C o t e n s P r o v i d e r h t t p : / / w w w. h a n b i t b o o k. c o. k r -------------------------------------------------------------------- -- 1. : ts_cre_bonsa.sql -- 2. :
More informationORACLE-SQL
ORACLE-SQL SELECT 문 2014-04-12 Blog.ksh123jjang.me 내용 SELECT문이란?... 2 SLELECT문사용하기... 3 모든열선택... 4 특정열검색... 5 SQL문작성방법... 6 열머리글기본값... 7 산술식... 8 NULL... 9 열 alias... 10 연결연산자... 11 대체인용연산자 (q)... 12 중복행제거...
More informationMicrosoft Word - PLSQL.doc
PL/SQL 2008 DB system and programming 보충자료 PL/SQL의실행절 BEGIN 절에서의몇가지규칙 - 실행문은여러라인에걸쳐사용할수있다. - 변수명의명명규칙은오라클의일반적인명명규칙과동일하다. PL/SQL 블록내에서 SQL 문을사용할때에는컬럼명과같은변수명은피해야한다. - SQL에서와마찬가지로날짜와문자는홑따옴표 ( ) 를사용하여인용하여야한다.
More information@OneToOne(cascade = = "addr_id") private Addr addr; public Emp(String ename, Addr addr) { this.ename = ename; this.a
1 대 1 단방향, 주테이블에외래키실습 http://ojcedu.com, http://ojc.asia STS -> Spring Stater Project name : onetoone-1 SQL : JPA, MySQL 선택 http://ojc.asia/bbs/board.php?bo_table=lecspring&wr_id=524 ( 마리아 DB 설치는위 URL
More informationESQL/C
20 장. PL/SQL 커서 주요내용 암시적커서 명시적커서선언 명시적커서열기및닫기 명시적커서에서데이터 Fetch 커서의속성 (%ISOPEN, %ROWCOUNT, %FOUND, %NOTFOUND) 커서 FOR 루프 PL/SQL 의커서 (Cursor) 커서 SQL 문과프로그램실행과정에서결과를저장할수있는오라클메모리구조 ( 개별 SQL 작업영역 ) 암시적커서 (Implicit
More informationJerry Held
,, - - - : DELETE : ROW (ROWID) row ROWID : I/O Full Table Scan I/O Index Scan ROWID I/O Fast Full Index Scan scan scan scan I/O scan scan Unique, nonunique. (Concatenated Index) B* Tree Bitmap Reverse
More information,, - - - : DELETE : ROW (ROWID) row ROWID : I/O Full Table Scan scan I/O scan Index Scan ROWID scan I/O Fast Full Index Scan scan scan I/O Unique, nonunique. (Concatenated Index) B* Tree Bitmap Reverse
More information´ÙÁß Row °á°ú¸¦ ´ÜÀÏÇàÀ¸·Î Äĸ¶·Î ºÐ¸®ÇØ Ãâ·ÂÇÏ´Â ¹æ¹ý
5 중 1 2007-06-12 오후 5:52 Home Login Register SQL Query SQL Tuning Oracle Administration Tools References Boards SoQooL? 쏘쿨 SoQooL) 이란? Q&A Tips Lectures Function Lectures Oracle Spatial Tips Scripts SQL
More informationSQL Tuning Business Development DB
SQL Tuning Business Development DB Oracle Optimizer 4.1 Optimizer SQL SQL.. SQL Optimizer :.. Rule-Based Optimization (RBO), Cost-Based Optimization (CBO) SQL Optimizer SQL Query Parser Dictionary Rule-Based
More information아이콘의 정의 본 사용자 설명서에서는 다음 아이콘을 사용합니다. 참고 참고는 발생할 수 있는 상황에 대처하는 방법을 알려 주거나 다른 기능과 함께 작동하는 방법에 대한 요령을 제공합니다. 상표 Brother 로고는 Brother Industries, Ltd.의 등록 상
Android 용 Brother Image Viewer 설명서 버전 0 KOR 아이콘의 정의 본 사용자 설명서에서는 다음 아이콘을 사용합니다. 참고 참고는 발생할 수 있는 상황에 대처하는 방법을 알려 주거나 다른 기능과 함께 작동하는 방법에 대한 요령을 제공합니다. 상표 Brother 로고는 Brother Industries, Ltd.의 등록 상표입니다. Android는
More informationMySQL-.. 1
MySQL- 기초 1 Jinseog Kim Dongguk University jinseog.kim@gmail.com 2017-08-25 Jinseog Kim Dongguk University jinseog.kim@gmail.com MySQL-기초 1 2017-08-25 1 / 18 SQL의 기초 SQL은 아래의 용도로 구성됨 데이터정의 언어(Data definition
More informationMicrosoft Word - SQL튜닝_실습교재_.doc
* 실습환경 * 1. 오라클데이터베이스의튜닝실습을하기위해서는기본적인테이블과데이터가필요합니다. 다음과같은절차에의해환경설정을하십시오. 1) 강사가제공하는 Export 된파일 (scott.dmp) 을자신의 ORACLE 경로에저장하십시오. [C: ] cd C: ORACLE ORA92 BIN [C: ] dir scott.dmp scott.dmp 2) SYSTEM 사용자로접속하여
More information다양한 예제로 쉽게 배우는 오라클 SQL 과 PL/SQL
다양한예제로쉽게배우는 오라클 SQL 과 PL/SQL 서진수저 4 장 JOIN 을배웁니다 1 2 1. Cartesian Product ( 카티션곱, CROSS Join) - Oracle Join 문법 SQL> SELECT e.ename, d.dname 2 FROM emp e, dept d ; - ANSI Join 문법 SQL> SELECT e.ename, d.dname
More information<C1A62038B0AD20B0ADC0C7B3EBC6AE2E687770>
제 8강 SQL: 관계데이터베이스언어 강의목표 관계데이타베이스언어로서상용 DBMS에서가장널리사용되는 SQL의동작원리에관하여학습하고, 이를이용하여다양한질의문을작성하는방법을습득한다 기대효과 SQL의데이터정의기능을이해한다 SQL의데이터조작기능중질의기능을이해한다 SQL의데이터조작기능중데이터갱신기능을이해한다 SQL의데이터조작기능중뷰및인덱스관련기능을이해한다 SQL 의개요
More informationInsertColumnNonNullableError(#colName) 에해당하는메시지출력 존재하지않는컬럼에값을삽입하려고할경우, InsertColumnExistenceError(#colName) 에해당하는메시지출력 실행결과가 primary key 제약에위배된다면, Ins
Project 1-3: Implementing DML Due: 2015/11/11 (Wed), 11:59 PM 이번프로젝트의목표는프로젝트 1-1 및프로젝트 1-2에서구현한프로그램에기능을추가하여간단한 DML을처리할수있도록하는것이다. 구현한프로그램은 3개의 DML 구문 (insert, delete, select) 을처리할수있어야한다. 테이블데이터는파일에저장되어프로그램이종료되어도사라지지않아야한다.
More informationFlashBackt.ppt
1. Flashback 목적 Flashback 이란? 사용자실수에의한손상된데이터를 Database 의크기와상관없이복구를할수있는기능이다. 이 Flashback 기능은일반적인복구에서우려되는데이터베이스의크기를걱정하지않아도된다. 보통의사용자실수는커다란시스템장애가수반되며, 이를복구하기위해서는많은자원과시간이필요하다. 하지만 9i 에서지원되느 flashback query
More informationMicrosoft Word - 05_SUBPROGRAM.doc
ORACLE SUBPROGRAM INTRODUCTION PLSQL 은오라클에서제공하는프로그래밍언어이다. 이는데이터베이스언어인 SQL 과함께효과적으로데이터베이스에접근할수있는방법을제공하고있다. Procedural LanguageSQL 의약자에서볼수있듯이절차적인기능을기본적으로가지는프로그래밍언어이다. PLSQL 은기본적으로블록 (BLOCK) 구조를가지고있다. 블록의기본적인구성은선언부
More informationMicrosoft Word - 04_EXCEPTION.doc
ORACLE EXCEPTION INTRODUCTION PLSQL 블록이 PARSE 되는동안에발생되는에러를컴파일에러 (Compilation Error) 라고부르며, PLSQL 블록이실행되는동안에발생되는에러를런타임에러 (Run-Time Error) 라고부르는데, 이런타임에러를오라클에서는예외 (Exception) 라고부른다. 오라클의예외 (Exception) 는크게두가지로구분된다.
More informationWINDOW FUNCTION 의이해와활용방법 엑셈컨설팅본부 / DB 컨설팅팀정동기 개요 Window Function 이란행과행간의관계를쉽게정의할수있도록만든함수이다. 윈도우함수를활용하면복잡한 SQL 들을하나의 SQL 문장으로변경할수있으며반복적으로 ACCESS 하는비효율역
WINDOW FUNCTION 의이해와활용방법 엑셈컨설팅본부 / DB 컨설팅팀정동기 개요 Window Function 이란행과행간의관계를쉽게정의할수있도록만든함수이다. 윈도우함수를활용하면복잡한 SQL 들을하나의 SQL 문장으로변경할수있으며반복적으로 ACCESS 하는비효율역시쉽게해결할수있다. 이번화이트페이퍼에서는 Window Function 중순위 RANK, ROW_NUMBER,
More informationWindows 8에서 BioStar 1 설치하기
/ 콘텐츠 테이블... PC에 BioStar 1 설치 방법... Microsoft SQL Server 2012 Express 설치하기... Running SQL 2012 Express Studio... DBSetup.exe 설정하기... BioStar 서버와 클라이언트 시작하기... 1 1 2 2 6 7 1/11 BioStar 1, Windows 8 BioStar
More informationMicrosoft Word - 07_TRIGGER.doc
DATABASE TRIGGER INTRODUCTION 프로그램단위 1 의하나인트리거 2 (Trigger) 는테이블, 뷰, 스키마또는데이터베이스에관련된 PLSQL 블록 ( 또는프로시저 ) 으로관련된특정사건 (Event) 이발생될때마다묵시적 ( 자동 ) 으로실행이이루어진다 (Fire). 트리거를생성할때관련된사건 (Event) 도함께정의되며, 실행부에서저장된프로시저
More informationMicrosoft Word - 03_SQL_CURSOR.doc
SQL Cursor SQL 커서소개오라클서버에서는 SQL 문을실행할때마다처리 (Parse, Execution) 를위한메모리공간, 즉 SQL 커서를사용하게된다. 이메모리공간은 Private SQL Area 라고도불리우며, 오라클의작업환경이 Dedicated Server 환경이냐또는 MTS(Multi- Threaded Server) 환경이냐에따라서버내에위치되는곳이다르다.
More informationMicrosoft PowerPoint - QVIZMVUMWURI.pptx
데이타베이스시스템 2011.03 충북대학교경영정보학과조완섭 (wscho@chungbuk.ac.kr) Chap. 4 SQL 질의어 C4 2 목차 - SQL2에서데이터정의, 제약조건및스키마변경 - SQL에서의기본질의 - 더복잡한 SQL 질의들 - SQL에서삽입, 삭제, 갱신구문 - SQL 뷰 - 주장으로추가적인제약조건명시 - SQL의부가적인기능들 Ch4 3 SQL
More information목차 BUG DEQUEUE 의 WAIT TIME 이 1 초미만인경우, 설정한시간만큼대기하지않는문제가있습니다... 3 BUG [qp-select-pvo] group by 표현식에있는컬럼을참조하는집합연산이존재하지않으면결괏값오류가발생할수있습니다... 4
ALTIBASE HDB 6.5.1.5.10 Patch Notes 목차 BUG-46183 DEQUEUE 의 WAIT TIME 이 1 초미만인경우, 설정한시간만큼대기하지않는문제가있습니다... 3 BUG-46249 [qp-select-pvo] group by 표현식에있는컬럼을참조하는집합연산이존재하지않으면결괏값오류가발생할수있습니다... 4 BUG-46266 [sm]
More information강의 개요
DDL TABLE 을만들자 웹데이터베이스 TABLE 자료가저장되는공간 문자자료의경우 DB 생성시지정한 Character Set 대로저장 Table 생성시 Table 의구조를결정짓는열속성지정 열 (Clumn, Attribute) 은이름과자료형을갖는다. 자료형 : http://dev.mysql.cm/dc/refman/5.1/en/data-types.html TABLE
More information90
89 3 차원공간질의를위한효율적인위상학적데이터모델의검증 Validation of Efficient Topological Data Model for 3D Spatial Queries Seokho Lee Jiyeong Lee 요약 키워드 Abstract Keywords 90 91 92 93 94 95 96 -- 3D Brep adjacency_ordering DECLARE
More information예제소스는 에서다운로드하여사용하거나툴바의 [ 새쿼리 ]( 에아래의소스를입력한다. 입력후에는앞으로실습을위해서저장해둔다. -- 실습에필요한 Madang DB 와 COMPANY DB 를모두생성한다. -- 데이터베이스생성 US
A.4 마당서점데이터베이스생성 1 마당서점의데이터베이스 Madang을생성하기위해윈도우의 [ 시작 ]-[ 모든프로그램 ]- [Microsoft SQL Server 2012]-[SQL Server Management Studio] 를선택한다. 인증을 [Windows 인증 ] 으로선택한후 < 연결 > 을클릭한다. 2 1 3 서버이름 MADANG_DB\SQLEXPRESS
More informationMicrosoft PowerPoint - 10Àå.ppt
10 장. DB 서버구축및운영 DBMS 의개념과용어를익힌다. 간단한 SQL 문법을학습한다. MySQL 서버를설치 / 운영한다. 관련용어 데이터 : 자료 테이블 : 데이터를표형식으로표현 레코드 : 테이블의행 필드또는컬럼 : 테이블의열 필드명 : 각필드의이름 데이터타입 : 각필드에입력할값의형식 학번이름주소연락처 관련용어 DB : 테이블의집합 DBMS : DB 들을관리하는소프트웨어
More informationchap 5: Trees
5. Threaded Binary Tree 기본개념 n 개의노드를갖는이진트리에는 2n 개의링크가존재 2n 개의링크중에 n + 1 개의링크값은 null Null 링크를다른노드에대한포인터로대체 Threads Thread 의이용 ptr left_child = NULL 일경우, ptr left_child 를 ptr 의 inorder predecessor 를가리키도록변경
More information歯sql_tuning2
SQL Tuning (2) SQL SQL SQL Tuning ROW(1) ROW(2) ROW(n) update ROW(2) at time 1 & Uncommitted update ROW(2) at time 2 SQLDBA> @ UTLLOCKT WAITING_SESSION TYPE MODE_REQUESTED MODE_HELD LOCK_ID1
More informationTITLE
CSED421 Database Systems Lab MySQL Basic Syntax SQL DML & DDL Data Manipulation Language SELECT UPDATE DELETE INSERT INTO Data Definition Language CREATE DATABASE ALTER DATABASE CREATE TABLE ALTER TABLE
More information歯PLSQL10.PDF
10 - SQL*Pl u s Pl / SQL - SQL*P lus 10-1 1 0.1 PL/ SQL SQL*Pl u s. SQL*P lus 10-2 1 0.2 S QL* Pl u s PL/ S QL SQL*Pl u s, Pl / SQL. - PL/ SQL (i npu t ), (s t or e ), (r un). - PL/ SQL s cr i pt,,. -
More information슬라이드 제목 없음
4.2 SQL 개요 SQL 개요 SQL은현재 DBMS 시장에서관계 DBMS가압도적인우위를차지하는데중요한요인의하나 SQL은 IBM 연구소에서 1974년에 System R이라는관계 DBMS 시제품을연구할때관계대수와관계해석을기반으로, 집단함수, 그룹화, 갱신연산등을추가하여개발된언어 1986년에 ANSI( 미국표준기구 ) 에서 SQL 표준을채택함으로써 SQL이널리사용되는데기여
More information목차 BUG offline replicator 에서유효하지않은로그를읽을경우비정상종료할수있다... 3 BUG 각 partition 이서로다른 tablespace 를가지고, column type 이 CLOB 이며, 해당 table 을 truncate
ALTIBASE HDB 6.1.1.5.6 Patch Notes 목차 BUG-39240 offline replicator 에서유효하지않은로그를읽을경우비정상종료할수있다... 3 BUG-41443 각 partition 이서로다른 tablespace 를가지고, column type 이 CLOB 이며, 해당 table 을 truncate 한뒤, hash partition
More informationALTIBASE HDB Patch Notes
ALTIBASE HDB 6.5.1.5.6 Patch Notes 목차 BUG-45643 암호화컬럼의경우, 이중화환경에서 DDL 수행시 Replication HandShake 가실패하는문제가있어수정하였습니다... 4 BUG-45652 이중화에서 Active Server 와 Standby Server 의 List Partition 테이블의범위조건이다른경우에 Handshake
More information5장 SQL 언어 Part II
5 장 SQL 언어 Part II 박창이 서울시립대학교통계학과 박창이 ( 서울시립대학교통계학과 ) 5 장 SQL 언어 Part II 1 / 26 데이터조작문 데이터검색 : SELECT 문데이터추가 : INSERT 문데이터수정 : UPDATE 문데이터삭제 : DELETE 문 박창이 ( 서울시립대학교통계학과 ) 5 장 SQL 언어 Part II 2 / 26 SELECT
More information다양한 예제로 쉽게 배우는 오라클 SQL 과 PL/SQL
다양한예제로쉽게배우는 오라클 SQL 과 PL/SQL 서진수저 9 장인덱스를배웁니다 1 1. 인덱스란무엇인가? 2 - ROWID ( 주소 ) 조회하기 SCOTT>SELECT ROWID, empno, ename 2 FROM emp 3 WHERE empno=7902 ; ROWID EMPNO ENAME --------------------------------- ----------
More information6장. SQL
학습목표 SQL이 무엇인지 개념을 설명 테이블을 생성, 변경, 제거할 할 수 있다. 수 있다. 데이터를 검색, 갱신, 삽입, 삭 제할 수 있다. 뷰, 시스템 카탈로그, 저장 프 로시저, 트리거에 대한 개념 을 설명할 수 있다. 2 목차 SECTION 01 SQL의 개요 11 SQL의 역사 12 SQL의 유형별 종류 SECTION 0 21 스키마 22 테이블
More information객관식 1. 아래의쿼리를만족하는결과를가장잘설명한것은? SELECT A.* FROM HR.EMPLOYEES A, HR.EMPLOYEES B WHERE 1=1 AND A.MANAGER_ID = B.EMPLOYEE_ID AND B.SALARY >= ANY A.SALARY;
Study Room Doc.02 : SQLD 예상문제 네이버 Cafe : 데이터베이스전문가포럼 Study Room http://cafe.naver.com/sqlpd SQLD 21 회기출문제를바탕으로작성 작성자 : 월야루 2016-09-04 객관식 1. 아래의쿼리를만족하는결과를가장잘설명한것은? SELECT A.* FROM HR.EMPLOYEES A, HR.EMPLOYEES
More informationPowerPoint Presentation
6 장 SQL (section 4-6) 목차 SECTION 01 SQL 의개요 1-1 SQL의역사 1-2 SQL의유형별종류 SECTION 02 데이터정의어 (DDL) 2-1 스키마 2-2 테이블생성 (CREATE TABLE) 2-3 테이블변경 (ALTER TABLE) 2-4 테이블제거 (DROP TABLE) 2-5 제약조건 SECTION 03 데이터조작어 (DML)
More informationMicrosoft PowerPoint - chap02-C프로그램시작하기.pptx
#include int main(void) { int num; printf( Please enter an integer "); scanf("%d", &num); if ( num < 0 ) printf("is negative.\n"); printf("num = %d\n", num); return 0; } 1 학습목표 을 작성하면서 C 프로그램의
More information쉽게 풀어쓴 C 프로그래밊
Power Java 제 27 장데이터베이스 프로그래밍 이번장에서학습할내용 자바와데이터베이스 데이터베이스의기초 SQL JDBC 를이용한프로그래밍 변경가능한결과집합 자바를통하여데이터베이스를사용하는방법을학습합니다. 자바와데이터베이스 JDBC(Java Database Connectivity) 는자바 API 의하나로서데이터베이스에연결하여서데이터베이스안의데이터에대하여검색하고데이터를변경할수있게한다.
More informationSpring Boot/JDBC JdbcTemplate/CRUD 예제
Spring Boot/JDBC JdbcTemplate/CRUD 예제 오라클자바커뮤니티 (ojc.asia, ojcedu.com) Spring Boot, Gradle 과오픈소스인 MariaDB 를이용해서 EMP 테이블을만들고 JdbcTemplate, SimpleJdbcTemplate 을이용하여 CRUD 기능을구현해보자. 마리아 DB 설치는다음 URL 에서확인하자.
More information슬라이드 1
Tadpole for DB 1. 도구개요 2. 설치및실행 4. 활용예제 1. 도구개요 도구명 소개 Tadpole for DB Tools (sites.google.com/site/tadpolefordb/) 웹기반의데이터베이스를관리하는도구 Database 스키마및데이터관리 라이선스 LGPL (Lesser General Public License) 특징 주요기능
More informationuntitled
(shared) (integrated) (stored) (operational) (data) : (DBMS) :, (database) :DBMS File & Database - : - : ( : ) - : - : - :, - DB - - -DBMScatalog meta-data -DBMS -DBMS - -DBMS concurrency control E-R,
More informationMicrosoft PowerPoint - PLSQL.ppt
SQL 의장점과단점 PL/SQL 오라클 DB 지역정보부서코드지역 1 서울 2 부산 < 장점 > (1) 사용자가이해하기쉬운단어로구성 (2) 쉽게배울수있다. (3) 복잡한로직을간단하게작성할수있다. (4) ANSI에의해문법이표준화되어있다. SQL < 단점 > Consultant 주종면 jina6678@yahoo.co.kr 1 (1) 반복처리를할수없다.(Loop)
More information슬라이드 1
17.1 데이터베이스트리거 17.2 DML 트리거 17.3 DML 트리거작성 17.4 DML 트리거관리 17.5 INSTEAD OF 트리거 17.6 NON-DML 트리거 17.1 데이터베이스트리거 데이터베이스트리거 (database trigger) 테이블에어떤조작이가해졌을때에미리지정해놓은처리를자동으로실행시키는블록 PL/SQL 블록으로작성, 오라클데이터베이스에저장
More informationePapyrus PDF Document
Goodus 기술노트 [38 회 ] Author 윤병길, 이은정 Creation Date 2009-02-27 Last Updated Version 1.0 Copyright(C) 2004 Goodus Inc. All Rights Reserved Version 변경일자변경자 ( 작성자 ) 주요내용 1 2009-02-27 윤병길, 이은정문서최초작성 Contents
More information8 장데이터베이스 8.1 기본개념 - 데이터베이스 : 데이터를조직적으로구조화한집합 (cf. 엑셀파일 ) - 테이블 : 데이터의기록형식 (cf. 엑셀시트의첫줄 ) - 필드 : 같은종류의데이터 (cf. 엑셀시트의각칸 ) - 레코드 : 데이터내용 (cf. 엑셀시트의한줄 )
8 장데이터베이스 8.1 기본개념 - 데이터베이스 : 데이터를조직적으로구조화한집합 (cf. 엑셀파일 ) - 테이블 : 데이터의기록형식 (cf. 엑셀시트의첫줄 ) - 필드 : 같은종류의데이터 (cf. 엑셀시트의각칸 ) - 레코드 : 데이터내용 (cf. 엑셀시트의한줄 ) - DDL(Data Definition Language) : show, create, drop
More information윈도우시스템프로그래밍
데이터베이스및설계 MySQL 을위한 MFC 를사용한 ODBC 프로그래밍 2012.05.10. 오병우 컴퓨터공학과금오공과대학교 http://www.apmsetup.com 또는 http://www.mysql.com APM Setup 설치발표자료참조 Department of Computer Engineering 2 DB 에속한테이블보기 show tables; 에러발생
More informationMicrosoft PowerPoint - PLSQL.ppt
PL/SQL Consultant 주종면 jina6678@yahoo.co.kr 1 - 목차 - 1장. PL/SQL 2장. 커서와에러처리 3장. 패키지와트리거 4장. PL/SQL의관리 2 1 PL-SQL 의개념 3 SQL 의장점과단점 < 장점 > 오라클 DB 지역정보부서코드지역명 1 서울 2 부산 SQL (1) 사용자가이해하기쉬운단어로구성 (2) 쉽게배울수있다.
More information10.ppt
: SQL. SQL Plus. JDBC. SQL >> SQL create table : CREATE TABLE ( ( ), ( ),.. ) SQL >> SQL create table : id username dept birth email id username dept birth email CREATE TABLE member ( id NUMBER NOT NULL
More informationLab 3. 실습문제 (Single linked list)_해답.hwp
Lab 3. Singly-linked list 의구현 실험실습일시 : 2009. 3. 30. 담당교수 : 정진우 담당조교 : 곽문상 보고서제출기한 : 2009. 4. 5. 학과 : 학번 : 성명 : 실습과제목적 : 이론시간에배운 Singly-linked list를실제로구현할수있다. 실습과제내용 : 주어진소스를이용해 Singly-linked list의각함수를구현한다.
More informationPostgreSQL 2 Uniersity of California at Berkeley ( ) 에서개발된관계형데이터베이스서버인 Ingres 가시초 ( 후에 Computer Associates 에인수됨 ) 1
ERwin 과 PostgreSQL 연동하기 인하대학교지리정보공학과데이터베이스실습 PostgreSQL 2 http://www.postgresql.org/ Uniersity of California at Berkeley (1977-1985) 에서개발된관계형데이터베이스서버인 Ingres 가시초 ( 후에 Computer Associates 에인수됨 ) 1996 년부터
More information3 S Q L A n t i p a t t e r n s Trees/intro/parent.sql CREATE TABLE Comments ( comment_id SERIAL PRIMARY KEY, parent_id BIGINT UNSIGNED, comment TEXT
3 S Q L A n t i p a t t e r n s Trees/intro/parent.sql CREATE TABLE Comments ( comment_id SERIAL PRIMARY KEY, parent_id BIGINT UNSIGNED, comment TEXT NOT NULL, FOREIGN KEY (parent_id) REFERENCES Comments(comment_id)
More information다양한 예제로 쉽게 배우는 오라클 SQL 과 PL/SQL
다양한예제로쉽게배우는 오라클 SQL 과 PL/SQL 서진수저 6 장. DML 을배웁니다 1 - SQL 명령어들 DML (Data Manipulation Language) : INSERT( 입력 ), UPDATE( 변경 ), DELETE( 삭제 ), MERGE( 병합 ) DDL (Data Definition Language) : CREATE ( 생성 ), ALTER
More informationCH04) 쿼리 (Query) 데이터베이스일반 1- 쿼리 (Query) 1) 쿼리의개념 테이블의데이터에서사용자가원하는조건에의해필드를추출하거나레코드를추출할수있는개체로즉, 여러가지방법으로데이터를보고, 변경하고, 분석할수있음 쿼리를폼, 보고서, 데이터액세스페이지등의레코드원본
1- 쿼리 (Query) 1) 쿼리의개념 테이블의데이터에서사용자가원하는조건에의해필드를추출하거나레코드를추출할수있는개체로즉, 여러가지방법으로데이터를보고, 변경하고, 분석할수있음 쿼리를폼, 보고서, 데이터액세스페이지등의레코드원본으로사용할수도있음 여러개의테이블에서서로유기적인관계를설정하여하나의테이블에서작업하는것처럼작업이가능 2- 쿼리 (Query) 종류 1) 선택쿼리가장일반적인방법형태의쿼리
More information[ 목차 ] 5.1 데이터베이스프로그래밍개념 5.2 T-SQL T-SQL 문법 5.3 JAVA 프로그래밍 2
5 장 SQL 응용 데이터베이스실험실 1 [ 목차 ] 5.1 데이터베이스프로그래밍개념 5.2 T-SQL 5.2.1 T-SQL 문법 5.3 JAVA 프로그래밍 2 5.1 데이터베이스프로그래밍개념 프로그래밍 이라고하면프로그램소스를설계하고, 작성하고, 디버깅하는과정을말한다. 프로그램 혹은소프트웨어는컴퓨터에서주어진작업을하는명령어나열을말한다. 데이터베이스프로그래밍은명확한정의는없지만데이터베이스에데이터를정의하고,
More informationORANGE FOR ORACLE V4.0 INSTALLATION GUIDE (Online Upgrade) ORANGE CONFIGURATION ADMIN O
Orange for ORACLE V4.0 Installation Guide ORANGE FOR ORACLE V4.0 INSTALLATION GUIDE...1 1....2 1.1...2 1.2...2 1.2.1...2 1.2.2 (Online Upgrade)...11 1.3 ORANGE CONFIGURATION ADMIN...12 1.3.1 Orange Configuration
More informationSQL
데이터베이스및 SQL 언어의기초 박창이 서울시립대학교통계학과 박창이 ( 서울시립대학교통계학과 ) 데이터베이스및 SQL 언어의기초 1 / 36 Part I 데이터베이스 박창이 ( 서울시립대학교통계학과 ) 데이터베이스및 SQL 언어의기초 2 / 36 데이터의구성및표현 개체 (entity): DB가표현하려는유형 / 무형적정보의대상속성 (attribute): 개체가갖는특성도메인
More information슬라이드 제목 없음
MS SQL Server 마이크로소프트사가윈도우운영체제를기반으로개발한관계 DBMS 모바일장치에서엔터프라이즈데이터시스템에이르는다양한플랫폼에서운영되는통합데이터관리및분석솔루션 2 MS SQL Server 개요 3.1 MS SQL Server 개요 클라이언트-서버모델을기반으로하는관계 DBMS 로서윈도우계열의운영체제에서만동작함 오라클관계 DBMS 보다가격이매우저렴한편이고,
More informationTablespace On-Offline 테이블스페이스 온라인/오프라인
2018/11/10 12:06 1/2 Tablespace On-Offline 테이블스페이스온라인 / 오프라인 목차 Tablespace On-Offline 테이블스페이스온라인 / 오프라인... 1 일반테이블스페이스 (TABLESPACE)... 1 일반테이블스페이스생성하기... 1 테이블스페이스조회하기... 1 테이블스페이스에데이터파일 (DATA FILE) 추가
More informationMicrosoft PowerPoint - 3장-MS SQL Server.ppt [호환 모드]
MS SQL Server 마이크로소프트사가윈도우운영체제를기반으로개발한관계 DBMS 모바일장치에서엔터프라이즈데이터시스템에이르는다양한플랫폼에서운영되는통합데이터관리및분석솔루션 2 MS SQL Server 개요 3.1 MS SQL Server 개요 클라이언트-서버모델을기반으로하는관계 DBMS로서윈도우계열의운영체제에서만동작함 오라클관계 DBMS보다가격이매우저렴한편이고,
More informationBind Peeking 한계에따른 Adaptive Cursor Sharing 등장 엑셈컨설팅본부 /DB 컨설팅팀김철환 Bind Peeking 의한계 SQL 이최초실행되면 3 단계의과정을거치게되는데 Parsing 단계를거쳐 Execute 하고 Fetch 의과정을통해데이터
Bind Peeking 한계에따른 Adaptive Cursor Sharing 등장 엑셈컨설팅본부 /DB 컨설팅팀김철환 Bind Peeking 의한계 SQL 이최초실행되면 3 단계의과정을거치게되는데 Parsing 단계를거쳐 Execute 하고 Fetch 의과정을통해데이터를사용자에게전송하게되며 Parsing 단계에서실행계획이생성된다. Bind 변수를사용하는 SQL
More information예제 1.1 ( 관계연산자 ) >> A=1:9, B=9-A A = B = >> tf = A>4 % 4 보다큰 A 의원소들을찾을경우 tf = >> tf = (A==B) % A
예제 1.1 ( 관계연산자 ) >> A=1:9, B=9-A A = 1 2 3 4 5 6 7 8 9 B = 8 7 6 5 4 3 2 1 0 >> tf = A>4 % 4 보다큰 A 의원소들을찾을경우 tf = 0 0 0 0 1 1 1 1 1 >> tf = (A==B) % A 의원소와 B 의원소가똑같은경우를찾을때 tf = 0 0 0 0 0 0 0 0 0 >> tf
More informationLec. 2: MySQL and RMySQL
1 / 26 Lec. 2: MySQL and RMySQL Instructor: SANG-HOON CHO DEPT. OF STATISTICS AND ACTUARIAL SCIENCES Soongsil University 1. Introduction 2 / 26 이번강의에서는 MySQL 관계형데이터베이스관리시스템 (RDBMS, Relational Database
More information빅데이터분산컴퓨팅-5-수정
Apache Hive 빅데이터분산컴퓨팅 박영택 Apache Hive 개요 Apache Hive 는 MapReduce 기반의 High-level abstraction HiveQL은 SQL-like 언어를사용 Hadoop 클러스터에서 MapReduce 잡을생성함 Facebook 에서데이터웨어하우스를위해개발되었음 현재는오픈소스인 Apache 프로젝트 Hive 유저를위한
More information다양한 예제로 쉽게 배우는 오라클 SQL 과 PL/SQL
다양핚예제로쉽게배우는 오라클 SQL 과 PL/SQL 서진수저 10 장 view 를배웁니다 1 - View 란가상의테이블이다! 2 1. 단순 View (Simple View) SCOTT>CONN / AS SYSDBA; SYS>GRANT CREATE VIEW TO scott ; CREATE [OR REPLACE] [ FORCE NOFORCE] VIEW view
More information강의 개요
정규화와 SELECT (II) 웹데이터베이스 학과 학생 과목 학과 지도교수 학과학번성명 수강과목 담당교수 A 김수정 A 0001 고길동 성질이론 김수정 B 허영만 A 0002 둘리 한식의멋 허영만 C 강풀 B 0003 희동이 심리학의이해 강풀 과목 _ 성적 학번 수강과목 성적 0001 성질이론 A 0001 한식의멋 C 0002 성질이론 A 0002 한식의멋
More information슬라이드 1
Pairwise Tool & Pairwise Test NuSRS 200511305 김성규 200511306 김성훈 200614164 김효석 200611124 유성배 200518036 곡진화 2 PICT Pairwise Tool - PICT Microsoft 의 Command-line 기반의 Free Software www.pairwise.org 에서다운로드후설치
More informationPowerPoint 프레젠테이션
MySQL - 명령어 1. 데이터베이스관련명령 2. 데이터베이스테이블관련명령 3. SQL 명령의일괄실행 4. 레코드관련명령 5. 데이터베이스백업및복원명령 1. 데이터베이스관련명령 데이터베이스접속명령 데이터베이스접속명령 mysql -u계정 -p비밀번호데이터베이스명 C: > mysql -ukdhong p1234 kdhong_db 데이터베이스생성명령 데이터베이스생성명령
More informationPowerPoint Presentation
Computer Science Suan Lee - Computer Science - 06 데이터베이스 1 06 데이터베이스 - Computer Science - 06 데이터베이스 2 목차 1. 데이터베이스의개요 2. 데이터모델 3. 관계형데이터베이스 4. SQL 5. 모바일데이터베이스 - Computer Science - 06 데이터베이스 3 데이터베이스의개념
More informationLab 4. 실습문제 (Circular singly linked list)_해답.hwp
Lab 4. Circular singly-linked list 의구현 실험실습일시 : 2009. 4. 6. 담당교수 : 정진우 담당조교 : 곽문상 보고서제출기한 : 2009. 4. 12. 학과 : 학번 : 성명 : 실습과제목적 : 이론시간에배운 Circular Singly-linked list를실제로구현할수있다. 실습과제내용 : 주어진소스를이용해 Circular
More informationMicrosoft Word - PLC제어응용-2차시.doc
과정명 PLC 제어응용차시명 2 차시. 접점명령 학습목표 1. 연산개시명령 (LOAD, LOAD NOT) 에대하여설명할수있다. 2. 직렬접속명령 (AND, AND NOT) 에대하여설명할수있다. 3. 병렬접속명령 (OR, OR NOT) 에대하여설명할수있다. 4.PLC의접점명령을가지고간단한프로그램을작성할수있다. 학습내용 1. 연산개시명령 1) 연산개시명령 (LOAD,
More informationMicrosoft PowerPoint - ch09 - 연결형리스트, Stack, Queue와 응용 pm0100
2015-1 프로그래밍언어 9. 연결형리스트, Stack, Queue 2015 년 5 월 4 일 교수김영탁 영남대학교공과대학정보통신공학과 (Tel : +82-53-810-2497; Fax : +82-53-810-4742 http://antl.yu.ac.kr/; E-mail : ytkim@yu.ac.kr) 연결리스트 (Linked List) 연결리스트연산 Stack
More informationvRealize Automation용 VMware Remote Console - VMware
vrealize Automation 용 VMware Remote Console VMware Remote Console 9.0 이문서는새버전으로교체되기전까지나열된각제품버전및모든이후버전을지원합니다. 이문서에대한최신버전을확인하려면 http://www.vmware.com/kr/support/pubs 를참조하십시오. KO-002230-00 vrealize Automation
More information문서 템플릿
HDSI 툴분석 [sql injection 기술명세서 ] Sql injection 기술명세서 Ver. 0.01 이문서는 sql injection 기술명세가범위입니다. Copyrights Copyright 2009 by CanvasTeam@SpeeDroot( 장경칩 ) All Rights Reserved. 장경칩의사전승인없이본내용의전부또는일부에대한복사, 전재,
More information윈도우시스템프로그래밍
데이타베이스 MySQL 을위한 MFC 를사용한 ODBC 프로그래밍 2013.05.15. 오병우 컴퓨터공학과금오공과대학교 http://www.apmsetup.com 또는 http://www.mysql.com APM Setup 설치발표자료참조 Department of Computer Engineering 2 DB 에속한테이블보기 show tables; 에러발생
More informationMicrosoft Word - 기술노트[19회] Flashback.doc
Goodus 기술노트 [19 회 ] Flashback Author 권웅원, 나지혜 Creation Date 2007-04-25 Last Updated 2007-04-25 Version 1.0 Copyright(C) 2004 Goodus Inc. All Rights Reserved Version 변경일자 변경자 ( 작성자 ) 주요내용 1 2007-04-25 권웅원,
More informationPowerPoint Template
JavaScript 회원정보 입력양식만들기 HTML & JavaScript Contents 1. Form 객체 2. 일반적인입력양식 3. 선택입력양식 4. 회원정보입력양식만들기 2 Form 객체 Form 객체 입력양식의틀이되는 태그에접근할수있도록지원 Document 객체의하위에위치 속성들은모두 태그의속성들의정보에관련된것
More informationRHEV 2.2 인증서 만료 확인 및 갱신
2018/09/28 03:56 1/2 목차... 1 인증서 확인... 1 인증서 종류와 확인... 4 RHEVM CA... 5 FQDN 개인 인증서... 5 레드햇 인증서 - 코드 서명 인증서... 6 호스트 인증... 7 참고사항... 8 관련링크... 8 AllThatLinux! - http://allthatlinux.com/dokuwiki/ rhev_2.2_
More informationPowerPoint Presentation
FORENSIC INSIGHT; DIGITAL FORENSICS COMMUNITY IN KOREA SQL Server Forensic AhnLab A-FIRST Rea10ne unused6@gmail.com Choi Jinwon Contents 1. SQL Server Forensic 2. SQL Server Artifacts 3. Database Files
More information[Brochure] KOR_TunA
LG CNS LG CNS APM (TunA) LG CNS APM (TunA) 어플리케이션의 성능 개선을 위한 직관적이고 심플한 APM 솔루션 APM 이란? Application Performance Management 란? 사용자 관점 그리고 비즈니스 관점에서 실제 서비스되고 있는 어플리케이션의 성능 관리 체계입니다. 이를 위해서는 신속한 장애 지점 파악 /
More informationMicrosoft Word - 02_PLSQL_BLOCK_STRUCTURE.doc
PL/SQL BLOCK PL/SQL 블록 기본구조 PL/SQL 은기본적으로블록 (BLOCK) 구조를가지고있다. 블록의기본적인구성은선언부 (DECLARE), 실행부 (BEGIN), 예외처리부 (EXCEPTION) 로구성되어있다. PL/SQL 블록은그블록안에블록을포함할수있는데포함된블록을 Nested Block 이라한다. 블록의유형에는크게 Anonymous PL/SQL
More informationMicrosoft PowerPoint - Oracle Data Access Pattern.ppt
Special Key Note Oracle Data Access Pattern ( 주 ) 오픈메이드컨설팅 오동규수석컨설턴트 1 What is Data Access Pattern? > 데이터를 I/O 하는방식 Index Scan Full Table Scan Rowid 2 Why is The Pattern Important? >SQL 의성능을좌지우지함. >SQL
More information- JPA를사용하는경우의스프링설정파일에다음을기술한다. <bean id="entitymanagerfactory" class="org.springframework.orm.jpa.localentitymanagerfactorybean" p:persistenceunitname=
JPA 와 Hibernate - 스프링의 JDBC 대신에 JPA를이용한 DB 데이터검색작업 - JPA(Java Persistence API) 는자바의 O/R 매핑에대한표준지침이며, 이지침에따라설계된소프트웨어를 O/R 매핑프레임워크 라고한다. - O/R 매핑 : 객체지향개념인자바와관계개념인 DB 테이블간에상호대응을시켜준다. 즉, 객체지향언어의인스턴스와관계데이터베이스의레코드를상호대응시킨다.
More informationMicrosoft PowerPoint - ch07_데이터베이스 언어 SQL.pptx
05-01 SQL의소개 SQL을이용한데이터정의 SQL을이용한데이터조작 뷰 삽입 SQL 학습목표 SQL의역할을이해하고, 이를기능별로분류해본다. SQL의데이터정의기능을예제를통해익힌다. SQL의데이터조작기능을예제를통해익힌다. 뷰의개념과장점을이해한다. 삽입 SQL의역할을이해한다. 2 01 SQL 의소개 SQL (Structured Query Language) 의미
More informationTcl의 문법
월, 01/28/2008-20:50 admin 은 상당히 단순하고, 커맨드의 인자를 스페이스(공백)로 단락을 짓고 나열하는 정도입니다. command arg1 arg2 arg3... 한행에 여러개의 커맨드를 나열할때는, 세미콜론( ; )으로 구분을 짓습니다. command arg1 arg2 arg3... ; command arg1 arg2 arg3... 한행이
More information(Microsoft Word - PLSQL\300\314\266\365.doc)
오라클 PL/SQL 제를다른홈페이지에기재할경우에는출처를꼭밝혀주세요. (http://www.oracleclub.com) 1 PL/SQL 의개요 1.1 PLSQL 이란? [ 2002/01/20 ] 1.2 PL/SQL Block 구조 [ 2002/05/09 ] 1.3 PL/SQL 블럭의유형 [ 2002/05/09 ] 2 프로시저 (PROCEDURE) 와함수 (FUNCTION)
More informationRDB개요.ppt
1 2 3 < > 1 SQL SQL 2 SQL 3 column DEPT DEPT# DNAME BUDGET D1 D2 D3 Marketing Development Research 10M 12M 5M tuple EMP EMP# ENAME DEPT# SALARY D1 40 D1 45 E1 E2 E3 Lopez Cheng Finzi D2 30 E4 Satio D2
More informationMF Driver Installation Guide
Korean MF 드라이버 설치설명서 사용자 소프트웨어 CD-ROM... 드라이버 및 소프트웨어 정보...1 지원되는 운영 체제...1 MF 드라이버 및 MF Toolbox 설치... [쉬운 설치]를 사용한 설치...2 [사용자 정의 설치]를 사용한 설치...10 USB 케이블 연결(USB를 이용해 연결하는 경우만)...20 설치 결과 확인...21 온라인
More informationMicrosoft Word - [Unioneinc] 특정컬럼의 통계정보 갱신_ _ldh.doc
특정 Column 통계정보갱신가이드 유니원아이앤씨 DB 사업부이대혁 2015 년 03 월 02 일 문서정보프로젝트명서브시스템명 버전 1.0 문서명 특정 Column 통계정보갱신가이드 작성일 2015-03-02 작성자 DB사업부이대혁사원 최종수정일 2015-03-02 문서번호 UNIONE-201503021500-LDH 재개정이력 일자내용수정인버전 문서배포이력
More informationuntitled
PowerBuilder 連 Microsoft SQL Server database PB10.0 PB9.0 若 Microsoft SQL Server 料 database Profile MSS 料 (Microsoft SQL Server database interface) 行了 PB10.0 了 Sybase 不 Microsoft 料 了 SQL Server 料 PB10.0
More informationPowerPoint 프레젠테이션
실습 1 배효철 th1g@nate.com 1 목차 조건문 반복문 System.out 구구단 모양만들기 Up & Down 2 조건문 조건문의종류 If, switch If 문 조건식결과따라중괄호 { 블록을실행할지여부결정할때사용 조건식 true 또는 false값을산출할수있는연산식 boolean 변수 조건식이 true이면블록실행하고 false 이면블록실행하지않음 3
More information금오공대 컴퓨터공학전공 강의자료
C 프로그래밍프로젝트 Chap 14. 포인터와함수에대한이해 2013.10.09. 오병우 컴퓨터공학과 14-1 함수의인자로배열전달 기본적인인자의전달방식 값의복사에의한전달 val 10 a 10 11 Department of Computer Engineering 2 14-1 함수의인자로배열전달 배열의함수인자전달방식 배열이름 ( 배열주소, 포인터 ) 에의한전달 #include
More information윈백및업그레이드 Tibero Flashback 가이드
Tibero Flashback 가이드 2014. 05. 09. 목차 1. FLASHBACK 소개... 3 1.1. Flashback 개요... 3 1.2. Flashback 기능... 3 2. FLASHBACK 기능... 3 2.1. FLASHBACK QUERY... 3 2.1.1. FLASHBACK QUERY 개요... 3 2.1.2. FLASHBACK QUERY
More information