PostgreSQL 이나 MySQL 을 쓰다 오면 CREATE SCHEMA app; 으로 빈 이름공간을 만들 수 있다고 생각하기 쉽다. Oracle 은 그렇지 않다. Oracle 의 스키마는 사용자가 소유한 객체의 집합이고, 사용자를 만들면 같은 이름의 스키마가 함께 생긴다.
Oracle 의 CREATE SCHEMA 는 이름공간을 만드는 문장이 아니라, 여러 DDL 을 한 트랜잭션으로 묶어 실행하는 문장이다. 그래서 다음 두 오류를 만난다.
| 오류 | 뜻 |
|---|---|
ORA-02420: missing schema authorization clause |
AUTHORIZATION 절을 빠뜨렸다 |
ORA-02421: missing or invalid schema authorization identifier |
지정한 사용자가 없거나 현재 접속 사용자와 다르다 |
CREATE SCHEMA 의 AUTHORIZATION 뒤에는 이미 존재하는 사용자를, 그것도 보통은 현재 접속한 사용자를 적어야 한다. 원래 용도는 다음과 같다.
CREATE SCHEMA AUTHORIZATION app_owner
CREATE TABLE t_sample (id NUMBER)
CREATE VIEW v_sample AS SELECT id FROM t_sample;
새 이름공간을 만들려는 것이라면 사용자를 만든다.
CREATE USER app_owner IDENTIFIED BY "${PASSWORD}"
DEFAULT TABLESPACE users
TEMPORARY TABLESPACE temp
QUOTA UNLIMITED ON users;
GRANT CREATE SESSION TO app_owner;
GRANT CREATE TABLE, CREATE VIEW, CREATE SEQUENCE, CREATE PROCEDURE TO app_owner;
GRANT CONNECT, RESOURCE TO app_owner; 로 한 번에 주는 예시가 흔하지만, 두 롤이 담고 있는 권한은 버전마다 달라진다. 12c 이후 RESOURCE 롤에는 UNLIMITED TABLESPACE 가 들어 있지 않으므로 할당량(QUOTA)을 따로 줘야 테이블을 만들 수 있다. 운영 계정에는 필요한 시스템 권한만 골라 주는 편이 낫다.
12c 이후 컨테이너 데이터베이스에서는 일반 사용자 이름이 C## 으로 시작해야 한다. 응용 계정은 CDB 가 아니라 PDB 에 접속해서 만든다.
ALTER SESSION SET CONTAINER = FREEPDB1;
CREATE USER app_owner IDENTIFIED BY "${PASSWORD}";
CDB$ROOT 에 붙은 채 CREATE USER app_owner 를 실행하면 ORA-65096: invalid common user or role name 이 난다.
SELECT username, account_status, default_tablespace
FROM dba_users
WHERE username = 'APP_OWNER';
SELECT USER FROM dual;
SELECT SYS_CONTEXT('USERENV', 'CON_NAME') AS pdb FROM dual;
따옴표 없이 적은 식별자는 대문자로 저장된다. dba_users 조회에서 소문자로 찾으면 나오지 않는다.
ORA-00906: missing left parenthesis 는 여는 괄호가 필요한 자리에 없다는 뜻이다. CREATE TABLE 에서 컬럼 목록을 괄호로 감싸지 않았거나, VARCHAR2 뒤 길이 지정을 빠뜨렸을 때 흔하다.
-- 틀림
CREATE TABLE t_sample id NUMBER;
-- 맞음
CREATE TABLE t_sample (id NUMBER);