【數據庫】Oracle -- 一文了解Oracle數據庫開發知識地圖

1.Oracle數據庫安裝

1.1.整合PL/SQL Developer軟件

1.點擊Tools—>Preferences—>Connection鏈接,填寫鏈接信息:java

 

2.鏈接Oracle數據庫,默認鏈接方式:mysql

192.168.88.6:表示安裝Oracle數據庫的服務器地址;git

1521:默認端口號github

orcl:默認Oracle安裝數據庫名稱sql

 

3.使用修改tnsnames.ora文件配置方式鏈接:數據庫

①複製遠程服務器Oracle安裝目錄中的tnsnames.ora到本地的instantclient_12_1軟件目錄下:編程

 

 ②修改本地複製的tnsnames.ora配置以下:服務器

 

 ③設置本地tnsnames.ora到本地的環境變量配置中:oracle

 配置完環境變量以後在繼續登陸PL/SQL去鏈接Oracle數據庫就可使用ORCL去鏈接數據庫了。app

 

2.Oracle體系結構

2.1.數據庫

Oracle數據庫是數據的物理存儲。這就包括(數據文件ORA或者DBF、控制文件、聯機日誌、參數文件)。其實Oracle數據庫的概念和其它數據庫不同,這裏的數據庫是一個操做系統只有一個庫。能夠看做是Oracle就只有一個大數據庫。

 

2.2.實例

一個Oracle實例(Oracle Instance)有一系列的後臺進程(Background Processes)和內存結構(Memory Structures)組成。一個數據庫能夠有n個實例。

 

2.3.用戶

用戶是在實例下創建的。不一樣實例能夠建相同名字的用戶。

 

2.4.表空間

表空間是Oracle對物理數據庫上相關數據文件(ORA或者DBF文件)的邏輯映射。一個數據庫在邏輯上被劃分紅一到若干個表空間。每一個表空間包含了在邏輯上相關的一組結構。每一個數據庫至少有一個表空間(稱之爲system表空間)。

每一個表空間由同一磁盤上的一個或多個文件組成。這些文件叫數據文件(datafile)。一個數據文件只能屬於一個表空間。

 

2.5.數據文件(dbf、ora)

數據文件是數據庫的物理存儲單位。數據庫的數據是存儲在表空間中的,真正是在某一個或者多個數據文件中。而一個表空間能夠由一個或多個數據文件組成,一個數據文件只能屬於一個表空間。一旦數據文件被加入到某個表空間後,就不能刪除這個文件,若是要刪除某個數據文件,只能刪除所屬於的表空間才行。

注意:表的數據,是有用戶放入某一個表空間的,而這個表空間會隨機把這些表數據放到一個或者多個數據文件中。

因爲oracle的數據庫不是普通的概念,oracle是有用戶和表空間對數據進行管理和存放的。可是表不是有表空間去查詢的,而是由用戶去查的。由於不一樣用戶能夠在同一個表空間創建同一個名字的表!這裏區分就是用戶了。

 

3.建立表空間

表空間是Oracle數據庫的邏輯單元。數據庫--表空間,一個表空間能夠與多個數據文件(物理結構)關聯。

一個數據庫下能夠創建多個表空間,一個表空間能夠創建多個用戶、一個用戶下能夠創建多個表。

create tablespace mytable
datafile 'c:\mytable.dbf'
size 100m
autoextend on
next 10m

其中

mytable:爲表空間名稱

datafile:指定表空間對應的數據文件

size:後定義的是表空間的初始大小

autoextend on:自動增加,當表空間存儲都佔滿時,自動增加

next:後指定的是一次自動增加的大小

 

編寫好sql語句以後,點擊小齒輪按鈕,Excute執行便可。

以下語句是建立表空間語句:

 

以下是刪除表空間語句:

 

4.用戶

建立用戶並給用戶受權:

 

 切換登陸用戶:

先選擇Log off進行退出當前用戶,再選擇Log on進行登陸;修改登陸用戶名與密碼進行登陸便可;

 

5.Oracle數據類型

No 數據類型 描述
1 varchar,varchar2 表示一個字符串,可變長度,經常使用的類型是varchar2
2 NUMBER NUMBER(n)表示一個整數,長度是n
3 NUMBER NUMBER(m, n)表示一個小數,總長度是m,小數是n,整數是m-n
4 DATA

表示日期類型

5 CLOB 大對象,表示大文本數據類型,可存4G
6 BLOB 大對象,表示二進制數據,可存4G

 

 6.表的管理

6.1.建表

語法:

create table 表名(

  字段1 數據類型 [default 默認值],

  字段2 數據類型 [default 默認值],

  ...

)

示例:

 

6.2.修改表結構

添加一列數據,若是多列數據使用(n1, n2):

--- 修改表結構
--- 添加一列
alter table person add (gender number(1));

添加以後查看錶結構:

 

 

 

修改列類型:

---修改列類型
alter table person modify gender char(1);

修改列名稱:

---修改列名稱
alter table person rename column gender to sex;

刪除一列:

---刪除一列
alter table person drop column sex;

 

6.3.數據的增刪改

添加數據insert:

---添加一條記錄
insert into person(pid, pname) values (1, '小明');
commit

修改數據update:

---修改一條記錄
update person set pname = '小馬' where pid = 1;
commit;

刪除表數據delete/truncate/drop:

---三個刪除
---刪除表中所有記錄
delete from person;
---刪除表結構
drop table person;
---先刪除表,再次建立表。效果等同於刪除表中所有記錄
---在數據量大的狀況下,尤爲在表中帶有索引的狀況下,該操做效率高。
---索引能夠提供查詢效率,可是會影響增刪改效率
truncate table person;

 

6.4.序列

---序列不真的屬於任何一張表,可是能夠邏輯和表作綁定
---序列:默認從1開始,依次遞增,主要用來給主鍵賦值使用
---dual:虛表,只是爲了補全語法,沒有任何意義
create sequence s_person;
select s person.currval from dual;

---添加一條記錄
insert into person (pid, pname) values (s_person.nextval, '小明');
commit;
select * from person;

 

6.5.Scott用戶介紹

scott是給初學者學習的用戶,學習者能夠用Scott登陸系統,注意scott用戶登陸後,就可使用Oracle提供的數據庫和數據表,這些都是oracle提供的,學習者不須要本身建立數據庫和數據表,直接使用這些數據庫和數據表練習SQL。

---scott用戶,密碼是tiger
---解鎖scott用戶
alter user scott account unlock;
---解鎖scott用戶的密碼【此句也能夠用來重置密碼】
alter user scott identified by tiger;

 

7.Oracle查詢

7.1.單行/多行函數

單行函數:做用於一行,返回一個值。

多行函數:做用於多行,返回一個值。

字符函數

select upper('yes') from dual;  -- YES
select lower('YES') from dual;  -- yes

數值函數

select round(26.16, 1) from dual;  -- 四捨五入,後面的參數表示保留的位數,結果26.2
select round(26.16, -1) from dual; -- 往前保留一位小數,結果30
select trunc(56.16, 1) from dual; -- 直接截取,再也不看後邊位數的數字是否大於5。56.1
select mod(10, 3) from dual;  -- 求餘數

日期函數

---查詢出emp表中全部員工入職距離如今幾天
select sysdate-e.hiredate from emp e;
---算出明天此刻
select sysdate+1 from dual;
---查詢出emp表中全部員工入職距離如今幾月
select months_between(sysdate, e.hiredate) from emp e;
---查詢出emp表中全部員工入職距離如今幾年
select months_between(sysdate, e.hiredate)/12 from emp e;
---查詢出emp表中全部員工入職距離如今幾周
select round((sysdate-e.hiredate)/7) from emp e;

轉換函數

日期轉換成字符串

注意:fm表示若是是"04"格式前面會自動省略0,展現爲"4";

---轉換函數
select to_char(sysdate, 'fm yyyy-mm-dd hh24:mi:ss') from dual;

 

字符串轉日期

---字符串轉日期
select to_date('2018-6-7 16:39:50', 'fm yyyy-mm-dd hh24:mi:ss') from dual;

 

多行函數(聚合函數)

---多行函數【聚合函數】:做用於多行,返回一個值。
select count(1) from emp;   ---查詢總數量
select sum(sal) from emp;   ---工資總和
select max(sal) from emp;   ---最大工資
select min(sal) from emp;   ---最低工資
select avg(sal) from emp;   ---平均工資

 

7.2.通用函數

--- 通用函數
--- 算出emp表中全部員工的年薪
--- 獎金裏面有null值,若是null值和任意數字作算術運算,結果都是null
select e.sal*12+nvl(e.comm, 0) from emp e;

計算結果:

 

7.3.條件表達式

如下兩種表達式爲mysql、oracle通用表達式:

第一種:

---條件表達式
---給emp表中員工起中文名
select e.ename,
       case e.ename
           when 'SMITH' then '曹賊'
           when 'ALLEN' then '大耳賊'
           when 'WARD'  then '諸葛小兒'
           else '無名'  --- 注意:若是else不寫則爲null
           end
from emp e;

 

第二種:

---判斷emp表中員工工資,若是高於3000顯示高收入;若是高於1500低於3000顯示中等收入;其他顯示低收入
select e.sal,
    case
     when e.sal>3000 then '高收入'
     when e.sal>1500 then '中等收入'
     else '低收入'
    end
from emp e;

 

如下寫法爲oracle中專用條件表達式

其中"中文名"爲別名,別名使用雙引號,其他都用單引號。

---oracle專用條件表達式
select e.ename,
    decode(e.ename,
          'SMITH', '曹賊',
          'ALLEN', '大耳賊',
          'WARD', '諸葛小兒',
          '無名') 中文名
from emp e;

 

7.4.聚合函數

---分組查詢
---查詢出每一個部門的平均工資
---分組查詢中,出如今group by 後面的原始列,才能出如今select後面
---沒有出如今group by後面的列,想在select後面,必須加上聚合函數
---聚合函數有一個特性,能夠把多行記錄變成一個值
select e.deptno, avg(e.sal)
from emp e
group by e.deptno;

 

別名問題:

---查詢出平均工資高於2000的部門信息
select e.deptno, avg(e.sal) asal
from emp e
group by e.deptno
having avg(e.sal)>2000;
---全部條件都不能使用別名來判斷
---好比下面的條件語句也不能使用別名當條件
select ename, sal s from emp where sal>1500;

 

分組group by與having問題:

---where是過濾分組前的數據,having是過濾分組後的數據
---表現形式:where必須在group by以前,having是在group by以後
---查詢出每一個部門工資高於800的員工的平均工資
---而後再查詢出平均工資高於2000的部門
select e.deptno, avg(e.sal) asal
from emp e
where e.sal>800
group by e.deptno
having avg(e.sal)>2000;

 

7.5.多表鏈接查詢

left join、right join、inner join

oracle中特有的鏈接方式,(+)在的地方表示right join等同

---oracle中專用外鏈接
select *
from emp e, dept d
where e.deptno(+) = d.deptno;

 

7.6.自鏈接查詢

---查詢出員工姓名,員工領導姓名
---自鏈接:自鏈接其實就是站在不一樣的角度把一張表當作多張表
select e1.ename, e2.ename
from emp e1, emp e2
where e1.mgr = e2.empno;

 

7.7.分頁查詢

---rownum行號:當咱們作select操做的時候,
---沒查詢出一行記錄,就會在該行上加上一個行號,
---行號從1開始,依次遞增,不能跳着走
---emp表工資倒敘排列後,每頁五條記錄,查詢第二頁
---排序操做會影響rownum的順序
select rownum, e.* from emp e order by e.sal desc
---若是涉及到排序,可是還要使用rownum的話,咱們能夠再次嵌套查詢
select rownum, t.* from(
    select rownum, e.* from emp e order by e.sal desc) t;

 

分頁查詢固定格式:

---emp表工資倒敘排列後,每頁五條記錄,查詢第二頁
---rownum行號不能寫上大於一個正數
select * from(
    select rownum rn, tt.* from(
        select * from emp order by sal desc  ---這裏能夠寫須要進行分頁的數據
    ) tt where rownum < 11
) where rn > 5;

 

8.Oracle視圖

視圖:視圖就是提供一個查詢的窗口,全部數據來自於原表。

-- 查詢語句建立表
create table emp as select * from scott.emp;
select * from emp;
-- 建立視圖【必須有dba權限】
create view v_emp as select ename, job from emp;
-- 查詢視圖
select * from v_emp;
-- 修改視圖[不推薦]
update v_emp set job ='CLERK' where ename = 'ALLEN';
commit;
-- 建立只讀視圖
create view v_emp as select ename, job from emp with read only;

視圖的做用:

第一:視圖能夠屏蔽掉一些敏感字段;

第二:保證總部和分部數據及時統一;

 

9.Oracle索引

索引:索引就是在表的列上構建一個二叉樹,達到大幅度提升查詢效率的目的,可是索引會影響增刪改的效率。

索引分爲:單列索引複合索引

-- 建立單列索引
create index idx_ename on emp(ename);
-- 單列索引觸發規則,條件必須是索引列中的原始值
-- 單行函數,模糊查詢,都會影響索引的觸發
select * from emp where ename = "SOCTT";
-- 複合索引
-- 建立複合索引
create index idx_enamejob on emp(ename, job);
-- 複合索引中第一列爲優先檢索列
-- 若是要觸發複合索引,必須包含有優先檢索列中的原始值
select * from emp where ename = 'SCOTT' and job = 'XX';  -- 觸發複合索引
select * from emp where ename = 'SCOTT' or job = 'XX';  -- 不觸發索引
select * from emp where ename = 'SCOTT';  -- 觸發單列索引

建立結果以下:

 

10.PL/SQL編程語言

pl/sql編程語言是對sql語言的擴展,使得sql語言具備過程化編程的特性。

pl/sql編程語言比通常的過程化編程語言,更加靈活高效。

pl/sql編程語言主要用來編寫存儲過程和存儲函數等。

10.1.pl/sql編程基礎語法

--- 聲明方法
--- 賦值操做可使用:=也可使用into查詢語句賦值
declare
    i number(2) := 10;
    s varchar2(10) := '小明';
    ena emp.ename%type; ---引用型變量
    emprow emp%rowtype; ---記錄型變量
begin
    dbms_output.put_line(i);
    dbms_output.put_line(s);
    select ename into ena from emp where empno = 7788;
    dbms_output.put_line(ena);
    select * into emprow from emp where empno = 7788;
    dbms_output.put_line(emprow.ename || '的工做爲:' || emprow.job)
end;

 

10.2.pl/sql中的if判斷

--- 輸入小於18的數字,輸出未成年
--- 輸入大於18小於40的數字,輸出中年人
--- 輸入大於40的數字,輸出老年人
declare
    i number(3) := &ii;
begin
    if i<18 then
        dbms_output.put_line('未成年');
    elsif i<40 then
        dbms_output.put_line('中年人');
    else
        dbms_output.put_line('老年人');
    end if;
end;

 

10.3.pl/sql中的loop循環

--- pl/sql中的loop循環
--- 用三種方式輸出1到10是個數字
--- while循環
declare
    i number(2) := 1;   --- 定義變量並賦值
begin
    while i<11 loop
        dbms_output.put_line(i);
        i := i+1;
    end loop
end;
--- exit循環
declare 
    i number(2) := 1;
begin
  loop
    exit when i > 10;
    dbms_output.put_line(i);
    i := i+1;
  end loop;
end;
--- for循環
declare 

begin
  for i in 1..10 loop
      dbms_output.put_line(i);
  end loop;
end;

 

10.4.pl/sql遊標

遊標:能夠存放多個對象,多行記錄。

--- 輸出emp表中全部員工的姓名
declare
    cursor c1 is select * from emp;
    emprow emp%rowtype;
begin
    open c1;
        loop
            fetch c1 into emprow;
            exit when c1%notfound;
            dbms_output.put_line(emprow.ename);
        end loop;
    close c1;
end;

--- 給指定部門員工漲工資
declare
    cursor c2(eno emp.deptno%type) 
    is select empno from emp where deptno = eno;
    en emp.empno%type;
begin
    open c2(10);
        loop
            fetch c2 into en;
            exit when c2%notfound;
            update emp set sal=sal+100 where empno = en;
            commit;
        end loop;
    close c2;
end;

 

10.5.存儲過程

存儲過程存儲過程就是提早已經編譯好的一段pl/sql語言,放置在數據庫中

能夠被直接調用。這一段pl/sql通常都是固定步驟的業務。

存儲過程的建立

--- 給指定員工漲100塊錢
--- 使用or replace
create or replace procedure p1(eno emp.empno%type)
is

begin
    update emp set sal=sal+100 where empno = eno;
    commit;
end;

--- 測試p1
declare

begin
    p1(7788);
end;
--- 經過存儲函數實現計算指定員工的年薪
--- 存儲過程和存儲函數的參數都不能帶長度
--- 存儲函數的返回值類型不能帶長度
create or replace function f_yearsal(eno emp.empno%type) return number
is
    s number(10);
begin
    select sal*12+nvl(comm, 0) into s from emp where empno = eno;
    return s;
end;

---測試f_yearsql
---存儲函數在調用的時候,返回值須要接收
declare
    s number(10);
begin
    s:= f_yearsal(7788);
    dbms_output.put_line(s);
end;

---out類型參數如何使用 out類型參數使用:
---使用存儲過程來算年薪
create or replace procedure p_yearsal(eno emp.empno%type, yearsal out number)
is
    s number(10);
    c emp.comm%type;
begin
    select sal*12, nvl(comm, 0) into s, c from emp where empno = eno;
    yearsal := s+c;
end;

---測試p_yearsal
declare
    yearsal number(10);
begin
    p_yearsal(7788, yearsal);
    dbms_output.put_line(yearsal);
end;

---in和out類型參數的區別是什麼?
---凡是涉及到into查詢語句賦值或者:=賦值操做的參數,都必須使用out來修飾

 

存儲過程存儲函數的區別:

語法區別:關鍵字不同;存儲函數比存儲過程多了兩個return

本質區別:存儲函數有返回值,而存儲過程沒有返回值

若是存儲過程想實現有返回值的業務,咱們就必須使用out類型的參數。即使是存儲過程使用了out類型的參數,其本質也不是真的有了返回值。而是在存儲過程內部給out類型參數賦值,在執行完畢後,咱們直接拿到輸出類型參數的值。

 

咱們可使用存儲函數有返回值的特性,來自定義函數。

而存儲過程不能用來自定義函數。

--- 案例需求:查詢出員工姓名,員工所在部門名稱

--- 案例準備工做:把scott用戶下的dept表複製到當前用戶下
create table dept as select * from scott.dept;
--- 使用傳統方式來實現案例需求
select e.ename, d.dname
from emp e, dept d
where e.deptno = d.deptno;

---使用存儲函數來實現提供一個部門編號,輸出一個部門名稱
create or replace function fdna(dno dept.deptno%type) return dept.dname%type
is
    dna dept.dname%type;
begin
    select dname into dna from dept where deptno = dno;
    return dna;
end;
--使用fdna存儲函數來實現案例需求:查詢出員工姓名,員工所在部門名稱
select e.ename, fdna(e.deptno)
from emp e;

 

10.6.觸發器

觸發器:就是指定一個規則,在咱們作增刪改操做的時候,主要知足該規則,自動觸發,無需調用。

觸發器分爲:語句級觸發器行級觸發器

語句級觸發器:不包含有for each row的觸發器。

行級觸發器:包含有for each row的行級觸發器。

加for each row是爲了使用:old或者:new對象或者一行記錄。

--- 語句級觸發器
--- 插入一條記錄,輸出一個新員工入職
create or replace trigger t1
after
insert
on person
declare 

begin
    dbms_output.put_line('一個新員工入職');
end;
---觸發t1
insert into person values (1, '小紅');
commit;
select * from person;
--- 行級觸發器
--- 不能給員工降薪
--- raise_application_error(-20001~20999之間, '錯誤提示信息');
create or replace trigger t2
before 
update
on emp
for each row
declare

begin
    if :old.sal > :new.sal then
        raise_application_error(-20001, '不能給員工降薪');
    end if;
end;
---觸發t2
select * from emp where empno = 7788;
update emp set sal=sal-1 where empno = 7788;
commit;

 

觸發器實現主鍵自增:

用到的是行級觸發器

--- 分析:在用戶作插入操做以前,拿到即將插入的數據。給該數據中的主鍵列賦值
create or replace trigger auid
before
insert
on person
for each row
declare

begin
    select s_person.nextval into :new.pid from dual;
end;
---查詢person表數據
select * from person;
---使用auid實現主鍵自增
insert into person (pname) values ('a');
commit;

 

11.Java調用存儲過程

11.1.Java調用Oracle存儲過程環境準備

oracle10g使用ojdbc14.jar包;

oracle11g使用ojdbc6.jar

1.建立Maven工程,導入如下依賴jar包:

<dependencies>
    <dependency>
        <groupId>com.oralce</groupId>
        <artifactId>ojdbc14</artifactId>
        <version>10.2.0.4.0</version>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.10</version>
        <scope>test</scope>
    </dependency>
</dependencies>

 

11.2.調用存儲過程代碼實現

jdbc.properties配置:

String driverName = "oracle.jdbc.driver.OracleDriver";
String url = "jdbc:oracle:thin:@192.168.79.10:1521:orcl";
String username = "scott";
String password = "tiger";

 

1.執行查詢操做:

 @Test
public void javaCallOracle() throws Exception {
    //加載數據庫驅動
    Class.forName("oracle.jdbc.driver.OracleDriver");
    //獲得Connection鏈接
    Connection connection = DriverManager.getConnection("jdbc:oracle:thin:@192.168.88.6:1521:orcl", "scott", "tiger");
    //獲得預編譯的Statement對象
    PreparedStatement pstm = connection.prepareStatement("select * from emp where empno = ?");
    //給參數賦值
    pstm.setObject(1, 7788);
    //執行數據庫查詢操做
    ResultSet rs = pstm.executeQuery();
    //輸出結果
    while(rs.next()){
        System.out.println(rs.getString("ename"));
    }
    //釋放資源
    rs.close();
    pstm.close();
    connection.close();
}

 

2.java調用存儲過程:

/**
  * java調用存儲過程
  * {?= call <procedure-name>[(<arg1>,<arg2>, ...)]}   調用存儲函數使用
  *  {call <procedure-name>[(<arg1>,<arg2>, ...)]}   調用存儲過程使用
  * @throws Exception
  */
@Test
public void javaCallProcedure() throws Exception {
    //加載數據庫驅動
    Class.forName("oracle.jdbc.driver.OracleDriver");
    //獲得Connection鏈接
    Connection connection = DriverManager.getConnection("jdbc:oracle:thin:@192.168.88.6:1521:orcl", "scott", "tiger");
    //獲得預編譯的Statement對象
    CallableStatement pstm = connection.prepareCall("{call p_yearsal(?, ?)}");
    //給參數賦值
    pstm.setObject(1, 7788);
    pstm.registerOutParameter(2, OracleTypes.NUMBER);
    //執行數據庫查詢操做
    pstm.execute();
    //輸出結果[第二個參數]
    System.out.println(pstm.getObject(2));
    //釋放資源
    pstm.close();
    connection.close();
}

 

3.java調用存儲函數

 /**
   * java調用存儲函數
   * {?= call <procedure-name>[(<arg1>,<arg2>, ...)]}   調用存儲函數使用
   *  {call <procedure-name>[(<arg1>,<arg2>, ...)]}   調用存儲過程使用
   * @throws Exception
   */
@Test
public void javaCallFunction() throws Exception {
    //加載數據庫驅動
    Class.forName("oracle.jdbc.driver.OracleDriver");
    //獲得Connection鏈接
    Connection connection = DriverManager.getConnection("jdbc:oracle:thin:@192.168.88.6:1521:orcl", "scott", "tiger");
    //獲得預編譯的Statement對象
    CallableStatement pstm = connection.prepareCall("{?= call f_yearsal(?)}");
    //給參數賦值
    pstm.setObject(2, 7788);
    pstm.registerOutParameter(1, OracleTypes.NUMBER);
    //執行數據庫查詢操做
    pstm.execute();
    //輸出結果[第一個參數]
    System.out.println(pstm.getObject(1));
    //釋放資源
    pstm.close();
    connection.close();
}

 

本博客相關文檔筆記均已上傳至GitHub地址:

OracleDBReview

相關文章
相關標籤/搜索