/*
Oracle客戶端遠程連接服務器,在客戶端配置TNS文件,配置TNS文件所需要的信息:
數據庫服務器的IP、
數據庫實例名稱、
數據庫實例端口(默認端口是1521)
登陸數據還需要用戶名和密碼
參考視頻"客戶端遠程連接服務器.exe"
*/
/*
數據庫對象:
表、試圖、觸發器、存儲過程、函數、數據類型、用戶等等
選擇My objects,只顯示當前用戶所擁有的對象
最關心的對象是:表(相當於一個Excel中的sheet頁)
*/
--dcl數據庫控制語句
/*新增用戶
create user 用戶名 identified by 密碼;
*/
create user liangxianfu identified by liangxianfu;
/*授權
grant 角色1,角色2,角色3 to 用戶名;
角色中有很多權限
*/
grant connect,dba,resource to liangxianfu;
--ddl:數據庫定義語句,定義表的結構(表就相當於excel中sheet頁)
/*創建表
create table 表名(
列1 數據類型 [constraint 主鍵別名 primary key],
列2 數據類型 [not null | null(默認是null)],
...
列n 數據類型 [default 默認值]
);
數據類型:number、varchar2(長度)或char(長度)、date,即數字、字符串、日期
varchar2(長度):可變長,varchar2(12),存儲內容的長度不能超過12個字節,若實際存儲3個字節,內容占用3個字節
char(長度):定長,char(12),存儲內容的長度不能超過12個字節,若實際存儲3個字節,內容仍然占用12個字節
約束:可以理解為限制條件,常見的約束:非空、唯一等等
主鍵:
主鍵相當於身份證號碼,唯一識別一行數據(通過主鍵只能找到一行數據),在一個表中只能有一個主鍵,
主鍵屬於表中的對象
主鍵默認有非空約束、唯一約束
在創建一張表時,建議增加主鍵列
默認值
*/
create table t_student(
id number constraint pk_t_student_id primary key,
name varchar2(50) not null,
sex char(12) default '女',
birthday date
);
--增加注釋
comment on table t_student is '學員基本信息表';
comment on column t_student.sex is '性別';
comment on column t_student.birthday is '出生日期';
/*修改表結構
1)、修改數據類型、非空約束、增加主鍵、默認值等等
2)、修改列的名字
*/
alter table t_student
modify name null;
alter table t_student
modify sex varchar2(12);
alter table t_student
modify sex default null;
alter table t_student
modify sex varchar2(12) default null;
alter table t_student
modify id number constraint pk_t_student_id primary key;
alter table t_student
rename column sex to ssex;
--修改表名
ALTER TABLE old_table_name RENAME TO new_table_name;
/*新增列*/
alter table t_student
add classid number not null;
/*刪除列*/
alter table t_student
drop column classid;
--刪除表結構
drop table t_student;
/*
Data definition language (DDL) statements define, alter the structure of, and drop
schema objects. DDL statements enable you to:
Create, alter, and drop schema objects and other database structures, including
the database itself and database users (CREATE, ALTER, DROP)
Change the names of schema objects (RENAME)
Delete all the data in schema objects without removing the objects’structure
(TRUNCATE)
Grant and revoke privileges and roles (GRANT, REVOKE)
Turn auditing options on and off (AUDIT, NOAUDIT)
Add a comment to the data dictionary (COMMENT)
DDL statements implicitly commit the preceding and start a new transaction
*/
/*dml:數據庫操作語句
增、刪、改、查操作
事務:做一件事情的過程,最終的結果要么成功、要么失敗,在數據庫中,執行一條dml語句即發起一個事務(自動開啟事務),發起了事務就要結束事務,
結束事務的兩種方式:
commit;提交,意味着所有的dml操作結果都生效
rollback;回滾,意味着所有的dml操作結果不會生效
新增:
insert into 表名(列1,列2,列3...列N) values(value1,value2,value3...valueN);
commit;
sysdate:獲取系統當前時間,格式是:年月日時分秒
*/
insert into t_student(id,name,sex,birthday) values(1,'一號學員','男',sysdate);
commit;
--沒有指定name列,name列的值為空值,但在定義表結構時,name列有非空約束,因此以下sql會執行失敗
insert into t_student(id,sex,birthday) values(2,'女',sysdate);
commit;
--沒有指定sex列,但在定義表結構時,sex列有一個默認值是'女',因此以下sql執行后,其sex列的值是'女'
insert into t_student(id,name,birthday) values(2,'二號學員',sysdate);
commit;
--修改表結構,給name列增加默認值
alter table t_student
modify name default '未知的姓名';
--沒有指定name列,name列的值為空值,但在定義表結構時,name列有非空約束和默認值,因此以下sql會執行成功,name列取默認值
insert into t_student(id,sex,birthday) values(3,'女',sysdate);
commit;
--id列是number類型,因此只能是數字,不能是字符串
insert into t_student(id,sex,birthday) values('a','女',sysdate);
commit;
/*修改數據
update 表名
set 字段1=值1,
字段2=值2,
...
字段N=值N
[where 過濾條件]
commit;
*/
update t_student
set name = '蔡10',sex = '男';
commit;
/*刪除數據
delete [from] 表名
[where 過濾條件]
commit;
*/
delete from t_student;
/*truncate table 表名
截斷表,即刪除表中的所有數據,且不會發起事務(要理解該含義,oracle內部隱式發起並結束事務),該操作是非常危險的(除非是100%確定表中的所有數據不需要,可以用,否則決不能用truncate來截斷表)
不能有where條件,不可恢復
*/
truncate table t_student;
/*dml查詢語句
select 列1,列2...列N
from 表
[where 過濾條件]
[group by 分組]
[having]
[order by]
*/
--查詢所有的行,顯示所有列
select * from student;
--查詢所有的行,顯示指定列
select sname, sex, birthday from student;
--where過濾(實際就是比較運算):>、<、=、<>或!=、>=、<=
select * from student where studentid > 10;
select * from student where sex = '男';
--to_date函數:將字符串類型的日期轉換成對應的date類型
--to_date(日期字符串,格式字符串),如to_date('2013-12-12 08:20:38' 'yyyy-mm-dd HH:mi:ss')
--trunc:忽略date類型的時分秒,返回的還是一個date類型
select * from student where birthday > to_date('2013-6-25', 'yyyy-mm-dd');
select *
from student
where trunc(birthday) > to_date('2013-6-25', 'yyyy-mm-dd');
--等效於
select *
from student
where birthday > to_date('2013-6-25 23:59:59', 'yyyy-mm-dd HH24:mi:ss');
--to_char():將date轉換成對應的字符串
select to_char(birthday, 'yyyy-mm-dd HH24:mi:ss') birthday from student;
--日期類型的比較,要用date進行比較,而不要用字符串比較
--'2013-09-9 10:31:57' > '2013-09-25'
select *
from student
where to_char(birthday, 'yyyy-mm-dd HH24:mi:ss') < '2013-06-25';
select to_char(to_date('2013-6-25 23:59:59', 'yyyy-mm-dd HH24:mi:ss'),
'yyyy-mm-dd') my_date
from dual;
--and(且)、or(或),若想要明確指定優先級,用括號括起指定的條件
--and會減少查詢結果的數據量
--or會增加查詢結果的數據量
select * from student where sex = '男' and sname = '劉海生' and studentid = 3;
select * from student where sex = '男' or sname = '劉紅';
--in、not in
select * from student where studentid in(10, 20);
--相當於
select * from student where studentid = 10 or studentid = 20;
select * from student where studentid not in(10, 20);
--相當於
select * from student where studentid != 10 and studentid <> 20;
-->all(是且的關系)、>any(是或的關系)、<all、<any、>=all、<=any
select * from student where studentid >=all(10, 20);
--相當於
select * from student where studentid >=10 and studentid >= 20;
--相當於
select * from student where studentid >= 20;
select * from student where studentid >=any(10, 20);
--相當於
select * from student where studentid >=10 or studentid >= 20;
--相當於
select * from student where studentid >= 10;
--between....and...
select * from student where studentid between 10 and 20;
--相當於
select * from student where studentid >= 10 and studentid <= 20;
select * from student where studentid > 10 and studentid <= 20;
/*dml查詢語句,多表查詢一定要避免笛卡爾積的產生
select 列1,列2...列N
from 表1,表2...表N
[where 過濾條件]
[group by 分組]
[having]
[order by]
內連接
select 列1,列2...列N
from 表1 inner join 表2 on 關聯條件1
inner join 表3 on 關聯條件2
[where 過濾條件]
[group by 分組]
[having]
[order by]
*/
--兩張表查詢,產生笛卡爾積
select * from student, class;
--內連接
select * from student st, class cl where st.classid = cl.classid;
--相當於
select * from student st inner join class cl on st.classid = cl.classid;
--左連接
select * from student st left join class cl on st.classid = cl.classid;
--相當於
select * from student st, class cl where st.classid = cl.classid(+);
--造數據
insert into student values(999,'999感冒靈','李玉剛',sysdate,999);
commit;
--右連接
select * from student st right join class cl on st.classid = cl.classid;
--相當於
select * from student st right join class cl on st.classid(+) = cl.classid;
--造數據
insert into class values(888,'發財班');
commit;
--查詢527班學員信息
select *
from class cl, student st
where cl.classid = st.classid
and cl.classname = '527';
--等同於
select *
from class cl
inner join student st on cl.classid = st.classid
where cl.classname = '527';
--查詢527班學員的分數
select st.sname, st.sex, sc.score
from stscore sc, class cl, student st
where sc.studentid = st.studentid
and st.classid = cl.classid
and cl.classname = '527';
--等同於
select st.sname, st.sex, sc.score
from stscore sc
inner join student st on sc.studentid = st.studentid
inner join class cl on st.classid = cl.classid
where cl.classname = '527';
--null值的處理:它是個未知數x,你不要指望它是個固定的值
--方式一:is null或is not null
--方式二:nvl(列,默認值),如果"列"的值是null,則給它賦一個"默認值"
-- ' '是空字符串,是個固定的值
insert into class(classid) values(111);
commit;
insert into class(classid,classname) values(112,' ');
commit;
select * from class;
select * from class cl where cl.classname = '826';
select * from class cl where cl.classname <> '826';
select * from class cl where cl.classname = null;
-- null = '826' 結果是null
-- null <> '826' 結果是null
-- null == null 結果是null
select * from class cl where cl.classname is null;
select * from class cl where cl.classname is not null;
select * from class cl where nvl(cl.classname, '826') = '826';
--查詢學員"劉紅"所有課程的分數,顯示信息如下:姓名、性別、出生日期、班級名稱、課程名稱、分數
select st.sname, st.sex, st.birthday, cl.classname, co.cname, sc.score
from student st, stscore sc, class cl, course co
where st.studentid = sc.studentid
and sc.courseid = co.courseid
and st.classid = cl.classid
and st.sname = '劉紅';
/*分組查詢
聚合函數:
sum()求和
avg()求平均數據
min()求最小值
max()求最大值
count()求總數
聚合函數可以單獨使用
*/
--以下sql會報錯,思考為什么會報錯
select st.sex,st.sname from student st group by st.sex;
--用聚合函數最數據進行聚合
select st.sex, max(st.sname) from student st group by st.sex;
select st.sex, count(st.sname) "人數" from student st group by st.sex;
--查詢527班每個學員的總分
--desc降序排序、asc升序排序(默認排序方式)
select st.studentid, min(st.sname) "姓名", sum(sc.score) "總分"
from class cl, stscore sc, student st
where cl.classid = st.classid
and st.studentid = sc.studentid
and cl.classname = '527'
group by st.studentid
order by sum(sc.score) desc;
--查詢每門課程的總分、最高分、最低分、平均分
--round()四舍五入函數
select max(co.cname) "課程名稱",
sum(sc.score) "總分",
max(sc.score) "最高分",
min(sc.score) "最低分",
round(avg(sc.score), 1) "平均分"
from stscore sc, course co
where sc.courseid = co.courseid
group by co.courseid;
--查詢826班oracle課程的總分、平均分、最高分、最低分
--lower()轉換成小寫
--upper()轉換成大寫
select sum(sc.score) "總分",
round(avg(sc.score), 1) "平均分",
max(sc.score) "最高分",
min(sc.score) "最低分"
from class cl
inner join student st on cl.classid = st.classid
inner join stscore sc on st.studentid = sc.studentid
inner join course co on sc.courseid = co.courseid
where cl.classname = '826'
and lower(co.cname) = 'oracle';
--查詢826班所有課程的總分、平均分、最高分、最低分
select min(co.cname) "課程名稱",
sum(sc.score) "總分",
round(avg(sc.score), 1) "平均分",
max(sc.score) "最高分",
min(sc.score) "最低分"
from class cl
inner join student st on cl.classid = st.classid
inner join stscore sc on st.studentid = sc.studentid
inner join course co on sc.courseid = co.courseid
where cl.classname = '826'
group by co.courseid;
--查詢每個學員的總分、平均分、最高分、最低分
select max(st.sname) "姓名",
sum(sc.score) "總分",
round(avg(sc.score), 1) "平均分",
max(sc.score) "最高分",
min(sc.score) "最低分"
from student st, stscore sc
where st.studentid = sc.studentid
group by st.studentid
order by sum(sc.score) desc;
/*
having過濾,是對分組之后的數據進行過濾,where是對數據分組之前進行過濾
having只能緊跟group by,沒有group by就沒有having
*/
--查詢每個學員的總分、平均分、最高分、最低分,只顯示總分在200分以上的學員
select max(st.sname) "姓名",
sum(sc.score) "總分",
round(avg(sc.score), 1) "平均分",
max(sc.score) "最高分",
min(sc.score) "最低分"
from student st, stscore sc
where st.studentid = sc.studentid
group by st.studentid
having sum(sc.score) > 200
order by sum(sc.score) desc;
--查詢每個班級沒門課程的總分、平均分、最高分、最低分
--多個字段進行分組
select min(cl.classname) "班級名稱",
max(co.cname) "課程名稱",
sum(sc.score) "總分",
round(avg(sc.score), 1) "平均分",
max(sc.score) "最高分",
min(sc.score) "最低分"
from course co, stscore sc, class cl, student st
where co.courseid = sc.courseid
and sc.studentid = st.studentid
and cl.classid = st.classid
group by cl.classid, co.courseid
order by cl.classid;
/*
聚合函數會忽略null值
*/
--造數據
insert into student values(998,'998','男',sysdate,5);
commit;
insert into stscore(stscoreid,studentid,courseid) values(999,998,1);
insert into stscore values(998,998,2,90);
insert into stscore values(997,998,3,80);
commit;
--查數據,比較一下3條sql的輸出結果
select count(*) from stscore sc;
select count(sc.score) from stscore sc;
select count(sc.studentid) from stscore sc;
--假設學員沒有考Linux科目,在分數表中的分數填寫的是null值
--以下聚合函數忽略掉null值
select max(st.sname) "學員姓名",
sum(sc.score) "總分",
round(avg(sc.score), 1) "平均分",
max(sc.score) "最高分",
min(sc.score) "最低分"
from stscore sc, student st
where st.studentid = sc.studentid
--and sc.score is not null
group by st.studentid
--having sum(sc.score) > 200
order by sum(sc.score) desc;
/*子查詢:用sql語句代替固定值
select 列1,列2...列N
from 結果集1,結果集2...結果集N
[where 過濾條件]
[group by 分組]
[having]
[order by]
*/
select classid from class cl where cl.classname in('527','529');
select *
from student
where classid in
(select classid from class cl where cl.classname in ('527', '529'));
--單行子查詢:>、<、=、<>或!=、>=、<=
select * from student where classid = 1;
--以下sql報錯,思考為什么會報錯,從而理解子查詢
select *
from student
where classid = (select * from class cl where cl.classname = '527');
--以下sql報錯,思考為什么會報錯,從而理解子查詢
select *
from student
where classid =
(select classid from class cl where cl.classname in ('527', '529'));
--in、not in、>all、<any等是多行子查詢(exists、not exists)
select *
from student
where classid not in
(select classid from class cl where cl.classname in ('527', '529'));
--查詢每個班級"總人數" "男生人數" "女生人數"
select count(*)
from (select ww.studentid
from student qq
left join (select * from student sq where sq.sex = '男') ww
on qq.studentid = ww.studentid)
where studentid is null;
select cl.classid, count(st.studentid) t_total
from student st, class cl
where st.classid = cl.classid
group by cl.classid;
select cl.classid, count(st.studentid) t_total
from student st, class cl
where st.classid = cl.classid and st.sex = '男'
group by cl.classid;
select t1.t_total "總人數",
t2.t_total "男生總人數",
(t1.t_total - t2.t_total) "女生總人數"
from (select cl.classid, count(st.studentid) t_total
from student st, class cl
where st.classid = cl.classid
group by cl.classid) t1,
(select cl.classid, count(st.studentid) t_total
from student st, class cl
where st.classid = cl.classid
and st.sex = '男'
group by cl.classid) t2
where t1.classid = t2.classid;
--查詢全校總人數、男生總人數、女生總人數
select (select count(student.studentid) from student) t_total,
(select count(student.studentid) from student where sex = '男') t_total_01,
(select count(student.studentid) from student) -
(select count(student.studentid) from student where sex = '男') t_total_02
from dual;
select t1.t_total "總人數",
t1.t_total_boy "男生總人數",
(t1.t_total - t1.t_total_boy) "女生總人數"
from (select count(st.studentid) t_total,
max((select count(studentid)
from student st1
where st1.sex = '男')) t_total_boy
from student st) t1;
/*偽列
rowid:屬於表中的列,是由數據庫自動增加的列,是真實存在的一個列,唯一標識一條數據的物理位置(查詢語句首先得到數據的rowid,然后根據rowid到數據文件中唯一定位數據)
因此,根據rowid查詢的效率是最高的,數據在入庫時(即成功插入數據),Oracle數據就給這條數據分配一個唯一的rowid
rownum:是給結果集增加的一個序號,不屬於任何的表,現有結果集,才能有rownum,始終是從1開始編號(不能跨過1而存在)
*/
--根據rowid查詢的效率是最高的,但通常情況下不知道rowid的值,rowid是整個數據庫唯一(在不同的數據庫中不一定唯一)
select t.*, t.rowid from student t where t.rowid = 'AAAM1iAAEAAAAGcAAA';
--不屬於任何的表
--select t.*,t.rowid,t.rownum from student t;
--始終是從1開始編號(不能跨過1而存在)
select * from student t where rownum < 10;
select * from student t where rownum > 10;
select * from student t where rownum between 10 and 20;
select * from student t where rownum between 1 and 10;
--查詢第10條到第20條數據,用子查詢,常用的分頁查詢(每一個結果集都對應一個rownum)
select t.*
from (select t.*, rownum rn from student t where rownum < 21) t
where t.rn > 9;
--步驟一:查詢每個學員的總分
select st.studentid, sum(sc.score) t_score
from stscore sc, student st
where sc.studentid = st.studentid
group by st.studentid;
--步驟二:查詢前3名的總分是多少
--造數據
select * from stscore sc where sc.studentid in (6,7) for update nowait;
select *
from (select distinct sum(sc.score) t_score
from stscore sc, student st
where sc.studentid = st.studentid
group by st.studentid
order by t_score desc) t
where rownum < 4;
--distinct的用法:去除重復的數據(所有的列全部相同,則取一條),比較以下sql語句
select distinct st.sname from student st where st.sname = '劉紅';
select distinct st.studentid, st.sname from student st where st.sname = '劉紅';
select distinct st.sex, st.sname from student st where st.sname = '劉紅';
--步驟三:步驟一、步驟二進行關聯查詢,關聯條件是總分數相等
select st1.sname "姓名", t1.t_score "總分", t2.rn "名次"
from (select st.studentid, sum(sc.score) t_score
from stscore sc, student st
where sc.studentid = st.studentid
group by st.studentid) t1,
(select t.*, rownum rn
from (select distinct sum(sc.score) t_score
from stscore sc, student st
where sc.studentid = st.studentid
group by st.studentid
order by t_score desc) t
where rownum < 4) t2,
student st1
where t1.t_score = t2.t_score
and t1.studentid = st1.studentid
order by t2.rn;
--試圖:虛擬表,保存了sql的中間結果,只能發出select語句,不能發insert、update、delete等語句
--試圖所涉及的表中的數據發生變化,則試圖中的數據也隨之發生更改
create or replace view v_view01 as
select st1.sname "姓名", t1.t_score "總分", t2.rn "名次"
from (select st.studentid, sum(sc.score) t_score
from stscore sc, student st
where sc.studentid = st.studentid
group by st.studentid) t1,
(select t.*, rownum rn
from (select distinct sum(sc.score) t_score
from stscore sc, student st
where sc.studentid = st.studentid
group by st.studentid
order by t_score desc) t
where rownum < 4) t2,
student st1
where t1.t_score = t2.t_score
and t1.studentid = st1.studentid
order by t2.rn;
--試圖的使用
select * from v_view01
--索引:相當於書的目錄,提高查詢效率,屬於表對象
--若表中已有的數據重復了,則不能創建唯一性索引
drop index i_index_01
create index i_index_01 on student (sname);
--以下sql執行失敗
create unique index i_index_01 on student (sname);
select st1.sno "學號",
st1.sname "姓名",
st1.sex "性別",
t3.t_degree "總成績"
from student st1,
(select max(t.t_degree) m_t_degree
from student st,
(select sc.sno, sum(sc.degree) t_degree
from score sc
group by sc.sno) t
where t.sno = st.sno
group by st.sname, st.sex) t3,
(select sc.sno, sum(sc.degree) t_degree from score sc group by sc.sno) t2
where t3.m_t_degree = t2.t_degree
and t2.sno = st1.sno;
select 部門
from A
group by 部門
having min(業績) = 7 and count(月份) = (select count(distinct 月份) t_月份
from A);
select max(co.cname) "課程名稱",
count(sc.studentid) "總人數",
sum(decode(sign(sc.score - 60), -1, 1, 0)) "[<60)人數",
sum(decode(sign(sc.score - 60),
-1,
0,
decode(sign(sc.score - 70), 1, 0, 1))) "[60,70]人數",
sum(decode(sign(sc.score - 70), 1, 1, 0)) "[>70)人數"
from stscore sc, course co
where sc.courseid = co.courseid
group by co.courseid
order by co.courseid;
select A.name, A.kecheng, A.fenshu
from A,
(select name
from A
group by name
having min(fenshu) >= 60 and count(kecheng) = (select count(distinct
kecheng)
from A)) t
where A.name = t.name;
select *
from A
group by 部門
having min(業績) > 7 and count(月份) = (select count(distinct 月份) from A);
select t3.作者姓名, t2.圖書名, t2.出版社
from (select t1.作者編號, t1.作者姓名
from t1
where t1.年齡 < (select avg(t1.年齡) from t1)) t3,
t2
where t3.作者編號 = t2.作者編號;
select st.sno "學號",
st.sname "姓名",
co.cname "課名",
co.cteacher "課程老師",
sc1.score "成績"
from student st,
(select sc.sno from score sc group by sc.sno having count(sc.cno) > 2) t,
course co,
score sc1
where st.sno = t.sno
and co.cno = sc1.cno
and t.sno = co.sno;
select 日期,
sum(decode(結果, '勝', 1, 0)) "勝",
sum(decode(結果, '負', 1, 0)) "負"
from A
group by 日期;
select max(t.t_score) m_t_score
from student st,
(select sc.sno, sum(sc.score) t_score from scour sc group by sc.sno) t
where st.sno = t.sno
group by st.sname, st.sex;
select st1.sno "學號",
st1.sname "姓名",
st1.ssex "性別",
t1.t_score "總成績"
from student st1,
(select sc.sno, sum(sc.score) t_score from scour sc group by sc.sno) t1,
(select max(t.t_score) m_t_score
from student st,
(select sc.sno, sum(sc.score) t_score
from scour sc
group by sc.sno) t
where st.sno = t.sno
group by st.sname, st.sex) t2
where st1.sno = t1.sno
and t1.t_score = t2.m_t_score;