ORDERS表字段爲order_id, order_date, customer_id, ship_date, total;數據來自oe.orders,主鍵爲order_id
CUSTOMERS表字段爲customer_id, cust_first_name, cust_last_name, date_of_birth, marital_status, cust_email,city_name數據來自oe.customers,主鍵爲customer_id
ORDERS表與CUSTOMERS爲多對1關係,須要用創建朱外鍵約束關係。
分析:由於orders外鍵依賴於customers的主鍵因此建表和插入數據時以customers爲先
//建立customers表
create table customers
(CUSTOMER_ID NUMBER(6) NOT NULL primary key ,
CUST_FIRST_NAME VARCHAR2(20) NOT NULL,
CUST_LAST_NAME VARCHAR2(20) NOT NULL ,
DATE_OF_BIRTH date ,
MARITAL_STATUS VARCHAR2(20),
CUST_EMAIL VARCHAR2(30),
city_name varchar2(50) default 'luoyang');
//建立orders表
create table orders
(order_id number(12) not null,
order_date date ,
customer_id number(6) not null ,
ship_date date not null ,
total number(8,2),
constraint pk_order_id primary key(order_id),
constraint fk_customer_id foreign key(customer_id) REFERENCES customers(customer_id));
grant dba to scott;
//向customers中插入數據
insert into customers(CUSTOMER_ID, CUST_FIRST_NAME, CUST_LAST_NAME ,DATE_OF_BIRTH, MARITAL_STATUS ,CUST_EMAIL) select CUSTOMER_ID, CUST_FIRST_NAME, CUST_LAST_NAME ,DATE_OF_BIRTH, MARITAL_STATUS ,CUST_EMAIL from oe.customers;
//向orders中插入數據
insert into orders(order_id,order_date ,customer_id ,ship_date,total)
select order_id,order_date ,customer_id ,add_months(order_date,2),order_total from oe.orders;
1.創建函數fun_valid_customer,根據輸入的客戶號,檢查客戶是否存在,若是客戶存在,則返回TRUE,不然返回FALSE。
方法一:
create or replace function fun_valid_customer (v_customer_id number)
return varchar2
is
v_return varchar2(50);
v_CUST_FIRST_NAME varchar2(50);
begin
update customers set customer_id=v_customer_id where customer_id=v_customer_id;
if sql%found then
v_return:='true';
else
v_return:='false';
end if;
return v_return;
end;
方法二:
create or replace function fun_valid_customer (v_customer_id number)
return varchar2
is
v_return varchar2(50);
v_CUST_FIRST_NAME varchar2(50);
begin
select CUST_FIRST_NAME into v_CUST_FIRST_NAME from customers where customer_id=v_customer_id;
if sql%found then
v_return:='true';
return v_return;
end if;
exception
when no_data_found then
return 'false';
end;
方法三:
create or replace function fun_valid_customer (v_customer_id number)
return boolean
is
v_tmp number;
begin
select 1 into v_tmp from customers where customer_id=v_customer_id;
return true;
exception
when no_data_found then
return false;
end;
本例選擇方法三
2.創建函數fun_get_total,根據輸入的訂單號返回訂單總價,而後調用該函數。當創建函數fun_get_total時,實現規則:
若是訂單不存在,則顯示自定義錯誤消息「ORA-20001:Please check correct order no.」
create or replace function fun_get_total(v_order_id number)
return number
is
v_total number(8,2);
begin
select total into v_total from orders where order_id=v_order_id;
return v_total;
exception
when no_data_found then
raise_application_error(-20001,'Please check correct order no.');
end;
3.創建過程pro_add_order,根據輸入的訂單號,預約日期,客戶號,交付日期和訂單總價,爲ORDERS表插入數據,而後調用過程。當創建過程pro_add_order,實現規則:
使用pro_valid_customer檢查客戶號是否正確;若是正確,則插入數據,不然顯示自定義錯誤消息「ORA-20001,Please check correct customer no.」
若是交付日期小於預約日期,則顯示錯誤信息「ORA-20002:交付日期必須在預約日期以後。」
若是輸入了已經存在的訂單號,則顯示自定義錯誤信息「ORA-20003:該訂單已經存在。」
create or replace procedure pro_add_order(v_order_id number,v_order_date date ,v_customer_id number,v_ship_date date,v_total number)
is
v_count number;
begin
if not fun_valid_customer(v_customer_id) then
raise_application_error(-20001,'the customer not exist,Please check correct customer no.');
end if;
if v_ship_date < v_order_date then
raise_application_error(-20002,'ship_date must large order_date .');
end if;
insert into orders(order_id ,order_date ,customer_id,ship_date,total ) values(v_order_id ,v_order_date ,v_customer_id,v_ship_date,v_total );
exception
when dup_val_on_index then
raise_application_error(-20003,'the order already exist,please check order no.');
end;
4.創建過程pro_delete_order,根據輸入的訂單號取消特定訂單,而後調用該過程。實現規則:若是定的不存在,則顯示錯誤信息「ORA-20001,請檢查並輸入正確的訂單號。」
create or replace procedure pro_delete_order(v_order_id number)
is
begin
delete from orders where order_id=v_order_id;
if sql%notfound then
raise_application_error(-20001,'Please check and enter the correct order id' );
end if;
commit;
end;
習題1
創建用於操做ORDERS表的包pkg_orders,並調用該包的公用過程和函數。實現的規則:
1.定義私有函數fun_valid_cust,檢查客戶號是否在CUSTOMER表中存在;若是客戶號存在,則返回TRUE,不然返回FALSE。
2.定義公用過程pro_add_order,根據輸入的訂單號,預約日期,客戶編號,交付日期,訂單總價爲ORDERS表增長訂單。若是訂單已經存在,則顯示自定義錯誤信息「ORA-20001:the order already exist,please check order no.」,若是客戶號不存在,則顯示自定義錯誤信息,「ORA-20002:the customer is not exist,please check customer no.」,若是交付日期小於預約日期,則顯示自定義錯誤信息「ORA-20003,ship_date must large order_date .」
3.定義公用過程pro_update_shipdate,根據輸入的訂單號和交付日期,更新特定訂單的交付日期。若是訂單不存在,則顯示自定義錯誤信息「ORA-20004,please input correct order no.」,若是交付日期小於預約日期,則顯示自定義錯誤信息「ORA-20003,ship_date must large order_date .」
4.定義公用函數fun_get_info,根據輸入的訂單號返回客戶名和訂單總價。若是訂單不存在,則顯示自定義錯誤信息「ORA-20004,please input correct order no.」,
5.定義公用過程pro_delete_order,根據輸入的訂單號取消特定訂單。若是訂單不存在,則顯示自定義錯誤信息「ORA-20004,please input correct order no.」,
############################################################################
創建包頭
create or replace package pkg_orders
is
procedure pro_add_order(v_order_id number,v_order_date date,v_customer_id number,v_ship_date date,v_total number);
procedure pro_update_shipdate(v_order_id number,v_ship_date date);
function fun_get_info(v_order_id number,v_customer_name out varchar2) return number;
procedure pro_delete_order(v_order_id number);
end pkg_orders;
###################
創建包體
create or replace package body pkg_orders
is
function fun_valid_cust (v_customer_id number)
return boolean
is
v_tmp number;
begin
select 1 into v_tmp from customers where customer_id=v_customer_id;
return true;
exception
when no_data_found then
return false;
end;
procedure pro_add_order(v_order_id number,v_order_date date,v_customer_id number,v_ship_date date,v_total number)
is
begin
if not fun_valid_customer(v_customer_id) then
raise_application_error(-20002,'the customer is not exist,please check customer no.');
end if;
if v_ship_date < v_order_date then
raise_application_error(-20003,'ship_date must large order_date');
end if;
insert into orders(order_id ,order_date ,customer_id,ship_date,total ) values(v_order_id ,v_order_date ,v_customer_id,v_ship_date,v_total );
exception
when dup_val_on_index then
raise_application_error(-20001,'the order already exist,please check order no.');
end;
procedure pro_update_shipdate(v_order_id number,v_ship_date date)
is
v_order_date date;
begin
select order_date into v_order_date from orders where order_id=v_order_id;
if v_ship_date < v_order_date then
raise_application_error(-20003,'ship_date must large order_date');
end if;
exception
when no_data_found then
raise_application_error(-20004,'please input correct order no.');
update orders set ship_date=v_ship_date where order_id=v_order_id;
end;
function fun_get_info(v_order_id number,v_customer_name out varchar2)
return number
is
v_total number(8,2);
begin
select b.CUST_FIRST_NAME ||' '|| b.CUST_LAST_NAME,a.total into v_customer_name,v_total from orders a join customers b on a.customer_id=b.customer_id where a.order_id=v_order_id ;
return v_total;
exception
when no_data_found then
raise_application_error(-20004,'please input correct order no.');
end;
procedure pro_delete_order(v_order_id number)
is
begin
delete from orders where order_id=v_order_id;
if sql%notfound then
raise_application_error(-20004,'please input correct order no.' );
end if;
commit;
end;
end pkg_orders;
##################################################################################################################
習題2
創建操做CUSTOMERS表的包pkg_customer,而後調用其公用的過程和函數。實現規則:
1.定義重載過程pro_update_city,分別根據輸入的客戶號或客戶名更新客戶所在城市,若是客戶號或者客戶名不存在,若是客戶號不存在,則顯示自定義錯誤信息,「ORA-20002:the customer is not exist,please check customer no or customer name.」
2.定義重載函數fun_get_city,分別根據輸入的客戶號或客戶名返回客戶所在城市。若是客戶號或者客戶名不存在,若是客戶號不存在,則顯示自定義錯誤信息,「ORA-20002:the customer is not exist,please check customer no or customer name.」
####創建包
create or replace package pkg_customer
is
procedure pro_update_city(v_cusno number,v_city varchar2);
procedure pro_update_city(v_cusname varchar2,v_city varchar2);
function fun_get_city(v_cusno number) return varchar2;
function fun_get_city(v_cusname varchar2) return varchar2;
end pkg_customer;
########創建包體
create or replace package body pkg_customer is
procedure pro_update_city(v_cusno number,v_city varchar2)
is
begin
update customers set city_name=v_city where customer_id=v_cusno;
if sql%notfound then
raise_application_error(-20002,'the customer is not exist,please check customer no.');
end if;
end;
procedure pro_update_city(v_cusname varchar2,v_city varchar2)
is
begin
update customers set city_name=v_city where upper(CUST_FIRST_NAME||' '||CUST_LAST_NAME) = upper(v_cusname) ;
if sql%notfound then
raise_application_error(-20002,'the customer is not exist,please check customer name.');
end if;
end;
function fun_get_city(v_cusno number)
return varchar2
is
v_city varchar2(50);
begin
select city_name into v_city from customers where customer_id=v_cusno;
return v_city;
exception
when no_data_found then
raise_application_error(-20002,'the customer is not exist,please check customer no.');
end;
function fun_get_city(v_cusname varchar2)
return varchar2
is
v_city varchar2(50);
begin
select city_name into v_city from customers where upper(CUST_FIRST_NAME||' '||CUST_LAST_NAME) = upper(v_cusname);
return v_city;
exception
when no_data_found then
raise_application_error(-20002,'the customer is not exist,please check customer name.');
end;
end pkg_customer;
##############################
在orders表中針對INSERT操做創建觸發器tr_add_order,規則以下:
1.若是在星期六,星期天增長訂單,顯示錯誤信息「ORA-20001,只能在工做日增長訂單」
2.若是在9:00-18:00以外的其餘時間增長訂單,則顯示錯誤信息,「ORA-20002,只能在工做日增長訂單」
create or replace trigger tr_add_order
before insert on orders
begin
if to_char(sysdate,'DY','nls_date_language=AMERICAN') IN ('SAT','SUN') THEN
RAISE_APPLICATION_ERROR(-20001,'只能在只能在週一~週五增長訂單增長訂單');
end if;
if to_char(sysdate,'HH24MI') not between 0900 and 1800 then
RAISE_APPLICATION_ERROR(-20002,'只能在9:00~18:00增長訂單');
end if;
end;
#############################################
1.動態修改特定部門的工資,並返回修改後的僱員名和工資---scott---emp
//使用遊標
create or replace procedure pro_change_sal(v_deptno emp.deptno%type,v_percent number)
is
type cursor_emp_type is ref cursor;
emp_record emp%rowtype;
emp_cursor cursor_emp_type;
v_sql varchar2(100);
begin
update emp set sal=sal*(1+v_percent/100) where deptno=v_deptno;
v_sql:='select * from emp where deptno=:v_deptno';
open emp_cursor for v_sql using v_deptno;
loop
fetch emp_cursor into emp_record;
exit when emp_cursor%notfound ;
dbms_output.put_line('ename: '|| emp_record.ename ||',salary: ' ||emp_record.sal);
end loop;
close emp_cursor;
end;
####################
//批量處理
set serveroutput on;
create or replace procedure pro_change_sal(v_deptno emp.deptno%type,v_percent number)
is
type sal_table_type is table of emp.sal%type index by binary_integer;
type ename_table_type is table of emp.ename%type index by binary_integer;
ename_table ename_table_type;
sal_table sal_table_type;
v_sql varchar2(100);
begin
update emp set sal=sal*(1+v_percent/100) where deptno=v_deptno;
v_sql:='select ename,sal from emp where deptno=:v_deptno';####必須使用:v_deptno加冒號
execute immediate v_sql bulk collect into ename_table,sal_table using v_deptno;
for i in 1..ename_table.count loop
dbms_output.put_line('ename: '|| ename_table(i) ||',salary: ' ||sal_table(i));
end loop;
end;
2.根據輸入的多個訂單號更新交付日期爲當前日期,並返回每隔訂單的對應的客戶編號.
create or replace procedure pro_change_ship_date(id1 number,id2 number,id3 number)
is
type customer_id_table_type is table of number;
type ordre_id_table_type is table of number;
customer_id_table customer_id_table_type;
ordre_id_table ordre_id_table_type;
v_sql varchar2(100);
begin
update orders set ship_date=sysdate where order_id in (id1 ,id2 ,id3);
v_sql :='select customer_id, order_id from orders where order_id in ( :id1 ,:id2 ,:id3)';
execute immediate v_sql bulk collect into customer_id_table,ordre_id_table using id1 ,id2 ,id3;
for i in 1.. customer_id_table.count loop
dbms_output.put_line('ordre_id '||ordre_id_table(i)||' '||'customer_id '||customer_id_table(i));
end loop;
end;
exec pro_change_ship_date(2381,2354,null);
sql