今天在按照书上的说明,运行这本书的代码store_schema.sql时报错了,主要有2个问题:
1、在插入数据时,报错:无效的月份,后来在晚上查了一下,主要是因为插入语句中的日期中的月份是英文的,比如1月就是JAN,另外,需要日期格式是"日-月-年",所以在代码中加上了如下的语句:
alter session set nls_date_format='DD-MON-YYYY';
alter session set nls_date_language='american';
这样就不会再报错了。
2、另外,在本地机器上直接运行代码store_schema.sql时,不会报错,但如果从一台远程的机器上执行这个脚本时,则好报错,本地的机器是oracle 11g 11.2.0 .1,而远程的机器安装的是oracle 10g 10.2.0.1,每次都报:对象每次已存在。
照理在代码中会删除已经最在的用户store的表:
DROP USER store CASCADE;
但还是报这种错误,一会是对象已存在,一会是报主键冲突,说插入了重复数据。
最后发现是由于代码中有一个connect语句:
CONNECT store/store_password;
CONNECT store/store_password@192.168.1.104/orcl;
store_schema.sql的完整代码:
-- This script does the following:
-- 1. Creates the store user
-- 2. Creates the database tables
-- 3. Creates the PL/SQL code
-- 4. Populates the database tables with sample data
-- attempt to drop the store user (this will generate an error
-- if the store user does not yet exist; do not worry about this
-- error); this statement is included so that you do not have
-- to manually run DROP before recreating the schema
DROP USER store CASCADE;
-- create the store user
CREATE USER store IDENTIFIED BY store_password;
-- allow the store user to connect and create database items
GRANT connect, resource TO store;
-- connect as the store user
CONNECT store/store_password@192.168.1.104/orcl;
alter session set nls_date_format='DD-MON-YYYY';
alter session set nls_date_language='american';
-- create the tables
CREATE TABLE customers (
customer_id INTEGER CONSTRAINT customers_pk PRIMARY KEY,
first_name VARCHAR2(10) NOT NULL,
last_name VARCHAR2(10) NOT NULL,
dob DATE,
phone VARCHAR2(12)
);
CREATE TABLE product_types (
product_type_id INTEGER CONSTRAINT product_types_pk PRIMARY KEY,
name VARCHAR2(10) NOT NULL
);
CREATE TABLE products (
product_id INTEGER CONSTRAINT products_pk PRIMARY KEY,
product_type_id INTEGER
CONSTRAINT products_fk_product_types
REFERENCES product_types(product_type_id),
name VARCHAR2(30) NOT NULL,
description VARCHAR2(50),
price NUMBER(5, 2)
);
CREATE TABLE purchases (
product_id INTEGER
CONSTRAINT purchases_fk_products
REFERENCES products(product_id),
customer_id INTEGER
CONSTRAINT purchases_fk_customers
REFERENCES customers(customer_id),
quantity INTEGER NOT NULL,
CONSTRAINT purchases_pk PRIMARY KEY (product_id, customer_id)
);
CREATE TABLE employees (
employee_id INTEGER CONSTRAINT employees_pk PRIMARY KEY,
manager_id INTEGER,
first_name VARCHAR2(10) NOT NULL,
last_name VARCHAR2(10) NOT NULL,
title VARCHAR2(20),
salary NUMBER(6, 0)
);
CREATE TABLE salary_grades (
salary_grade_id INTEGER CONSTRAINT salary_grade_pk PRIMARY KEY,
low_salary NUMBER(6, 0),
high_salary NUMBER(6, 0)
);
CREATE TABLE purchases_with_timestamp (
product_id INTEGER REFERENCES products(product_id),
customer_id INTEGER REFERENCES customers(customer_id),
made_on TIMESTAMP(4)
);
CREATE TABLE purchases_timestamp_with_tz (
product_id INTEGER REFERENCES products(product_id),
customer_id INTEGER REFERENCES customers(customer_id),
made_on TIMESTAMP(4) WITH TIME ZONE
);
CREATE TABLE purchases_with_local_tz (
product_id INTEGER REFERENCES products(product_id),
customer_id INTEGER REFERENCES customers(customer_id),
made_on TIMESTAMP(4) WITH LOCAL TIME ZONE
);
CREATE TABLE coupons (
coupon_id INTEGER CONSTRAINT coupons_pk PRIMARY KEY,
name VARCHAR2(30) NOT NULL,
duration INTERVAL YEAR(3) TO MONTH
);
CREATE TABLE promotions (
promotion_id INTEGER CONSTRAINT promotions_pk PRIMARY KEY,
name VARCHAR2(30) NOT NULL,
duration INTERVAL DAY(3) TO SECOND (4)
);
CREATE TABLE order_status (
order_status_id INTEGER CONSTRAINT default_example_pk PRIMARY KEY,
status VARCHAR2(20) DEFAULT 'Order placed' NOT NULL,
last_modified DATE DEFAULT SYSDATE
);
CREATE TABLE product_changes (
product_id INTEGER CONSTRAINT prod_changes_pk PRIMARY KEY,
product_type_id INTEGER
CONSTRAINT prod_changes_fk_product_types
REFERENCES product_types(product_type_id),
name VARCHAR2(30) NOT NULL,
description VARCHAR2(50),
price NUMBER(5, 2)
);
CREATE TABLE more_products (
prd_id INTEGER PRIMARY KEY,
prd_type_id INTEGER REFERENCES product_types(product_type_id),
name VARCHAR2(30) NOT NULL,
available CHAR(1)
);
CREATE TABLE more_employees (
employee_id INTEGER CONSTRAINT more_employees_pk PRIMARY KEY,
manager_id INTEGER
CONSTRAINT more_empl_fk_fk_more_empl
REFERENCES more_employees(employee_id),
first_name VARCHAR2(10) NOT NULL,
last_name VARCHAR2(10) NOT NULL,
title VARCHAR2(20),
salary NUMBER(6, 0)
);
CREATE TABLE divisions (
division_id CHAR(3) CONSTRAINT divisions_pk PRIMARY KEY,
name VARCHAR2(15) NOT NULL
);
CREATE TABLE jobs (
job_id CHAR(3) CONSTRAINT jobs_pk PRIMARY KEY,
name VARCHAR2(20) NOT NULL
);
CREATE TABLE employees2 (
employee_id INTEGER CONSTRAINT employees2_pk PRIMARY KEY,
division_id CHAR(3)
CONSTRAINT employees2_fk_divisions
REFERENCES divisions(division_id),
job_id CHAR(3) REFERENCES jobs(job_id),
first_name VARCHAR2(10) NOT NULL,
last_name VARCHAR2(10) NOT NULL,
salary NUMBER(6, 0)
);
CREATE TABLE all_sales (
year INTEGER NOT NULL,
month INTEGER NOT NULL,
prd_type_id INTEGER
CONSTRAINT all_sales_fk_product_types
REFERENCES product_types(product_type_id),
emp_id INTEGER
CONSTRAINT all_sales_fk_employees2
REFERENCES employees2(employee_id),
amount NUMBER(8, 2),
CONSTRAINT all_sales_pk PRIMARY KEY (
year, month, prd_type_id, emp_id
)
);
CREATE TABLE product_price_audit (
product_id INTEGER
CONSTRAINT price_audit_fk_products
REFERENCES products(product_id),
old_price NUMBER(5, 2),
new_price NUMBER(5, 2)
);
CREATE TABLE reg_exps (
id NUMBER CONSTRAINT reg_exps_pk PRIMARY KEY,
text VARCHAR2(512) NOT NULL
);
-- create the PL/SQL code
CREATE PROCEDURE update_product_price(
p_product_id IN products.product_id%TYPE,
p_factor IN NUMBER
) AS
v_product_count INTEGER;
BEGIN
-- count the number of products with the
-- supplied product_id (will be 1 if the product exists)
SELECT COUNT(*)
INTO v_product_count
FROM products
WHERE product_id = p_product_id;
-- if the product exists (v_product_count = 1) then
-- update that product's price
IF v_product_count = 1 THEN
UPDATE products
SET price = price * p_factor
WHERE product_id = p_product_id;
COMMIT;
END IF;
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
END update_product_price;
/
CREATE FUNCTION circle_area (
p_radius IN NUMBER
) RETURN NUMBER AS
v_pi NUMBER := 3.1415926;
v_area NUMBER;
BEGIN
-- circle area is pi multiplied by the radius squared
v_area := v_pi * POWER(p_radius, 2);
RETURN v_area;
END circle_area;
/
CREATE FUNCTION average_product_price (
p_product_type_id IN INTEGER
) RETURN NUMBER AS
v_average_product_price NUMBER;
BEGIN
SELECT AVG(price)
INTO v_average_product_price
FROM products
WHERE product_type_id = p_product_type_id;
RETURN v_average_product_price;
END average_product_price;
/
CREATE PACKAGE product_package AS
TYPE t_ref_cursor IS REF CURSOR;
FUNCTION get_products_ref_cursor RETURN t_ref_cursor;
PROCEDURE update_product_price (
p_product_id IN products.product_id%TYPE,
p_factor IN NUMBER
);
END product_package;
/
CREATE PACKAGE BODY product_package AS
FUNCTION get_products_ref_cursor
RETURN t_ref_cursor IS
v_products_ref_cursor t_ref_cursor;
BEGIN
-- get the REF CURSOR
OPEN v_products_ref_cursor FOR
SELECT product_id, name, price
FROM products;
-- return the REF CURSOR
RETURN v_products_ref_cursor;
END get_products_ref_cursor;
PROCEDURE update_product_price (
p_product_id IN products.product_id%TYPE,
p_factor IN NUMBER
) AS
v_product_count INTEGER;
BEGIN
-- count the number of products with the
-- supplied product_id (will be 1 if the product exists)
SELECT COUNT(*)
INTO v_product_count
FROM products
WHERE product_id = p_product_id;
-- if the product exists (v_product_count = 1) then
-- update that product's price
IF v_product_count = 1 THEN
UPDATE products
SET price = price * p_factor
WHERE product_id = p_product_id;
COMMIT;
END IF;
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
END update_product_price;
END product_package;
/
CREATE TRIGGER before_product_price_update
BEFORE UPDATE OF price
ON products
FOR EACH ROW WHEN (new.price < old.price * 0.75)
BEGIN
dbms_output.put_line('product_id = ' || :old.product_id);
dbms_output.put_line('Old price = ' || :old.price);
dbms_output.put_line('New price = ' || :new.price);
dbms_output.put_line('The price reduction is more than 25%');
-- insert row into the product_price_audit table
INSERT INTO product_price_audit (
product_id, old_price, new_price
) VALUES (
:old.product_id, :old.price, :new.price
);
END before_product_price_update;
/
-- insert sample data into customers table
INSERT INTO customers (
customer_id, first_name, last_name, dob, phone
) VALUES (
1, 'John', 'Brown', '01-JAN-1965', '800-555-1211'
);
INSERT INTO customers (
customer_id, first_name, last_name, dob, phone
) VALUES (
2, 'Cynthia', 'Green', '05-FEB-1968', '800-555-1212'
);
INSERT INTO customers (
customer_id, first_name, last_name, dob, phone
) VALUES (
3, 'Steve', 'White', '16-MAR-1971', '800-555-1213'
);
INSERT INTO customers (
customer_id, first_name, last_name, dob, phone
) VALUES (
4, 'Gail', 'Black', NULL, '800-555-1214'
);
INSERT INTO customers (
customer_id, first_name, last_name, dob, phone
) VALUES (
5, 'Doreen', 'Blue', '20-MAY-1970', NULL
);
-- commit the transaction
COMMIT;
-- insert sample data into product_types table
INSERT INTO product_types (
product_type_id, name
) VALUES (
1, 'Book'
);
INSERT INTO product_types (
product_type_id, name
) VALUES (
2, 'Video'
);
INSERT INTO product_types (
product_type_id, name
) VALUES (
3, 'DVD'
);
INSERT INTO product_types (
product_type_id, name
) VALUES (
4, 'CD'
);
INSERT INTO product_types (
product_type_id, name
) VALUES (
5, 'Magazine'
);
-- commit the transaction
COMMIT;
-- insert sample data into products table
INSERT INTO products (
product_id, product_type_id, name, description, price
) VALUES (
1, 1, 'Modern Science', 'A description of modern science', 19.95
);
INSERT INTO products (
product_id, product_type_id, name, description, price
) VALUES (
2, 1, 'Chemistry', 'Introduction to Chemistry', 30.00
);
INSERT INTO products (
product_id, product_type_id, name, description, price
) VALUES (
3, 2, 'Supernova', 'A star explodes', 25.99
);
INSERT INTO products (
product_id, product_type_id, name, description, price
) VALUES (
4, 2, 'Tank War', 'Action movie about a future war', 13.95
);
INSERT INTO products (
product_id, product_type_id, name, description, price
) VALUES (
5, 2, 'Z Files', 'Series on mysterious activities', 49.99
);
INSERT INTO products (
product_id, product_type_id, name, description, price
) VALUES (
6, 2, '2412: The Return', 'Aliens return', 14.95
);
INSERT INTO products (
product_id, product_type_id, name, description, price
)
VALUES (
7, 3, 'Space Force 9', 'Adventures of heroes', 13.49
);
INSERT INTO products (
product_id, product_type_id, name, description, price
) VALUES (
8, 3, 'From Another Planet', 'Alien from another planet lands on Earth', 12.99
);
INSERT INTO products (
product_id, product_type_id, name, description, price
) VALUES (
9, 4, 'Classical Music', 'The best classical music', 10.99
);
INSERT INTO products (
product_id, product_type_id, name, description, price
) VALUES (
10, 4, 'Pop 3', 'The best popular music', 15.99
);
INSERT INTO products (
product_id, product_type_id, name, description, price
) VALUES (
11, 4, 'Creative Yell', 'Debut album', 14.99
);
INSERT INTO products (
product_id, product_type_id, name, description, price
) VALUES (
12, NULL, 'My Front Line', 'Their greatest hits', 13.49
);
-- commit the transaction
COMMIT;
-- insert sample data into purchases table
INSERT INTO purchases (
product_id, customer_id, quantity
) VALUES (
1, 1, 1
);
INSERT INTO purchases (
product_id, customer_id, quantity
) VALUES (
2, 1, 3
);
INSERT INTO purchases (
product_id, customer_id, quantity
) VALUES (
1, 4, 1
);
INSERT INTO purchases (
product_id, customer_id, quantity
) VALUES (
2, 2,