oracle產品線圍繞企業開發平台的
企業開發平台四大組件:unix,weblogic中間件,java編程語言,oracle數據庫
oracle 開發主要分兩類
數據庫管理:dba
數據庫編程:分兩部分
sql編程
pl/sql編程(子程序,觸發器,面向對象,游標)
下載 官方網站下載相應的版本到本地,並解壓縮。
環境 在啟動安裝之前的環境配置。
安裝
只要是行與列的集合就是數據表
SQL> ed hello
SQL> @hello
數據庫開發都以dml操作為主
數據庫設計時以ddl操作為主
數據類型 number(7,2) 小數位是兩位,總共是7位,整數是5位
#######################################
簡單查詢的最大特征在於可以控制列,它無法進行數據行的控制。
select [distinct] *| 列名 [別名],列名 [別名],... from 表名 [別名];
distinct是去掉重復的行。指所查詢出來的所有列內容都一樣的去重。
執行順序是先from再select
子句有兩個 一個是select ...,一個是from ...。或者還會有where ...,order by ...。
進行數據的投影-----控制所需要顯示的數據列。
支持四則運算,再加上別名就美觀了。
select aa,bb,cc*2 from emp;
select aa,bb,cc*2 nian from emp;
select trans_new_price-2 sum from tis_ft_adjust_price where rownum <=5;
select trans_new_price*2 sum from tis_ft_adjust_price where rownum <=5;
拼接列的值。列名1 || 列名2
select adjust_time || operator_id ww from tis_ft_adjust_price where rownum <=5;
格式化輸出,字符串用單引號引起來,數字直接寫,不用引用。
select 'tj:'||adjust_reason||',ti:'||ADJUST_TIME ww from tis_ft_adjust_price where rownum <=5;
#######################################
限定查詢,控制數據行
1.sql語句的執行順序
第三步:選出所需要的數據列 select *
第一步:確定數據來源 from table
第二步:篩選數據行 where 條件
第四步:數據排序 order by
2.限定符號的使用,以下是標准sql支持的。
若干個條件判斷符,
>,<,=,>=,<=,!=(<>).
is not null,is null
like,not like _匹配任意一位字符,%匹配多位。
in,not in not in中不能有null,in可以有。where 字段 in(8899,2234,7554,null); 不連續的行
betwwen...and where 字段|數值 betwwen 最小值 and 最大值; 連續的行
以上只能使用一次,如果有多個條件,則用邏輯運算符:
and,or,not(非)
書寫標准,先查列,再將select from where 分別寫三行,再寫各種限定,表限定,行限定,列限定。這是按照執行順序寫的。
desc tis_bk_user;
select user_id
from tis_bk_user
where rownum <=5;
select *
from tis_ft_g_owner_clear
where trans_freight between 10000 and 11000;
betwwen...and...是一個運算符,也可以用關系運算符與邏輯運算符組合來使用,但效率低。where trans_freight>10000 and trans_freight<11000。
oracle所有的運算符不受數據類型的控制,以上是對數字的判斷,字符串意義不大,重點是對日期時間的判斷。
select clear_time
from tis_ft_g_owner_clear
where clear_time between '2015-07-28 11:13:57' and '2015-07-29 11:47:07';
select *
from tis_bk_role
where not role_id<to_number('001056');
空判斷
select null + 1 from emp; 這個表有幾行,就返回幾行空行
null不能使用關系運算,關系可以判斷的是數據,null屬於一個未知的數據。
select *
from tis_bk_role
where role_id in (001050,001025,001034);
select * from emp where enam like '%%';
select * from emp;
這兩條是一樣的結果,下面雖然效率高,但上面在程序開發中方便后續擴充
order by 字段1 asc|desc,字段2 asc|desc...
默認是按照自然順序排列的,也就是輸入數據時的順序。也可以進行多字段的排序。如果某一個字段重復的話。
所有的排序操作都是在where之后執行的,order by 永遠最后執行。
###############################################
單行函數
字符串函數 replace(),substr(),length(),
select user_accout,initcap(USER_ACCOUT) from tis_bk_user; select user_accout,length(USER_ACCOUT) from tis_bk_user;
select *
from tis_bk_user
where length(user_accout)=5;
replace(列名|數據,‘原內容’,'替換的內容')
利用replace()可以取消字符串中的空格
create table t2 as select * from tis_bk_user_info;
select replace(user_name,'木','森')
from t2
where user_name like '%神木%';
下標從1開始的
substr(列名|數據,開始點) 指定位置到結尾
substr(列名|數據,開始點,長度) 截取范圍
select substr('helloworld',3) from dual;
select substr('helloworld',3,5) from dual;
截取后三個
select substr('helloworld',length('helloworld')-2) from dual;
select substr('helloworld',-3)
數值函數
mod(),round(),trunc() round() 四舍五入 -2小數點前兩位,2小數點后兩位 select round(998.8876568), round(9999.77777655,2), round(9999.77777655,-2), round(-15.132) from dual; trunc() 不四舍五入進行處理 mod() 求模(求余數)
日期函數
日期函數(oracle自己特色) 如何可以取得當前的日期,用偽列sysdata 偽列sysdate,systimestamp, 虛擬表dual select sysdate,systimestamp from dual; 日期計算模式 日期+1 后一天 日期-1 前一天 日期-日期 沒有日期+日期 select sysdate,sysdate-2,sysdate+3 from dual; 如果只是依靠天婁無法獲得一個准確的年或月,所以oracle里面才提供了日期處理函數,利用這些函數可以避免閏年與閏月的問題
計算下一個周二的日期
SQL> select next_day(sysdate,'TUE') from dual;
trunc(months_betwwen(sysdate,hiredate)/12) year
trunc(mod(months_between(sysdate,hiredate)/12)) month
轉換函數
利用to_char進行年,月,日的拆分,只是提供一個思路,oracle本身的一個自動轉換。
to_char
下面兩個幾乎等於無用 to_date to_number to_char(列|日期|數字,格式)
select to_char(sysdate,'yyyy:mm:dd'),to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') from dual; select to_char(98468472392823,'L999,999,999,999,999,999') from dual;
通用函數
nvl()
decode()
#################################################
多表查詢(進入了復雜查詢的階段)
笛卡爾積一直存在,無法消除,雖然能消除顯示問題。數據量一大,多表查詢會帶來嚴重的問題。
多表查詢之中的多張表一定要有關聯關系,否則不能查詢
判斷程序慢的兩種方法:程序算法慢(cpu 占用率高),數據庫數據大(內存占用高)
由數據量決定,用不用多表查詢,如果數據量幾百行,隨便用,幾十萬行,就得選用其它技術點了。
select count(*) from costs a,prod b where a.prod_id=b.prod.id;
有明確的關聯字段的案例如下:
確定要使用的數據表 emp,dept
確定已知的關聯字段 prod_id
select a.pname,a.sal,b.loc,b.job
from emp a,dept b
where a.prod_id=b.prod_id;
沒有明確的關聯字段,而是關聯條件
select e.name,e.sal,s.grade
from emp e,salgrade s
where e.sal between s.lowsal and s.higsal;
分析過程如下:(關聯字段或關聯條件)
第一:寫出第一張表的查詢
第二:引入第二張表,加表,加字段,加條件,消除笛卡爾積的顯示
第三:引入第三張表,加表,加字段,加條件,用and連接。
#################################
表的連接操作
連接操作本身就是一個查詢
select * from dept; select * from salgrade; 兩張表的所有行組合,from之中 select * from salgrade,dept; 兩張表所有組合的任意列,select list之中 select a.grade,b.dname from salgrade a,dept b;
對於兩張表進行多表查詢對於消除笛卡爾積主要依靠連接模式來處理的,表的連接模式有兩種:
內連接:在之前都利用where子句來消除笛卡爾積,只有滿足條件的數據才會顯示出來
外連接:不用管是左還是右,只要所需要的數據全部顯示就可以了。分左外連接,右外連接,全外連接(幾乎不會出現)
where d.deptno=s.deptno(+) 左連接
where d.deptno(+)=s.deptno 右連接
(+)是oracle特有的
left join是以A表的記錄為基礎的,A可以看成左表,B可以看成右表,left join是以左表為准的.
換句話說,左表(A)的記錄將會全部表示出來,而右表(B)只會顯示符合搜索條件的記錄(例子中為: A.aID = B.bID).
B表記錄不足的地方均為NULL.
三種寫法
http://www.cnblogs.com/kerrycode/p/5935704.html
select a.user_id,a.user_account||','||a.user_type aa,b.user_name
from tis_ft_user a,tis_ft_user_info b
where rownum<5 and a.user_id(+)=b.user_id;
select a.user_id,a.user_account||','||a.user_type aa,b.user_name
from tis_ft_user a left join tis_ft_user_info b on a.user_id=b.user_id
where rownum<5;
select user_id,a.user_account||','||a.user_type aa,b.user_name
from tis_ft_user a inner join tis_ft_user_info b using(user_id)
where rownum<5;
仔細觀察一下,就會發現,和left join的結果剛好相反,這次是以右表(B)為基礎的,A表不足的地方用NULL填充.
inner join(相等聯接或內聯接)
sql語句如下:
SELECT * FROM a
INNER JOIN b
ON a.aID =b.bID
等同於以下SQL句:
SELECT *
FROM a,b
WHERE a.aID = b.bID
##################################
數據集合操作 並集,交集,差集,補集
是將若干個查詢結果合並在一起,若干個數據查詢結果所返回的數據結構必須一致。
union 取消重復行
union all
intersect 交集
minus 差集
如果我們需要將兩個select語句的結果作為一個整體顯示出來,我們就需要用到union或者union all關鍵字。union(或稱為聯合)的作用是將多個結果合並在一起顯示出來。
union和union all的區別是,union會自動壓縮多個結果集合中的重復結果,而union all則將所有的結果全部顯示出來,不管是不是重復。
1. union:對兩個結果集進行並集操作,不包括重復行,同時進行默認規則的排序;
2. union All:對兩個結果集進行並集操作,包括重復行,不進行排序;
3. intersect:對兩個結果集進行交集操作,不包括重復行,同時進行默認規則的排序;
4. minus:對兩個結果集進行差操作,不包括重復行,同時進行默認規則的排序。
可以在最后一個結果集中指定Order by子句改變排序方式。
SELECT * FROM emp WHERE sal < 1500; 7369 SMITH CLERK 7902 17-DEC-80 800 20 7521 WARD SALESMAN 7698 22-FEB-81 1250 500 30 7654 MARTIN SALESMAN 7698 28-SEP-81 1250 1400 30 7876 ADAMS CLERK 7788 23-MAY-87 1100 20 7900 JAMES CLERK 7698 03-DEC-81 950 30 7934 MILLER CLERK 7782 23-JAN-82 1300 10 SELECT * FROM emp WHERE sal BETWEEN 1000 AND 2000 ORDER BY 1; 7499 ALLEN SALESMAN 7698 20-FEB-81 1600 300 30 7521 WARD SALESMAN 7698 22-FEB-81 1250 500 30 7654 MARTIN SALESMAN 7698 28-SEP-81 1250 1400 30 7844 TURNER SALESMAN 7698 08-SEP-81 1500 0 30 7876 ADAMS CLERK 7788 23-MAY-87 1100 20 7934 MILLER CLERK 7782 23-JAN-82 1300 10 SELECT * FROM emp WHERE sal < 1500 union SELECT * FROM emp WHERE sal BETWEEN 1000 AND 2000 ORDER BY 1; 7369 SMITH CLERK 7902 17-DEC-80 800 20 7499 ALLEN SALESMAN 7698 20-FEB-81 1600 300 30 7521 WARD SALESMAN 7698 22-FEB-81 1250 500 30 7654 MARTIN SALESMAN 7698 28-SEP-81 1250 1400 30 7844 TURNER SALESMAN 7698 08-SEP-81 1500 0 30 7876 ADAMS CLERK 7788 23-MAY-87 1100 20 7900 JAMES CLERK 7698 03-DEC-81 950 30 7934 MILLER CLERK 7782 23-JAN-82 1300 10 SELECT * FROM emp WHERE sal < 1500 union all SELECT * FROM emp WHERE sal BETWEEN 1000 AND 2000 ORDER BY 1; 7369 SMITH CLERK 7902 17-DEC-80 800 20 7499 ALLEN SALESMAN 7698 20-FEB-81 1600 300 30 7521 WARD SALESMAN 7698 22-FEB-81 1250 500 30 7521 WARD SALESMAN 7698 22-FEB-81 1250 500 30 7654 MARTIN SALESMAN 7698 28-SEP-81 1250 1400 30 7654 MARTIN SALESMAN 7698 28-SEP-81 1250 1400 30 7844 TURNER SALESMAN 7698 08-SEP-81 1500 0 30 7876 ADAMS CLERK 7788 23-MAY-87 1100 20 7876 ADAMS CLERK 7788 23-MAY-87 1100 20 7900 JAMES CLERK 7698 03-DEC-81 950 30 7934 MILLER CLERK 7782 23-JAN-82 1300 10 7934 MILLER CLERK 7782 23-JAN-82 1300 10 SELECT * FROM emp WHERE sal < 1500 intersect SELECT * FROM emp WHERE sal BETWEEN 1000 AND 2000 ORDER BY 1; 7521 WARD SALESMAN 7698 22-FEB-81 1250 500 30 7654 MARTIN SALESMAN 7698 28-SEP-81 1250 1400 30 7876 ADAMS CLERK 7788 23-MAY-87 1100 20 7934 MILLER CLERK 7782 23-JAN-82 1300 10 SELECT * FROM emp WHERE sal < 1500 minus SELECT * FROM emp WHERE sal BETWEEN 1000 AND 2000 ORDER BY 1; 7369 SMITH CLERK 7902 17-DEC-80 800 20 7900 JAMES CLERK 7698 03-DEC-81 950 30
####################################
統計函數(也叫分組函數)
count(),sum(),avg(),:支持數字
max(),min():支持數字,字符串,日期數據類型
在沒有數據的時候,只有count返回結果,其它是null
count()有三種形式:
count(*):統計所有的數據行
count(字段):統計所有不為空的數據行數
count(distinct 字段)統計所有不重復的數據行
####################################
分組統計
group by 找重復的列
第四步:選出所需要的數據列 select *|分組列
第一步:確定數據來源 from table
第二步:篩選數據行 where 條件
第三步:針對篩選的數據行進行分組 group by 分組字段1,分組字段2,
第五步:數據排序 order by
select sid,count(*),min(statistic#),max(statistic#)
from v$sesstat
group by sid;
統計函數
是針對一張表的完整統計,
分組統計
分組的前提是存在有重復,允許單獨一行記錄進行分組。
分組的時候有一些約定條件
1、如果查詢不使用group by 子句,那么select 子句中只允許出現統計函數,其它任何字段不允許出現。
或者說是統計函數不與其它字段同時出現。
正確
select count(*) from emp;
錯誤
select empno,count(*) from emp;
2、如果查詢中使用group by 子句,那么select 子句中只允許出現分組字段,統計函數,其它任何字段都不允許出現。
正確
select job,count(*) from emp group by job;
錯誤
select ename,job,count(*) from emp group by job;
3、統計函數允許嵌套,但是嵌套之后的select 子句里面只允許出現嵌套函數,而不允許出現任何字段,包括分組字段。
正確
select max(avg(sal)) from emp group by deptno;
錯誤
select deptno,max(avg(sal)) from emp group by deptno;
可以將下面的查詢結果想象成一張數據表,這張表沒有group by子句,那么就回到了第一個約定條件,只允許出現統計函數。
所以就解釋了第三個約定條件。
select deptno,avg(sal) from emp group by deptno;
####################################
多表查詢與分組統計
having子句,此時就不能用where子句了,having 跟隨group by 而出現。
針對分組后的數據進行篩選,是在group by
select job,avg(sal)
from emp
group by job
having avg(sal)>2000;
where 與having的區別
1:where 是在group by 之前執行的,先選出可以參與分組的數據,不能使用統計函數。
2:having是在group by 之后執行的,可以使用統計函數。
##########################################
子查詢
子查詢並沒有特殊的語法,可以出現在任意子句之中(select ,from,where,group by,having,order by),但必須用()聲明
子查詢就是查詢的嵌套。
############################################
在where子句中使用子查詢
where子句主要是進行數據的篩選,而且通過分析可以發現,
單行單列,單行多列,多行單列,都可以在where子句
中出現。
--查單行單列的
--要求查出誰的工資最低
不能直接拿800這個數據直接使用,因為這個數據是需要統計出來的,
而想要知道這個內容,可以利用min();
--所以分兩步
1.先查出最低的
select min(sal) from emp;
2.再用最低的去過濾
以上查詢返回單行單列,本質上就是一個數值。
select * from emp
where sal=(select min(sal) from emp);
上下兩個查詢,下面是寫死了,上面動態計算的,比較靈活。
select * from emp
where sal=800;
--查出公司雇佣最早的雇員
select * from emp
where hiredate=(select min(hiredate) from emp);
--子查詢返回單行多列(了解就行,用的不多)
--查出與scott工資相同,職位相同的所有雇員
select * from emp
where
(sal,job)=(select sal,job from emp where ename='SCOTT')
and ename<>'SCOTT';
--子查詢返回多行單列(比較重要)
--子查詢返回多行單列實際上相當於告訴用戶一個數據的操作范圍,從...到...
而如果想要進行范圍的判斷,在where中提供有三個運算符,in,any,all
in與not in
select sal from emp where job='MANAGER';
上面返回了多行單列
select * from emp
where sal in
(select sal from emp where job='MANAGER');
多行單列就相當於給出了我們一個查詢范圍
select * from emp
where sal not in
(select sal from emp where job='MANAGER');
not in中不能有空,否則查不出來。一定要保證子查詢中不能有空
select * from emp
where comm not in
(select comm from emp);
any操作
sal=any 功能上與in沒有區別
sal>any 比子查詢返回內容的最小值要大
sal<any 比子查詢返回內容的最大值要小
select * from emp
where sal>any
(select sal from emp where job='MANAGER');
all操作
sal>all 比子查詢返回內容的最大值要大
sal<all 比子查詢返回內容的最小值要小
select * from emp
where sal<all
(select sal from emp where job='MANAGER');
#################################
exists()條件
主要測試在一個子查詢中行的存在
如果子查詢有數據返回(至少有一行,不管什么數據)就表示條件滿足,那么就可以顯示出數據,否則不顯示
select * from emp
where exists (
select * from emp where deptno=20);
如果子查詢有數據返回,外部查詢就有數據返回,子沒有父就沒有
exists()與in()區別
exists()以行為主
in()以列(數據)為主
exists()要比in()性能更高,判斷行有無比判斷數據有無更快。
使用exists()只關心子查詢里面返回的是否有行,至於什么行,不關心
select * from emp
where exists(
select 'hello' from dual where 1=1);
select * from emp
where not exists(
select 'hello' from dual where 1=2);
##################################################
having子句中使用子查詢
要使用having必須結合group by子句,要使用group by必須要有分組
部門平均工資大於公司平均工資的部門編號,人數與部門工資
select deptno,count(*),avg(sal) from emp
group by deptno
having avg(sal)>(select avg(sal) from emp);
select子句中使用子查詢(基本沒用)
意義不大,性能不高
肯定使用多表查詢
select e.empno,e.job,e.ename,d.dname
from emp e,dept d
where e.deptno=d.deptno;
變換成子查詢
select e.empno,e.job,e.ename,
(select dname d from dept d where d.deptno=e.deptno)
from emp e;
實際上在select子句里面出現的子查詢核心目的在於:行列轉換
from子句中出現子查詢(重點)
主要是思路問題,是需要去思考的
################################################
DML包括查詢與更新。
數據的更新包括:增加,修改,刪除
更新離不開查詢
數據的增加
數據的修改
數據的刪除
先復制一份原始數據
create table myemp as select * from emp;
數據的增加
insert into myemp() values();
常用的三種類型
字符串:‘字符串’
數值:直接編寫
日期:有三種
sysdate
根據日期的保存結構編寫字符串:‘天-年-月’
利用to_date()將字符串轉換為date型數據
完整語法
值與字段對應即可。
insert into myemp(empno,job,sal,hiredate,ename,deptno,mgr,comm)
values(6666,'清潔工',2000,to_date('1988-09-08','yyyy-mm-dd'),'王二',40,7396,null);
執行上面的語句報下面的錯
ORA-01756: quoted string not properly terminated
將清潔工與王二換成英文即可。或者撤銷NLS_LANG環境變量,再insert就可以了,因為我的系統上有這個變量
但是行插進去了,卻亂碼了(變成???)
[oracle@db Downloads]$ echo $NLS_LANG
AMERICAN_AMERICA.ZHS16GBK
[oracle@db Downloads]$ echo $LANG
en_US.UTF-8
亂碼問題先不處理了,所以先選用英文。
insert into myemp(empno,job,sal,hiredate,ename,deptno,mgr,comm)
values(6668,'aa',2000,to_date('1988-09-08','yyyy-mm-dd'),'aa1',40,7396,null);
insert into myemp(empno,job,sal,hiredate,ename,deptno,mgr,comm)
values(6669,'aa',2000,to_date('1986-09-08','yyyy-mm-dd'),'aa2',40,7397,null);
省略字段語法
必須注意要與表中的字段順序一致。
在開發時盡量使用完整語法,一條數據一行
##########################################
update 表名 set 字段=內容,字段=內容,...[where 更新條件(s)]
普通的
update myemp set sal=2500,comm=40 where ename='aa2';
帶子查詢的
update myemp set sal=(select avg(sal) from myemp)
where sal=(select min(sal) from myemp);
update myemp set hiredate=sysdate,sal=sal*1.2
where hiredate between '01-jan-81' and '31-dec-81';
where to_char(hiredate,'yyyy')=1981;
不帶條件的,是修改所有的記錄
update myemp set comm=null;
#################################
先查再刪除
select * from myemp where empno=7369;
delete from myemp where empno=7369;
刪除若干個數據
select * from myemp where empno in(7566,7788,7799);
delete from myemp where empno in(7566,7788,7799);
刪除也可以結合子查詢
select * from myemp order by sal desc;
delete from myemp where sal=(select max(sal) from myemp)
刪除全部數據幾乎是不可能的
delete from myemp;
####################################
事務處理的概念
保證數據完整性的一種手段
具有ACID原則
保證你一個人更新數據的時候,其它人不能更新。
sessionA
sessionB
每一個session有自己獨立的事務。
緩沖區中的數據可以rollback
rollback;
commit;
更新操作被事務保護。要成功就一起成功,要失敗就退回原點重新再來。
事務鎖
兩個session進行同一條數據的操作,誰手快誰成功。
sessionA操作了,但沒提交,sessionB執行的時候會一直等待。也就是說A鎖定了這條數據,在沒有提交或回流之前,sessionB不能操作。只能等待它提交后才能操作。
update myemp set sal=5000 where empno=7566;
update myemp set sal=90000 where empno=7566; 一直等待。
事務處理的過程中,存在行級鎖。事務的隔離性
在整個程序的世界里,只有兩個方法可以評價程序:時間復雜度與空間復雜度
時間換空間,不加硬件的情況下,就等吧。
空間換時間。加硬件,不加硬件的話,用雲計算,來臨時空間換時間。
在不改變現有硬件的情況下,可以利用一個周期來完成,不是一次完成。可能需要半年時間,但不影響用戶。活躍用戶與僵shi用戶。
################################
偽列,很多,重要的就這兩個
列本身不存在,但卻可以使用
rownum 行號
rowid 數據開發並不重要,數據分析時會用到
select rownum,empno,ename,job from emp;
不是固定的,是動態生成的。行號是根據查詢結果動態生成的。
select rownum,empno,ename,job from emp where deptno=10;
rownum做兩件事
1、取得第一行
select rownum,empno,ename,job from emp where deptno=10 and rownum=1;
一般不會做select * from 表名;的操作,因為如果表太大的話,會是災難的
一般只查第一行。
2、取得前N行(一個更為重要的特性)
select * from emp where rownum<=10;
6到10行的記錄,分頁程序就是這樣實現的,上一頁與下一頁。這是很普遍的
select *
from(
select rownum rn,ename,empno from emp where rownum <=10) temp
where temp.rn>5;
分頁的固定格式
currentPage 當前頁
lineSize 每頁行數
select *
from (
select rownum rn,列,...
from 表名
where rownum<=currentPage*lineSize) temp
where temp.rn>(currentPage-1)*lineSize;
樣例:
select *
from(
select rownum rn,ename,empno
from emp
where rownum <=9) temp
where temp.rn>6;
#############################
rowid 理解就可以了
分析上使用,開發時不常用。
針對每行數據提供一個物理地址。
select rowid,job,ename from emp;
AAAVREAAEAAAACXAAA
AAAVRE 數據對象編號
AAE 數據文件編號
AAAACX 數據塊號
AAA 數據行號
題目:刪除表中重復的數據,只保留最原始的一個。
create table mydept as select * from dept;
SQL> select rowid,deptno,dname,loc from mydept;
ROWID DEPTNO DNAME LOC
------------------ ---------- -------------- -------------
AAAV5uAAEAAAAMzAAA 10 ACCOUNTING NEW YORK
AAAV5uAAEAAAAMzAAB 20 RESEARCH DALLAS
AAAV5uAAEAAAAMzAAC 30 SALES CHICAGO
AAAV5uAAEAAAAMzAAD 40 OPERATIONS BOSTON
插入測試數據
insert into mydept(deptno,dname,loc) values(10,'ACCOUNTING','NEW YORK');
insert into mydept(deptno,dname,loc) values(20,'RESEARCH','DALLAS');
insert into mydept(deptno,dname,loc) values(30,'SALES','CHICAGO');
insert into mydept(deptno,dname,loc) values(40,'OPERATIONS','BOSTON');
表的不正當設計,造成了表中有重復數據,所以為了刪除,就要用到rowid來解決。
rowid是一直累加的,不會減小。原始數據的rowid較小,所以先分組,再將分組中較小的查出來,
然后取反(not in)刪除即可。
select rowid,deptno,dname,loc from mydept;
delete from mydept where rowid not in(
select min(rowid)
from mydept
group by deptno,dname,loc);
min()是一個多行單列
select max(rowid),deptno,dname,loc
from mydept
group by deptno,dname,loc;
這只是rowid的一個使用說明,講解索引的時候也會用到rowid