什麼是存儲過程?有哪些優缺點?javascript
存儲過程就像咱們編程語言中的函數同樣,封裝了咱們的代碼(PLSQL、T-SQL)。php
存儲過程的優勢:html
存儲過程的缺點:java
三個範式是什麼python
第一範式(1NF):數據庫表中的字段都是單一屬性的,不可再分。這個單一屬性由基本類型構成,包括整型、實數、字符型、邏輯型、日期型等。
第二範式(2NF):數據庫表中不存在非關鍵字段對任一候選關鍵字段的部分函數依賴(部分函數依賴指的是存在組合關鍵字中的某些字段決定非關鍵字段的狀況),也即全部非關鍵字段都徹底依賴於任意一組候選關鍵字。
第三範式(3NF):在第二範式的基礎上,數據表中若是不存在非關鍵字段對任一候選關鍵字段的傳遞函數依賴則符合第三範式。所謂傳遞函數依賴,指的是若是存在"A → B → C"的決定關係,則C傳遞函數依賴於A。所以,知足第三範式的數據庫表應該不存在以下依賴關係: 關鍵字段 → 非關鍵字段x → 非關鍵字段ymysql
上面的文字咱們確定是看不懂的,也不肯意看下去的。接下來我就總結一下:程序員
首先要明確的是:知足着第三範式,那麼就必定知足第二範式、知足着第二範式就必定知足第一範式sql
第一範式:字段是最小的的單元不可再分數據庫
第二範式:知足第一範式,表中的字段必須徹底依賴於所有主鍵而非部分主鍵。編程
第三範式:知足第二範式,非主鍵外的全部字段必須互不依賴
參考連接:
什麼是視圖?以及視圖的使用場景有哪些?
視圖是一種基於數據表的一種虛表
有的時候,咱們可能只關係一張數據表中的某些字段,而另外的一些人只關係同一張數據表的某些字段...
那麼把所有的字段都都顯示給他們看,這是不合理的。
咱們應該作到:他們想看到什麼樣的數據,咱們就給他們什麼樣的數據...一方面就可以讓他們只關注本身的數據,另外一方面,咱們也保證數據表一些保密的數據不會泄露出來...
[圖片上傳失敗...(image-bfc6ce-1520388670690)]
咱們在查詢數據的時候,經常須要編寫很是長的SQL語句,幾乎每次都要寫很長很長....上面已經說了,視圖就是基於查詢的一種虛表,也就是說,視圖能夠將查詢出來的數據進行封裝。。。那麼咱們在使用的時候就會變得很是方便...
值得注意的是:使用視圖可讓咱們專一與邏輯,但不提升查詢效率
drop、delete與truncate分別在什麼場景之下使用?
咱們來對比一下他們的區別:
drop table
truncate table
delete from
索引是什麼?有什麼做用以及優缺點?
什麼是索引【Index】
索引表把數據變成是有序的....
[圖片上傳失敗...(image-22098f-1520388670690)]
快速定位到硬盤中的數據文件...
[圖片上傳失敗...(image-7be20b-1520388670690)]
rowid的特色
索引的特色
須要注意的是:Oracle是自動幫咱們管理索引的,而且若是咱們指定了primary key或者unique約束,系統會自動在對應的列上建立索引..
何時【要】建立索引
何時【不要】建立索引
索引優缺點:
索引分類:
深刻理解索引可參考:
什麼是事務?
事務簡單來講:一個Session中所進行全部的操做,要麼同時成功,要麼同時失敗
ACID — 數據庫事務正確執行的四個基本要素
一個支持事務(Transaction)中的數據庫系統,必須要具備這四種特性,不然在事務過程(Transaction processing)當中沒法保證數據的正確性,交易過程很可能達不到交易。
舉個例子:A向B轉帳,轉帳這個流程中若是出現問題,事務可讓數據恢復成原來同樣【A帳戶的錢沒變,B帳戶的錢也沒變】。
事例說明:
/* * 咱們來模擬A向B帳號轉帳的場景 * A和B帳戶都有1000塊,如今我讓A帳戶向B帳號轉500塊錢 * * */ //JDBC默認的狀況下是關閉事務的,下面咱們看看關閉事務去操做轉帳操做有什麼問題 //A帳戶減去500塊 String sql = "UPDATE a SET money=money-500 "; preparedStatement = connection.prepareStatement(sql); preparedStatement.executeUpdate(); //B帳戶多了500塊 String sql2 = "UPDATE b SET money=money+500"; preparedStatement = connection.prepareStatement(sql2); preparedStatement.executeUpdate();
從上面看,咱們的確能夠發現A向B轉帳,成功了。但是若是A向B轉帳的過程當中出現了問題呢?下面模擬一下
//A帳戶減去500塊 String sql = "UPDATE a SET money=money-500 "; preparedStatement = connection.prepareStatement(sql); preparedStatement.executeUpdate(); //這裏模擬出現問題 int a = 3 / 0; String sql2 = "UPDATE b SET money=money+500"; preparedStatement = connection.prepareStatement(sql2); preparedStatement.executeUpdate();
顯然,上面代碼是會拋出異常的,咱們再來查詢一下數據。A帳戶少了500塊錢,B帳戶的錢沒有增長。這明顯是不合理的。
咱們能夠經過事務來解決上面出現的問題
//開啓事務,對數據的操做就不會當即生效。 connection.setAutoCommit(false); //A帳戶減去500塊 String sql = "UPDATE a SET money=money-500 "; preparedStatement = connection.prepareStatement(sql); preparedStatement.executeUpdate(); //在轉帳過程當中出現問題 int a = 3 / 0; //B帳戶多500塊 String sql2 = "UPDATE b SET money=money+500"; preparedStatement = connection.prepareStatement(sql2); preparedStatement.executeUpdate(); //若是程序能執行到這裏,沒有拋出異常,咱們就提交數據 connection.commit(); //關閉事務【自動提交】 connection.setAutoCommit(true); } catch (SQLException e) { try { //若是出現了異常,就會進到這裏來,咱們就把事務回滾【將數據變成原來那樣】 connection.rollback(); //關閉事務【自動提交】 connection.setAutoCommit(true); } catch (SQLException e1) { e1.printStackTrace(); }
上面的程序也同樣拋出了異常,A帳戶錢沒有減小,B帳戶的錢也沒有增長。
注意:當Connection遇到一個未處理的SQLException時,系統會非正常退出,事務也會自動回滾,但若是程序捕獲到了異常,是須要在catch中顯式回滾事務的。
數據庫定義了4個隔離級別:
分別對應Connection類中的4個常量
髒讀:一個事務讀取到另一個事務未提交的數據
例子:A向B轉帳,A執行了轉帳語句,但A尚未提交事務,B讀取數據,發現本身帳戶錢變多了!B跟A說,我已經收到錢了。A回滾事務【rollback】,等B再查看帳戶的錢時,發現錢並無多。
不可重複讀:一個事務讀取到另一個事務已經提交的數據,也就是說一個事務能夠看到其餘事務所作的修改
注:A查詢數據庫獲得數據,B去修改數據庫的數據,致使A屢次查詢數據庫的結果都不同【危害:A每次查詢的結果都是受B的影響的,那麼A查詢出來的信息就沒有意思了】
虛讀(幻讀):是指在一個事務內讀取到了別的事務插入的數據,致使先後讀取不一致。
注:和不可重複讀相似,但虛讀(幻讀)會讀到其餘事務的插入的數據,致使先後讀取不一致
簡單總結:髒讀是不可容忍的,不可重複讀和虛讀在必定的狀況下是能夠的【作統計的確定就不行】。
數據庫的樂觀鎖和悲觀鎖是什麼?
確保在多個事務同時存取數據庫中同一數據時不破壞事務的隔離性和統一性以及數據庫的統一性,樂觀鎖和悲觀鎖是併發控制主要採用的技術手段。
悲觀鎖:假定會發生併發衝突,屏蔽一切可能違反數據完整性的操做
樂觀鎖:假設不會發生併發衝突,只在提交操做時檢查是否違反數據完整性。
悲觀鎖:
[圖片上傳失敗...(image-25e4f4-1520388670690)]
樂觀鎖:
[圖片上傳失敗...(image-54cbf0-1520388670690)]
參考資料:
SQL 約束有哪幾種?
數據庫運行於哪一種狀態下能夠防止數據的丟失?
在archivelog mode(歸檔模式)只要其歸檔日誌文件不丟失,就能夠有效地防止數據丟失。
Mysql的存儲引擎有如下幾種:
[圖片上傳失敗...(image-491584-1520388670690)]
個人是5.7.15版本,默認使用的是Innodb版本!
經常使用的存儲引擎有如下:
[圖片上傳失敗...(image-34e292-1520388670690)]
同一個數據庫也可使用多種存儲引擎的表。若是一個表修改要求比較高的事務處理,能夠選擇InnoDB。這個數據庫中能夠將查詢要求比較高的表選擇MyISAM存儲。若是該數據庫須要一個用於查詢的臨時表,能夠選擇MEMORY存儲引擎。
參考資料:
MyIASM和Innodb兩種引擎所使用的索引的數據結構是什麼?
答案:都是B+樹!
MyIASM引擎,B+樹的數據結構中存儲的內容其實是實際數據的地址值。也就是說它的索引和實際數據是分開的,只不過使用索引指向了實際數據。這種索引的模式被稱爲非彙集索引。
Innodb引擎的索引的數據結構也是B+樹,只不過數據結構中存儲的都是實際的數據,這種索引有被稱爲彙集索引。
varchar和char的區別
Char是一種固定長度的類型,varchar是一種可變長度的類型
mysql有關權限的表都有哪幾個
MySQL服務器經過權限表來控制用戶對數據庫的訪問,權限表存放在mysql數據庫裏,由mysql_install_db腳本初始化。這些權限表分別user,db,table_priv,columns_priv和host。下面分別介紹一下這些表的結構和內容:
數據表損壞的修復方式有哪些?
使用 myisamchk 來修復,具體步驟:
使用repair table 或者 OPTIMIZE table命令來修復,REPAIR TABLE table_name 修復表 OPTIMIZE TABLE table_name 優化表 REPAIR TABLE 用於修復被破壞的表。
OPTIMIZE TABLE 用於回收閒置的數據庫空間,當表上的數據行被刪除時,所佔據的磁盤空間並無當即被回收,使用了OPTIMIZE TABLE命令後這些空間將被回收,而且對磁盤上的數據行進行重排(注意:是磁盤上,而非數據庫)
MySQL中InnoDB引擎的行鎖是經過加在什麼上完成
InnoDB是基於索引來完成行鎖
例: select * from tab_with_index where id = 1 for update
;
for update
能夠根據條件來完成行鎖鎖定,而且 id 是有索引鍵的列,
若是 id 不是索引鍵那麼InnoDB將完成表鎖,,併發將無從談起
在咱們書寫SQL語句的時候,其實書寫的順序、策略會影響到SQL的性能,雖然實現的功能是同樣的,可是它們的性能會有些許差異。
所以,下面就講解在書寫SQL的時候,怎麼寫比較好。
數據庫的解析器按照從右到左的順序處理FROM子句中的表名,FROM子句中寫在最後的表將被最早處理
在FROM子句中包含多個表的狀況下:
若是有3個以上的錶鏈接查詢:
例如:查詢員工的編號,姓名,工資,工資等級,部門名
emp表被引用得最多,記錄數也是最多,所以放在form字句的最後面
select emp.empno,emp.ename,emp.sal,salgrade.grade,dept.dname
from salgrade,dept,emp where (emp.deptno = dept.deptno) and (emp.sal between salgrade.losal and salgrade.hisal)
數據庫採用自右而左的順序解析WHERE子句,根據這個原理,表之間的鏈接必須寫在其餘WHERE條件之左,那些能夠過濾掉最大數量記錄的條件必須寫在WHERE子句的之右。
emp.sal能夠過濾多條記錄,寫在WHERE字句的最右邊
select emp.empno,emp.ename,emp.sal,dept.dname
from dept,emp where (emp.deptno = dept.deptno) and (emp.sal > 1500)
咱們當時學習的時候,「*」號是能夠獲取表中所有的字段數據的。
這裏僅僅是:刪除表的所有記錄,除了表結構才這樣作。
DELETE是一條一條記錄的刪除,而Truncate是將整個表刪除,保留表結構,這樣比DELETE快
例如使用mysql的concat()函數會比使用||來進行拼接快,由於concat()函數已經被mysql優化過了。
若是表或列的名稱太長了,使用一些簡短的別名也能稍微提升一些SQL的性能。畢竟要掃描的字符長度就變少了。。。
comiit會釋放回滾點...
索引就是爲了提升咱們的查詢數據的,當表的記錄量很是大的時候,咱們就可使用索引了。
咱們在編寫SQL 的時候,官方推薦的是使用大寫來寫關鍵字,由於Oracle服務器老是先將小寫字母轉成大寫後,才執行
由於Oracle服務器遇到NOT後,他就會中止目前的工做,轉而執行全表掃描
WHERE子句中,若是索引列是函數的一部分,優化器將不使用索引而使用全表掃描,這樣會變得變慢
>=
替代 >
低效: SELECT * FROM EMP WHERE DEPTNO > 3 首先定位到DEPTNO=3的記錄而且掃描到第一個DEPT大於3的記錄 高效: SELECT * FROM EMP WHERE DEPTNO >= 4 直接跳到第一個DEPT等於4的記錄
select * from emp where sal = 1500 or sal = 3000 or sal = 800; select * from emp where sal in (1500,3000,800);
若是索引是創建在多個列上,只有在它的第一個列被WHERE子句引用時,優化器纔會選擇使用該索引。 當只引用索引的第二個列時,不引用索引的第一個列時,優化器使用了全表掃描而忽略了索引
create index emp_sal_job_idex
on emp(sal,job);
----------------------------------
select *
from emp
where job != 'SALES'; 上邊就不使用索引了。
這個麼多花錢咯!
下列練習題參考自公衆號Java知音:
基本表結構:
student(sno,sname,sage,ssex)學生表 course(cno,cname,tno) 課程表 sc(sno,cno,score) 成績表 teacher(tno,tname) 教師表
題目:
101,查詢課程1的成績比課程2的成績高的全部學生的學號 select a.sno from (select sno,score from sc where cno=1) a, (select sno,score from sc where cno=2) b where a.score>b.score and a.sno=b.sno 102,查詢平均成績大於60分的同窗的學號和平均成績 select a.sno as "學號", avg(a.score) as "平均成績" from (select sno,score from sc) a group by sno having avg(a.score)>60 103,查詢全部同窗的學號、姓名、選課數、總成績 select a.sno as 學號, b.sname as 姓名, count(a.cno) as 選課數, sum(a.score) as 總成績 from sc a, student b where a.sno = b.sno group by a.sno, b.sname 或者: selectstudent.sno as 學號, student.sname as 姓名, count(sc.cno) as 選課數, sum(score) as 總成績 from student left Outer join sc on student.sno = sc.sno group by student.sno, sname 104,查詢姓「張」的老師的個數 selectcount(distinct(tname)) from teacher where tname like '張%‘ 或者: select tname as "姓名", count(distinct(tname)) as "人數" from teacher where tname like'張%' group by tname 105,查詢沒學過「張三」老師課的同窗的學號、姓名 爲何有sc表進行關聯由於要select sc.sno 讓學號不在這裏就表明沒學過 select student.sno,student.sname from student where sno not in (select distinct(sc.sno) from sc,course,teacher where sc.cno=course.cno and teacher.tno=course.tno and teacher.tname='張三') 106,查詢同時學過課程1和課程2的同窗的學號、姓名 select sno, sname from student where sno in (select sno from sc where sc.cno = 1) and sno in (select sno from sc where sc.cno = 2) 或者: selectc.sno, c.sname from (select sno from sc where sc.cno = 1) a, (select sno from sc where sc.cno = 2) b, student c where a.sno = b.sno and a.sno = c.sno 或者: select student.sno,student.sname from student,sc where student.sno=sc.sno and sc.cno=1 and exists( select * from sc as sc_2 where sc_2.sno=sc.sno and sc_2.cno=2) 107,查詢學過「李四」老師所教全部課程的全部同窗的學號、姓名 select a.sno, a.sname from student a, sc b where a.sno = b.sno and b.cno in (select c.cno from course c, teacher d where c.tno = d.tno and d.tname = '李四') 或者: select a.sno, a.sname from student a, sc b, (select c.cno from course c, teacher d where c.tno = d.tno and d.tname = '李四') e where a.sno = b.sno and b.cno = e.cno 108,查詢課程編號1的成績比課程編號2的成績高的全部同窗的學號、姓名 select a.sno, a.sname from student a, (select sno, score from sc where cno = 1) b, (select sno, score from sc where cno = 2) c where b.score > c.score and b.sno = c.sno and a.sno = b.sno 109,查詢全部課程成績小於60分的同窗的學號、姓名 select sno,sname from student where sno not in (select distinct sno from sc where score > 60) 110,查詢至少有一門課程與學號爲1的同窗所學課程相同的同窗的學號和姓名 select distinct a.sno, a.sname from student a, sc b where a.sno <> 1 and a.sno=b.sno and b.cno in (select cno from sc where sno = 1) 或者: select s.sno,s.sname from student s, (select sc.sno from sc where sc.cno in (select sc1.cno from sc sc1 where sc1.sno=1)and sc.sno<>1 group by sc.sno)r1 where r1.sno=s.sno 1十一、把「sc」表中「王五」所教課的成績都更改成此課程的平均成績 update sc set score = (select avg(sc_2.score) from sc sc_2 wheresc_2.cno=sc.cno) from course,teacher where course.cno=sc.cno and course.tno=teacher.tno andteacher.tname='王五' 1十二、查詢和編號爲2的同窗學習的課程徹底相同的其餘同窗學號和姓名 這一題分兩步查: 1, select sno from sc where sno <> 2 group by sno having sum(cno) = (select sum(cno) from sc where sno = 2) 2, select b.sno, b.sname from sc a, student b where b.sno <> 2 and a.sno = b.sno group by b.sno, b.sname having sum(cno) = (select sum(cno) from sc where sno = 2) 11三、刪除學習「王五」老師課的sc表記錄 delete sc from course, teacher where course.cno = sc.cno and course.tno = teacher.tno and tname = '王五' 11四、向sc表中插入一些記錄,這些記錄要求符合如下條件: 將沒有課程3成績同窗的該成績補齊, 其成績取全部學生的課程2的平均成績 insert sc select sno, 3, (select avg(score) from sc where cno = 2) from student where sno not in (select sno from sc where cno = 3) 11五、按平平均分從高到低顯示全部學生的以下統計報表: -- 學號,企業管理,馬克思,UML,數據庫,物理,課程數,平均分 select sno as 學號 ,max(case when cno = 1 then score end) AS 企業管理 ,max(case when cno = 2 then score end) AS 馬克思 ,max(case when cno = 3 then score end) AS UML ,max(case when cno = 4 then score end) AS 數據庫 ,max(case when cno = 5 then score end) AS 物理 ,count(cno) AS 課程數 ,avg(score) AS 平均分 FROM sc GROUP by sno ORDER by avg(score) DESC 11六、查詢各科成績最高分和最低分: 以以下形式顯示:課程號,最高分,最低分 select cno as 課程號, max(score) as 最高分, min(score) 最低分 from sc group by cno select course.cno as '課程號' ,MAX(score) as '最高分' ,MIN(score) as '最低分' from sc,course where sc.cno=course.cno group by course.cno 11七、按各科平均成績從低到高和及格率的百分數從高到低順序 SELECT t.cno AS 課程號, max(course.cname)AS 課程名, isnull(AVG(score),0) AS 平均成績, 100 * SUM(CASE WHEN isnull(score,0)>=60 THEN 1 ELSE 0 END)/count(1) AS 及格率 FROM sc t, course where t.cno = course.cno GROUP BY t.cno ORDER BY 及格率 desc 11八、查詢以下課程平均成績和及格率的百分數(用"1行"顯示): 企業管理(001),馬克思(002),UML (003),數據庫(004) select avg(case when cno = 1 then score end) as 平均分1, avg(case when cno = 2 then score end) as 平均分2, avg(case when cno = 3 then score end) as 平均分3, avg(case when cno = 4 then score end) as 平均分4, 100 * sum(case when cno = 1 and score > 60 then 1 else 0 end) / sum(casewhen cno = 1 then 1 else 0 end) as 及格率1, 100 * sum(case when cno = 2 and score > 60 then 1 else 0 end) / sum(casewhen cno = 2 then 1 else 0 end) as 及格率2, 100 * sum(case when cno = 3 and score > 60 then 1 else 0 end) / sum(casewhen cno = 3 then 1 else 0 end) as 及格率3, 100 * sum(case when cno = 4 and score > 60 then 1 else 0 end) / sum(casewhen cno = 4 then 1 else 0 end) as 及格率4 from sc 11九、查詢不一樣老師所教不一樣課程平均分, 從高到低顯示 select max(c.tname) as 教師, max(b.cname) 課程, avg(a.score) 平均分 from sc a, course b, teacher c where a.cno = b.cno and b.tno = c.tno group by a.cno order by 平均分 desc 或者: select r.tname as '教師',r.rname as '課程' , AVG(score) as '平均分' from sc, (select t.tname,c.cno as rcso,c.cname as rname from teacher t ,course c where t.tno=c.tno)r where sc.cno=r.rcso group by sc.cno,r.tname,r.rname order by AVG(score) desc 120、查詢以下課程成績均在第3名到第6名之間的學生的成績: -- [學生ID],[學生姓名],企業管理,馬克思,UML,數據庫,平均成績 select top 6 max(a.sno) 學號, max(b.sname) 姓名, max(case when cno = 1 then score end) as 企業管理, max(case when cno = 2 then score end) as 馬克思, max(case when cno = 3 then score end) as UML, max(case when cno = 4 then score end) as 數據庫, avg(score) as 平均分 from sc a, student b where a.sno not in (select top 2 sno from sc where cno = 1 order by score desc) and a.sno not in (select top 2 sno from sc where cno = 2 order by scoredesc) and a.sno not in (select top 2 sno from sc where cno = 3 order by scoredesc) and a.sno not in (select top 2 sno from sc where cno = 4 order by scoredesc) and a.sno = b.sno group by a.sno
在Mysql中,一個用戶下能夠建立多個庫:
而在Oracle中,Oracle服務器是由兩部分組成
一個數據庫實例可擁有多個用戶,一個用戶默認擁有一個表空間。
表空間是存儲咱們數據庫表的地方,表空間內能夠有多個文件。
[圖片上傳失敗...(image-c64c66-1520388670688)]
當咱們使用Oracle做爲咱們數據庫時,咱們須要指定用戶、表空間來存儲咱們所須要的數據!
參考資料:
做者:晏子小七連接:https://www.jianshu.com/p/40ca5e8c59b7來源:簡書著做權歸做者全部。商業轉載請聯繫做者得到受權,非商業轉載請註明出處。