------------------------------------------------------------------------------ -- 0. User Creation -- パスワードは環境に合わせて変更してください。 ------------------------------------------------------------------------------ DROP USER demo CASCADE; CREATE USER demo IDENTIFIED BY change_password DEFAULT TABLESPACE users TEMPORARY TABLESPACE temp QUOTA UNLIMITED ON users; GRANT CREATE SESSION, CREATE TABLE, CREATE VIEW, CREATE PROCEDURE, CREATE SEQUENCE, CREATE TRIGGER, CREATE TYPE TO demo; DROP END USER nsato; DROP END USER mtanaka; DROP END USER myamamoto; CREATE END USER nsato IDENTIFIED BY change_password; CREATE END USER mtanaka IDENTIFIED BY change_password; CREATE END USER myamamoto IDENTIFIED BY change_password; ------------------------------------------------------------------------------ -- 1. TABLES ------------------------------------------------------------------------------ DROP TABLE demo.exam_results; DROP TABLE demo.patients; DROP TABLE demo.healthcare_workers; CREATE TABLE demo.healthcare_workers ( worker_id NUMBER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, username VARCHAR2(50) NOT NULL, firstname VARCHAR2(100) NOT NULL, lastname VARCHAR2(100) NOT NULL, worker_name VARCHAR2(100) NOT NULL, worker_role VARCHAR2(20) NOT NULL, department VARCHAR2(100) NOT NULL, email VARCHAR2(200), created_at TIMESTAMP DEFAULT SYSTIMESTAMP NOT NULL ); CREATE TABLE demo.patients ( patient_id NUMBER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, healthcare_worker_id NUMBER NOT NULL, patient_name VARCHAR2(100) NOT NULL, sex CHAR(1), birth_date DATE NOT NULL, phone VARCHAR2(30), prefecture VARCHAR2(50), created_at TIMESTAMP DEFAULT SYSTIMESTAMP NOT NULL ); CREATE TABLE demo.exam_results ( exam_id NUMBER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, patient_id NUMBER NOT NULL, exam_date DATE NOT NULL, height_cm NUMBER(5,1) NOT NULL, weight_kg NUMBER(5,1) NOT NULL, systolic_bp NUMBER(4) NOT NULL, diastolic_bp NUMBER(4) NOT NULL, hba1c NUMBER(4,2) NOT NULL, ldl NUMBER(5,1) NOT NULL, triglyceride NUMBER(6,1) NOT NULL, fasting_glucose NUMBER(5,1) NOT NULL, smoking_status VARCHAR2(20), notes VARCHAR2(4000), bmi NUMBER(4,1) GENERATED ALWAYS AS (ROUND(weight_kg / POWER(height_cm / 100, 2), 1)) VIRTUAL ); ------------------------------------------------------------------------------ -- 2. SAMPLE DATA ------------------------------------------------------------------------------ INSERT INTO demo.healthcare_workers (worker_id, username, firstname, lastname, worker_name, worker_role, department, email) VALUES (1, 'nsato', 'naoto', 'sato', '佐藤 直人', 'DOCTOR', '内科', 'sato.naoto@hospital.example'); INSERT INTO demo.healthcare_workers (worker_id, username, firstname, lastname, worker_name, worker_role, department, email) VALUES (2, 'rsuzuki', 'rina', 'suzuki', '鈴木 里奈', 'DOCTOR', '糖尿病内科', 'suzuki.rina@hospital.example'); INSERT INTO demo.healthcare_workers (worker_id, username, firstname, lastname, worker_name, worker_role, department, email) VALUES (3, 'mtanaka', 'megumi', 'tanaka', '田中 恵', 'STAFF', '医事課', 'tanaka.megumi@hospital.example'); INSERT INTO demo.healthcare_workers (worker_id, username, firstname, lastname, worker_name, worker_role, department, email) VALUES (4, 'ykondo', 'yuki', 'kondo', '近藤 由紀', 'STAFF', '受付', 'kondo.yuki@hospital.example'); INSERT INTO demo.healthcare_workers (worker_id, username, firstname, lastname, worker_name, worker_role, department, email) VALUES (5, 'myamamoto', 'makoto', 'yamamoto', '山本 誠', 'STUDENT', '医学部実習', 'yamamoto.makoto@hospital.example'); INSERT INTO demo.healthcare_workers (worker_id, username, firstname, lastname, worker_name, worker_role, department, email) VALUES (6, 'ytakahashi', 'yu', 'takahashi', '高橋 悠', 'STUDENT', '医学部実習', 'takahashi.yu@hospital.example'); INSERT INTO demo.patients (patient_id, healthcare_worker_id, patient_name, sex, birth_date, phone, prefecture) VALUES (1, 1, '山田 太郎', 'M', DATE '1982-04-12', '090-1111-0001', '東京都'); INSERT INTO demo.patients (patient_id, healthcare_worker_id, patient_name, sex, birth_date, phone, prefecture) VALUES (2, 1, '田中 花子', 'F', DATE '1978-09-03', '090-1111-0002', '神奈川県'); INSERT INTO demo.patients (patient_id, healthcare_worker_id, patient_name, sex, birth_date, phone, prefecture) VALUES (3, 2, '佐々木 一郎', 'M', DATE '1990-01-21', '090-1111-0003', '埼玉県'); INSERT INTO demo.patients (patient_id, healthcare_worker_id, patient_name, sex, birth_date, phone, prefecture) VALUES (4, 2, '小林 美咲', 'F', DATE '1969-11-30', '090-1111-0004', '千葉県'); INSERT INTO demo.patients (patient_id, healthcare_worker_id, patient_name, sex, birth_date, phone, prefecture) VALUES (5, 5, '中村 健', 'M', DATE '1988-06-18', '090-1111-0005', '東京都'); INSERT INTO demo.patients (patient_id, healthcare_worker_id, patient_name, sex, birth_date, phone, prefecture) VALUES (6, 6, '渡辺 愛', 'F', DATE '1995-02-14', '090-1111-0006', '大阪府'); -- 山田 太郎(3件) INSERT INTO demo.exam_results (patient_id, exam_date, height_cm, weight_kg, systolic_bp, diastolic_bp, hba1c, ldl, triglyceride, fasting_glucose, smoking_status, notes) VALUES (1, DATE '2025-11-10', 170.0, 84.0, 142, 90, 6.1, 158.0, 220.0, 112.0, 'Former', '前回よりやや悪化。'); INSERT INTO demo.exam_results (patient_id, exam_date, height_cm, weight_kg, systolic_bp, diastolic_bp, hba1c, ldl, triglyceride, fasting_glucose, smoking_status, notes) VALUES (1, DATE '2026-02-10', 170.0, 85.5, 145, 92, 6.3, 160.0, 230.0, 115.0, 'Former', '生活習慣改善指導。'); INSERT INTO demo.exam_results (patient_id, exam_date, height_cm, weight_kg, systolic_bp, diastolic_bp, hba1c, ldl, triglyceride, fasting_glucose, smoking_status, notes) VALUES (1, DATE '2026-05-10', 170.0, 86.5, 148, 94, 6.5, 162.0, 245.0, 118.0, 'Former', '腹囲増加。再検査推奨。'); -- 田中 花子(2件) INSERT INTO demo.exam_results (patient_id, exam_date, height_cm, weight_kg, systolic_bp, diastolic_bp, hba1c, ldl, triglyceride, fasting_glucose, smoking_status, notes) VALUES (2, DATE '2025-11-10', 158.0, 59.0, 132, 84, 5.7, 142.0, 176.0, 99.0, 'Never', '軽度高値あり。'); INSERT INTO demo.exam_results (patient_id, exam_date, height_cm, weight_kg, systolic_bp, diastolic_bp, hba1c, ldl, triglyceride, fasting_glucose, smoking_status, notes) VALUES (2, DATE '2026-05-10', 158.0, 60.0, 136, 86, 5.8, 148.0, 182.0, 102.0, 'Never', '経過観察。生活習慣改善指導。'); -- 佐々木 一郎(2件) INSERT INTO demo.exam_results (patient_id, exam_date, height_cm, weight_kg, systolic_bp, diastolic_bp, hba1c, ldl, triglyceride, fasting_glucose, smoking_status, notes) VALUES (3, DATE '2025-11-12', 176.0, 69.0, 124, 80, 5.5, 108.0, 101.0, 94.0, 'Never', '前回も概ね正常。'); INSERT INTO demo.exam_results (patient_id, exam_date, height_cm, weight_kg, systolic_bp, diastolic_bp, hba1c, ldl, triglyceride, fasting_glucose, smoking_status, notes) VALUES (3, DATE '2026-05-11', 176.0, 68.0, 122, 78, 5.4, 104.0, 98.0, 92.0, 'Never', '異常所見なし。'); -- 小林 美咲(3件) INSERT INTO demo.exam_results (patient_id, exam_date, height_cm, weight_kg, systolic_bp, diastolic_bp, hba1c, ldl, triglyceride, fasting_glucose, smoking_status, notes) VALUES (4, DATE '2025-11-12', 155.0, 63.0, 130, 82, 6.8, 168.0, 198.0, 138.0, 'Current', '高血糖傾向。'); INSERT INTO demo.exam_results (patient_id, exam_date, height_cm, weight_kg, systolic_bp, diastolic_bp, hba1c, ldl, triglyceride, fasting_glucose, smoking_status, notes) VALUES (4, DATE '2026-02-12', 155.0, 63.5, 131, 83, 7.0, 169.0, 205.0, 142.0, 'Current', '糖尿病精査推奨。'); INSERT INTO demo.exam_results (patient_id, exam_date, height_cm, weight_kg, systolic_bp, diastolic_bp, hba1c, ldl, triglyceride, fasting_glucose, smoking_status, notes) VALUES (4, DATE '2026-05-11', 155.0, 64.0, 132, 84, 7.2, 170.0, 210.0, 146.0, 'Current', 'HbA1c高値。糖尿病精査推奨。'); -- 中村 健(2件) INSERT INTO demo.exam_results (patient_id, exam_date, height_cm, weight_kg, systolic_bp, diastolic_bp, hba1c, ldl, triglyceride, fasting_glucose, smoking_status, notes) VALUES (5, DATE '2025-11-13', 172.0, 79.0, 126, 80, 5.8, 134.0, 205.0, 101.0, 'Former', '中性脂肪高め。'); INSERT INTO demo.exam_results (patient_id, exam_date, height_cm, weight_kg, systolic_bp, diastolic_bp, hba1c, ldl, triglyceride, fasting_glucose, smoking_status, notes) VALUES (5, DATE '2026-05-12', 172.0, 81.0, 128, 82, 5.9, 138.0, 230.0, 105.0, 'Former', '運動・食事指導対象。'); -- 渡辺 愛(2件) INSERT INTO demo.exam_results (patient_id, exam_date, height_cm, weight_kg, systolic_bp, diastolic_bp, hba1c, ldl, triglyceride, fasting_glucose, smoking_status, notes) VALUES (6, DATE '2025-11-14', 160.0, 54.0, 118, 76, 5.3, 96.0, 88.0, 90.0, 'Never', '概ね正常。'); INSERT INTO demo.exam_results (patient_id, exam_date, height_cm, weight_kg, systolic_bp, diastolic_bp, hba1c, ldl, triglyceride, fasting_glucose, smoking_status, notes) VALUES (6, DATE '2026-05-13', 160.0, 55.0, 120, 78, 5.4, 100.0, 92.0, 92.0, 'Never', '経過観察。'); COMMIT; ------------------------------------------------------------------------------ -- 3. PACKAGE / END USER CONTEXT ------------------------------------------------------------------------------ DROP DATA GRANT demo.hospital_ctx_read_grant; DROP END USER CONTEXT demo.hospital_ctx; DROP PACKAGE demo.ctx_pkg; CREATE OR REPLACE PACKAGE demo.ctx_pkg AS PROCEDURE init_user_context; END; / CREATE OR REPLACE PACKAGE BODY demo.ctx_pkg AS PROCEDURE init_user_context IS sql_stmt VARCHAR2(4000); BEGIN sql_stmt := ' UPDATE END_USER_CONTEXT t SET t.CONTEXT.healthcare_worker_id = ( SELECT hw.worker_id FROM demo.healthcare_workers hw WHERE UPPER(hw.username) = UPPER(ORA_END_USER_CONTEXT.username) ) WHERE owner = ''DEMO'' AND name = ''HOSPITAL_CTX'' '; EXECUTE IMMEDIATE sql_stmt; END; END; / CREATE OR REPLACE END USER CONTEXT demo.hospital_ctx USING JSON SCHEMA '{ "type":"object", "properties":{ "healthcare_worker_id":{ "type":"integer", "o:onFirstRead":"DEMO.ctx_pkg.init_user_context" } } }'; ------------------------------------------------------------------------------ -- 4. DATA ROLES / ROLE GRANTS ------------------------------------------------------------------------------ DROP ROLE hospital_context_admin; DROP ROLE db_role; CREATE OR REPLACE DATA ROLE doctor_role; CREATE OR REPLACE DATA ROLE staff_role; CREATE OR REPLACE DATA ROLE student_role; GRANT DATA ROLE doctor_role TO nsato; GRANT DATA ROLE staff_role TO mtanaka; GRANT DATA ROLE student_role TO myamamoto; CREATE ROLE db_role; GRANT CREATE SESSION TO db_role; GRANT db_role TO doctor_role, staff_role, student_role; CREATE ROLE hospital_context_admin; GRANT EXECUTE ON demo.ctx_pkg TO hospital_context_admin; GRANT hospital_context_admin TO doctor_role, staff_role, student_role; GRANT UPDATE ANY END USER CONTEXT TO demo; ------------------------------------------------------------------------------ -- 5. DATA GRANTS ------------------------------------------------------------------------------ CREATE OR REPLACE DATA GRANT demo.hospital_ctx_read_grant AS SELECT ON SYS.END_USER_CONTEXT WHERE owner = 'DEMO' AND name = 'HOSPITAL_CTX' TO doctor_role, staff_role, student_role; ------------------------------------------------------------------------------ -- Doctor : 全テーブル参照可能 ------------------------------------------------------------------------------ CREATE OR REPLACE DATA GRANT lc_doctor_workers_grant AS SELECT ON demo.healthcare_workers TO doctor_role; CREATE OR REPLACE DATA GRANT lc_doctor_patients_grant AS SELECT ON demo.patients TO doctor_role; CREATE OR REPLACE DATA GRANT lc_doctor_exam_results_grant AS SELECT ON demo.exam_results TO doctor_role; ------------------------------------------------------------------------------ -- Staff : 自分の情報 + 患者一覧 ------------------------------------------------------------------------------ CREATE OR REPLACE DATA GRANT lc_staff_workers_self_grant AS SELECT ON demo.healthcare_workers WHERE LOWER(username) = LOWER(ORA_END_USER_CONTEXT.username) TO staff_role; CREATE OR REPLACE DATA GRANT lc_staff_patients_grant AS SELECT ON demo.patients TO staff_role; ------------------------------------------------------------------------------ -- Student : 自分の情報 + 自分の担当患者 + 検査結果 ------------------------------------------------------------------------------ CREATE OR REPLACE DATA GRANT lc_student_workers_self_grant AS SELECT ON demo.healthcare_workers WHERE LOWER(username) = LOWER(ORA_END_USER_CONTEXT.username) TO student_role; CREATE OR REPLACE DATA GRANT lc_student_patients_grant AS SELECT ON demo.patients WHERE healthcare_worker_id = ORA_END_USER_CONTEXT.demo.hospital_ctx.healthcare_worker_id TO student_role; CREATE OR REPLACE DATA GRANT lc_student_exam_results_grant AS SELECT ON demo.exam_results WHERE patient_id IN ( SELECT p.patient_id FROM demo.patients p WHERE p.healthcare_worker_id = ORA_END_USER_CONTEXT.demo.hospital_ctx.healthcare_worker_id ) TO student_role;