为示例应用程序创建安装脚本
您可以为示例应用程序创建安装脚本。
以下脚本适用于 Developing a Simple Oracle Database Application 中的应用程序:
-
objects.sql ,它在部署环境中执行您在“创建方案对象并加载数据”中的开发环境中执行的操作
-
employees.sql ,它在部署环境中执行您在“创建 employees_pkg 软件包”中的开发环境中执行的操作
-
admin.sql ,它在部署环境中执行您在“创建 admin_pkg 软件包”中的开发环境中执行的操作
-
create_app.sql ,用于运行上述脚本的主脚本,从而在部署环境中部署示例应用程序
您可以按任意顺序创建脚本。要创建 schema.sql 和 create_app.sql,必须使用文本编辑器。要创建其他脚本,可以使用文本编辑器或 SQL Developer。
创建安装脚本 schema.sql
安装脚本 schemas.sql 在部署环境中执行您在开发环境中在“为应用程序创建方案”和“为方案授予权限”中所执行的操作。
要创建 schema.sql,请在任意文本编辑器中输入以下文本,并将文件另存为 schema.sql。
注意:选择安全密码。有关安全口令的准则,请参阅 Oracle Database Security Guide。
-----------------
-- Create schemas
-----------------
DROP USER app_data CASCADE;
CREATE USER app_data IDENTIFIED BY password
DEFAULT TABLESPACE USERS
QUOTA UNLIMITED ON USERS
ENABLE EDITIONS;
DROP USER app_code CASCADE;
CREATE USER app_code IDENTIFIED BY password
DEFAULT TABLESPACE USERS
QUOTA UNLIMITED ON USERS
ENABLE EDITIONS;
DROP USER app_admin CASCADE;
CREATE USER app_admin IDENTIFIED BY password
DEFAULT TABLESPACE USERS
QUOTA UNLIMITED ON USERS
ENABLE EDITIONS;
DROP USER app_user CASCADE;
CREATE USER app_user IDENTIFIED BY password
ENABLE EDITIONS;
DROP USER app_admin_user CASCADE;
CREATE USER app_admin_user IDENTIFIED BY password
ENABLE EDITIONS;
------------------------------
-- Grant privileges to schemas
------------------------------
GRANT CREATE SESSION TO app_data;
GRANT CREATE TABLE, CREATE VIEW, CREATE TRIGGER, CREATE SEQUENCE TO app_data;
GRANT SELECT ON HR.DEPARTMENTS TO app_data;
GRANT SELECT ON HR.EMPLOYEES TO app_data;
GRANT SELECT ON HR.JOB_HISTORY TO app_data;
GRANT SELECT ON HR.JOBS TO app_data;
GRANT CREATE SESSION, CREATE PROCEDURE, CREATE SYNONYM TO app_code;
GRANT CREATE SESSION, CREATE PROCEDURE, CREATE SYNONYM TO app_admin;
GRANT CREATE SESSION, CREATE SYNONYM TO app_user;
GRANT CREATE SESSION, CREATE SYNONYM TO app_admin_user;
另请参阅:“应用程序方案”了解示例应用程序的方案说明
创建安装脚本 objects.sql
安装脚本 objects.sql 在部署环境中执行您在开发环境中的“创建方案对象和加载数据”操作。
可以使用文本编辑器或 SQL Developer 创建 objects.sql。
要在任意文本编辑器中创建 objects.sql,请输入以下文本并将文件另存为 objects.sql。对于密码,请使用 schema.sql 在创建用户 app_data 时指定的密码。
注:仅当部署环境具有标准 HR 方案时,加载数据的 INSERT 语句才起作用。如果没有,则使用 SQL Developer 创建一个脚本,该脚本使用源表中的数据(在开发环境中)加载新表(在部署环境中),或修改以下脚本中的 INSERT 语句。
------------------------
-- Create schema objects
------------------------
CONNECT app_data/*password*
CREATE TABLE jobs#
( job_id VARCHAR2(10)
CONSTRAINT jobs_pk PRIMARY KEY,
job_title VARCHAR2(35)
CONSTRAINT jobs_job_title_not_null NOT NULL,
min_salary NUMBER(6)
CONSTRAINT jobs_min_salary_not_null NOT NULL,
max_salary NUMBER(6)
CONSTRAINT jobs_max_salary_not_null NOT NULL
)
/
CREATE TABLE departments#
( department_id NUMBER(4)
CONSTRAINT departments_pk PRIMARY KEY,
department_name VARCHAR2(30)
CONSTRAINT dept_department_name_not_null NOT NULL
CONSTRAINT dept_department_name_unique UNIQUE,
manager_id NUMBER(6)
)
/
CREATE TABLE employees#
( employee_id NUMBER(6)
CONSTRAINT employees_pk PRIMARY KEY,
first_name VARCHAR2(20)
CONSTRAINT emp_first_name_not_null NOT NULL,
last_name VARCHAR2(25)
CONSTRAINT emp_last_name_not_null NOT NULL,
email_addr VARCHAR2(25)
CONSTRAINT emp_email_addr_not_null NOT NULL,
hire_date DATE
DEFAULT TRUNC(SYSDATE)
CONSTRAINT emp_hire_date_not_null NOT NULL
CONSTRAINT emp_hire_date_check
CHECK(TRUNC(hire_date) = hire_date),
country_code VARCHAR2(5)
CONSTRAINT emp_country_code_not_null NOT NULL,
phone_number VARCHAR2(20)
CONSTRAINT emp_phone_number_not_null NOT NULL,
job_id CONSTRAINT emp_job_id_not_null NOT NULL
CONSTRAINT emp_to_jobs_fk REFERENCES jobs#,
job_start_date DATE
CONSTRAINT emp_job_start_date_not_null NOT NULL,
CONSTRAINT emp_job_start_date_check
CHECK(TRUNC(JOB_START_DATE) = job_start_date),
salary NUMBER(6)
CONSTRAINT emp_salary_not_null NOT NULL,
manager_id CONSTRAINT emp_mgrid_to_emp_empid_fk REFERENCES employees#,
department_id CONSTRAINT emp_to_dept_fk REFERENCES departments#
)
/
CREATE TABLE job_history#
( employee_id CONSTRAINT job_hist_to_emp_fk REFERENCES employees#,
job_id CONSTRAINT job_hist_to_jobs_fk REFERENCES jobs#,
start_date DATE
CONSTRAINT job_hist_start_date_not_null NOT NULL,
end_date DATE
CONSTRAINT job_hist_end_date_not_null NOT NULL,
department_id
CONSTRAINT job_hist_to_dept_fk REFERENCES departments#
CONSTRAINT job_hist_dept_id_not_null NOT NULL,
CONSTRAINT job_history_pk PRIMARY KEY(employee_id,start_date),
CONSTRAINT job_history_date_check CHECK( start_date < end_date )
)
/
CREATE EDITIONING VIEW jobs AS SELECT * FROM jobs#
/
CREATE EDITIONING VIEW departments AS SELECT * FROM departments#
/
CREATE EDITIONING VIEW employees AS SELECT * FROM employees#
/
CREATE EDITIONING VIEW job_history AS SELECT * FROM job_history#
/
CREATE OR REPLACE TRIGGER employees_aiufer
AFTER INSERT OR UPDATE OF salary, job_id ON employees FOR EACH ROW
DECLARE
l_cnt NUMBER;
BEGIN
LOCK TABLE jobs IN SHARE MODE; -- Ensure that jobs does not change
-- during the following query.
SELECT COUNT(*) INTO l_cnt
FROM jobs
WHERE job_id = :NEW.job_id
AND :NEW.salary BETWEEN min_salary AND max_salary;
IF (l_cnt<>1) THEN
RAISE_APPLICATION_ERROR( -20002,
CASE
WHEN :new.job_id = :old.job_id
THEN 'Salary modification invalid'
ELSE 'Job reassignment puts salary out of range'
END );
END IF;
END;
/
CREATE OR REPLACE TRIGGER jobs_aufer
AFTER UPDATE OF min_salary, max_salary ON jobs FOR EACH ROW
WHEN (NEW.min_salary > OLD.min_salary OR NEW.max_salary < OLD.max_salary)
DECLARE
l_cnt NUMBER;
BEGIN
LOCK TABLE employees IN SHARE MODE;
SELECT COUNT(*) INTO l_cnt
FROM employees
WHERE job_id = :NEW.job_id
AND salary NOT BETWEEN :NEW.min_salary and :NEW.max_salary;
IF (l_cnt>0) THEN
RAISE_APPLICATION_ERROR( -20001,
'Salary update would violate ' || l_cnt || ' existing employee records' );
END IF;
END;
/
CREATE SEQUENCE employees_sequence START WITH 210;
CREATE SEQUENCE departments_sequence START WITH 275;
------------
-- Load data
------------
INSERT INTO jobs (job_id, job_title, min_salary, max_salary)
SELECT job_id, job_title, min_salary, max_salary
FROM HR.JOBS
/
INSERT INTO departments (department_id, department_name, manager_id)
SELECT department_id, department_name, manager_id
FROM HR.DEPARTMENTS
/
INSERT INTO employees (employee_id, first_name, last_name, email_addr,
hire_date, country_code, phone_number, job_id, job_start_date, salary,
manager_id, department_id)
SELECT employee_id, first_name, last_name, email, hire_date,
CASE WHEN phone_number LIKE '011.%'
THEN '+' || SUBSTR( phone_number, INSTR( phone_number, '.' )+1,
INSTR( phone_number, '.', 1, 2 ) - INSTR( phone_number, '.' ) - 1 )
ELSE '+1'
END country_code,
CASE WHEN phone_number LIKE '011.%'
THEN SUBSTR( phone_number, INSTR(phone_number, '.', 1, 2 )+1 )
ELSE phone_number
END phone_number,
job_id,
NVL( (SELECT MAX(end_date+1)
FROM HR.JOB_HISTORY jh
WHERE jh.employee_id = employees.employee_id), hire_date),
salary, manager_id, department_id
FROM HR.EMPLOYEES
/
INSERT INTO job_history (employee_id, job_id, start_date, end_date,
department_id)
SELECT employee_id, job_id, start_date, end_date, department_id
FROM HR.JOB_HISTORY
/
COMMIT;
-----------------------------
-- Add foreign key constraint
-----------------------------
ALTER TABLE departments#
ADD CONSTRAINT dept_to_emp_fk
FOREIGN KEY(manager_id) REFERENCES employees#;
----------------------------------------------
-- Grant privileges on schema objects to users
----------------------------------------------
GRANT SELECT, INSERT, UPDATE, DELETE ON employees TO app_code;
GRANT SELECT ON departments TO app_code;
GRANT SELECT ON jobs TO app_code;
GRANT SELECT, INSERT on job_history TO app_code;
GRANT SELECT ON employees_sequence TO app_code;
GRANT SELECT, INSERT, UPDATE, DELETE ON jobs TO app_admin;
GRANT SELECT, INSERT, UPDATE, DELETE ON departments TO app_admin;
GRANT SELECT ON employees_sequence TO app_admin;
GRANT SELECT ON departments_sequence TO app_admin;
GRANT SELECT ON jobs TO app_admin_user;
GRANT SELECT ON departments TO app_admin_user;
另请参见:
-
应用程序方案对象,用于说明示例应用程序的方案对象
创建安装脚本 employees.sql
安装脚本 employees.sql 在部署环境中执行您在“创建 employees_pkg Package ”中的开发环境中执行的操作。
可以使用文本编辑器或 SQL Developer 创建 employees.sql。
要在任意文本编辑器中创建 employees.sql,请输入以下文本并将该文件另存为 employees.sql。对于密码,请使用 schema.sql 在创建用户 app_code 时指定的密码。
-----------------------
-- Create employees_pkg
-----------------------
CONNECT app_code/*password*
CREATE SYNONYM employees FOR app_data.employees;
CREATE SYNONYM departments FOR app_data.departments;
CREATE SYNONYM jobs FOR app_data.jobs;
CREATE SYNONYM job_history FOR app_data.job_history;
CREATE OR REPLACE PACKAGE employees_pkg
AS
PROCEDURE get_employees_in_dept
( p_deptno IN employees.department_id%TYPE,
p_result_set IN OUT SYS_REFCURSOR );
PROCEDURE get_job_history
( p_employee_id IN employees.department_id%TYPE,
p_result_set IN OUT SYS_REFCURSOR );
PROCEDURE show_employee
( p_employee_id IN employees.employee_id%TYPE,
p_result_set IN OUT SYS_REFCURSOR );
PROCEDURE update_salary
( p_employee_id IN employees.employee_id%TYPE,
p_new_salary IN employees.salary%TYPE );
PROCEDURE change_job
( p_employee_id IN employees.employee_id%TYPE,
p_new_job IN employees.job_id%TYPE,
p_new_salary IN employees.salary%TYPE := NULL,
p_new_dept IN employees.department_id%TYPE := NULL );
END employees_pkg;
/
CREATE OR REPLACE PACKAGE BODY employees_pkg
AS
PROCEDURE get_employees_in_dept
( p_deptno IN employees.department_id%TYPE,
p_result_set IN OUT SYS_REFCURSOR )
IS
l_cursor SYS_REFCURSOR;
BEGIN
OPEN p_result_set FOR
SELECT e.employee_id,
e.first_name || ' ' || e.last_name name,
TO_CHAR( e.hire_date, 'Dy Mon ddth, yyyy' ) hire_date,
j.job_title,
m.first_name || ' ' || m.last_name manager,
d.department_name
FROM employees e INNER JOIN jobs j ON (e.job_id = j.job_id)
LEFT OUTER JOIN employees m ON (e.manager_id = m.employee_id)
INNER JOIN departments d ON (e.department_id = d.department_id)
WHERE e.department_id = p_deptno ;
END get_employees_in_dept;
PROCEDURE get_job_history
( p_employee_id IN employees.department_id%TYPE,
p_result_set IN OUT SYS_REFCURSOR )
IS
BEGIN
OPEN p_result_set FOR
SELECT e.First_name || ' ' || e.last_name name, j.job_title,
e.job_start_date start_date,
TO_DATE(NULL) end_date
FROM employees e INNER JOIN jobs j ON (e.job_id = j.job_id)
WHERE e.employee_id = p_employee_id
UNION ALL
SELECT e.First_name || ' ' || e.last_name name,
j.job_title,
jh.start_date,
jh.end_date
FROM employees e INNER JOIN job_history jh
ON (e.employee_id = jh.employee_id)
INNER JOIN jobs j ON (jh.job_id = j.job_id)
WHERE e.employee_id = p_employee_id
ORDER BY start_date DESC;
END get_job_history;
PROCEDURE show_employee
( p_employee_id IN employees.employee_id%TYPE,
p_result_set IN OUT sys_refcursor )
IS
BEGIN
OPEN p_result_set FOR
SELECT *
FROM (SELECT TO_CHAR(e.employee_id) employee_id,
e.first_name || ' ' || e.last_name name,
e.email_addr,
TO_CHAR(e.hire_date,'dd-mon-yyyy') hire_date,
e.country_code,
e.phone_number,
j.job_title,
TO_CHAR(e.job_start_date,'dd-mon-yyyy') job_start_date,
to_char(e.salary) salary,
m.first_name || ' ' || m.last_name manager,
d.department_name
FROM employees e INNER JOIN jobs j on (e.job_id = j.job_id)
RIGHT OUTER JOIN employees m ON (m.employee_id = e.manager_id)
INNER JOIN departments d ON (e.department_id = d.department_id)
WHERE e.employee_id = p_employee_id)
UNPIVOT (VALUE FOR ATTRIBUTE IN (employee_id, name, email_addr, hire_date,
country_code, phone_number, job_title, job_start_date, salary, manager,
department_name) );
END show_employee;
PROCEDURE update_salary
( p_employee_id IN employees.employee_id%type,
p_new_salary IN employees.salary%type )
IS
BEGIN
UPDATE employees
SET salary = p_new_salary
WHERE employee_id = p_employee_id;
END update_salary;
PROCEDURE change_job
( p_employee_id IN employees.employee_id%TYPE,
p_new_job IN employees.job_id%TYPE,
p_new_salary IN employees.salary%TYPE := NULL,
p_new_dept IN employees.department_id%TYPE := NULL )
IS
BEGIN
INSERT INTO job_history (employee_id, start_date, end_date, job_id,
department_id)
SELECT employee_id, job_start_date, TRUNC(SYSDATE), job_id, department_id
FROM employees
WHERE employee_id = p_employee_id;
UPDATE employees
SET job_id = p_new_job,
department_id = NVL( p_new_dept, department_id ),
salary = NVL( p_new_salary, salary ),
job_start_date = TRUNC(SYSDATE)
WHERE employee_id = p_employee_id;
END change_job;
END employees_pkg;
/
---------------------------------------------
-- Grant privileges on employees_pkg to users
---------------------------------------------
GRANT EXECUTE ON employees_pkg TO app_user;
GRANT EXECUTE ON employees_pkg TO app_admin_user;
另请参见:
创建安装脚本 admin.sql
安装脚本 admin.sql 在部署环境中执行您在“创建 admin_pkg 软件包”中的开发环境中执行的操作。
可以使用文本编辑器或 SQL Developer 创建 admin.sql。
要在任意文本编辑器中创建 admin.sql,请输入以下文本并将文件另存为 admin.sql。对于密码,请使用 schema.sql 在创建用户 app_admin 时指定的密码。
-------------------
-- Create admin_pkg
-------------------
CONNECT app_admin/*password*
CREATE SYNONYM departments FOR app_data.departments;
CREATE SYNONYM jobs FOR app_data.jobs;
CREATE SYNONYM departments_sequence FOR app_data.departments_sequence;
CREATE OR REPLACE PACKAGE admin_pkg
AS
PROCEDURE update_job
( p_job_id IN jobs.job_id%TYPE,
p_job_title IN jobs.job_title%TYPE := NULL,
p_min_salary IN jobs.min_salary%TYPE := NULL,
p_max_salary IN jobs.max_salary%TYPE := NULL );
PROCEDURE add_job
( p_job_id IN jobs.job_id%TYPE,
p_job_title IN jobs.job_title%TYPE,
p_min_salary IN jobs.min_salary%TYPE,
p_max_salary IN jobs.max_salary%TYPE );
PROCEDURE update_department
( p_department_id IN departments.department_id%TYPE,
p_department_name IN departments.department_name%TYPE := NULL,
p_manager_id IN departments.manager_id%TYPE := NULL,
p_update_manager_id IN BOOLEAN := FALSE );
FUNCTION add_department
( p_department_name IN departments.department_name%TYPE,
p_manager_id IN departments.manager_id%TYPE )
RETURN departments.department_id%TYPE;
END admin_pkg;
/
CREATE OR REPLACE PACKAGE BODY admin_pkg
AS
PROCEDURE update_job
( p_job_id IN jobs.job_id%TYPE,
p_job_title IN jobs.job_title%TYPE := NULL,
p_min_salary IN jobs.min_salary%TYPE := NULL,
p_max_salary IN jobs.max_salary%TYPE := NULL )
IS
BEGIN
UPDATE jobs
SET job_title = NVL( p_job_title, job_title ),
min_salary = NVL( p_min_salary, min_salary ),
max_salary = NVL( p_max_salary, max_salary )
WHERE job_id = p_job_id;
END update_job;
PROCEDURE add_job
( p_job_id IN jobs.job_id%TYPE,
p_job_title IN jobs.job_title%TYPE,
p_min_salary IN jobs.min_salary%TYPE,
p_max_salary IN jobs.max_salary%TYPE )
IS
BEGIN
INSERT INTO jobs ( job_id, job_title, min_salary, max_salary )
VALUES ( p_job_id, p_job_title, p_min_salary, p_max_salary );
END add_job;
PROCEDURE update_department
( p_department_id IN departments.department_id%TYPE,
p_department_name IN departments.department_name%TYPE := NULL,
p_manager_id IN departments.manager_id%TYPE := NULL,
p_update_manager_id IN BOOLEAN := FALSE )
IS
BEGIN
IF ( p_update_manager_id ) THEN
UPDATE departments
SET department_name = NVL( p_department_name, department_name ),
manager_id = p_manager_id
WHERE department_id = p_department_id;
ELSE
UPDATE departments
SET department_name = NVL( p_department_name, department_name )
WHERE department_id = p_department_id;
END IF;
END update_department;
FUNCTION add_department
( p_department_name IN departments.department_name%TYPE,
p_manager_id IN departments.manager_id%TYPE )
RETURN departments.department_id%TYPE
IS
l_department_id departments.department_id%TYPE;
BEGIN
INSERT INTO departments ( department_id, department_name, manager_id )
VALUES ( departments_sequence.NEXTVAL, p_department_name, p_manager_id )
RETURNING department_id INTO l_department_id;
RETURN l_department_id;
END add_department;
END admin_pkg;
/
----------------------------------------
-- Grant privileges on admin_pkg to user
----------------------------------------
GRANT EXECUTE ON admin_pkg TO app_admin_user;
另请参见:
创建主安装脚本 create_app.sql
主安装脚本 create_app.sql 以正确的顺序为示例应用程序运行其他四个安装脚本,从而在部署环境中部署示例应用程序。
要创建 create_app.sql,请在任何文本编辑器中输入以下文本,并将文件另存为 create_app.sql:
@schemas.sql
@objects.sql
@employees.sql
@admin.sql