1. 程式人生 > >java面試題彙總(四)-----資料庫

java面試題彙總(四)-----資料庫

1、用兩種方式根據部門號從高到低,工資從低到高列出每個員工的資訊。

employee: eid, ename, salary, dept_id

select * from employee order by dept_id desc, salary;

2、ORACLE和MySQL的區別。

1.  Oracle是大型資料庫而Mysql是中小型資料庫,Oracle市場佔有率達40%,Mysql只有20%左右,同時Mysql是開源的而Oracle價格非常高Oracle。

2. Oracle支援大併發,大訪問量,是OLTP最好的工具。(OLTP[聯機事務處理])(OLAP[資料倉庫處理 有了基礎大資料後 根據資料分析 市場定位])。

3. 安裝所用的空間差別也是很大的,Mysql安裝完後才幾百M而Oracle有幾G左右,且使用的時候Oracle佔用特別大的記憶體空間和其他機器效能。

4.Oracle和Mysql操作上的一些區別【開發人員接觸的】

①主鍵Mysql一般使用自動增長型別,在建立表時只要指定表的主鍵為auto_increment,插入記錄時,不需要再指定該記錄的主鍵值,Mysql將自動增長;Oracle沒有自動增長型別,主鍵一般使用的序列,插入記錄時將序列號的下一個值付給該欄位即可;只是ORM框架是隻要是native主鍵生成策略即可。

②單引號的處理MYSQL裡可以用雙引號包起字串,ORACLE裡只可以用單引號包起字串。在插入和修改字串前必須做單引號的替換:把所有出現的一個單引號替換成兩個單引號。

③翻頁的SQL語句的處理MYSQL處理翻頁的SQL語句比較簡單,用LIMIT開始位置,記錄個數;ORACLE處理翻頁的SQL語句就比較繁瑣了。每個結果集只有一個ROWNUM欄位標明它的位置,並且只能用ROWNUM<100,不能用ROWNUM>80

④ 長字串的處理長字串的處理ORACLE也有它特殊的地方。INSERT和UPDATE時最大可操作的字串長度小於等於4000個單位元組,如果要插入更長的字串,請考慮欄位用CLOB型別,方法借用ORACLE裡自帶的DBMS_LOB程式包。插入修改記錄前一定要做進行非空和長度判斷,不能為空的欄位值和超出長度欄位值都應該提出警告,返回上次操作。

⑤空字元的處理MYSQL的非空欄位也有空的內容,ORACLE裡定義了非空欄位就不容許有空的內容。按MYSQL的NOT NULL來定義ORACLE表結構,導資料的時候會產生錯誤。因此導資料時要對空字元進行判斷,如果為NULL或空字元,需要把它改成一個空格的字串。

⑥字串的模糊比較MYSQL裡用 欄位名 like '%字串%',ORACLE裡也可以用 欄位名like '%字串%'但這種方法不能使用索引,速度不快。【like ‘%’開頭 無法使用索引 不使用開頭 可以使用索引】

⑦Oracle實現了ANSII SQL中大部分功能,如,事務的隔離級別、傳播特性等而Mysql在這方面還是比較的弱

1). 可以理解函式是儲存過程的一種 ,都是預編譯的 【塊語句每次執行都會編譯 儲存過程塊 一次編譯多次執行 效率更高】    Plsql塊語句        Begin        End          儲存過程塊        Create procedure prg_add()        As      Begin      End; 2). 函式可以沒有引數,但是一定需要一個返回值,儲存過程可以沒有引數,不需要返回值 3). 函式return返回值沒有返回引數模式,儲存過程通過out引數返回值,如果需要返回多個引數則建議使用儲存過程 【函式oracle在函式可以使用inout mysql不能使用out】 4). 在sql資料操縱(DML)語句中只能呼叫函式而不能呼叫儲存過程

4、Oracle匯入和匯出方式

使用oracle工具exp/imp   

使用plsql相關工具 1. 匯入/匯出的是二進位制的資料,

2.plsql匯入/匯出的是sql語句的文字檔案

5、Oracle分頁方法

Oracle中使用rownum來進行分頁,這個是效率最好的分頁方法,hibernate也是使用rownum來進行oralce分頁的select * from   ( select rownum r,a from tabName where rownum <= 20 )where r > 10

6、mysql的分頁方法

select * from content order by id desc limit 0, 10

在中小資料量的情況下,這樣的SQL足夠用了,唯一需要注意的問題就是確保使用了索引。隨著資料量的增加,頁數會越來越多,檢視後幾頁的SQL就可能類似:

select * from content order by id desc limit 10000, 10

一言以蔽之,就是越往後分頁,LIMIT語句的偏移量就會越大,速度也會明顯變慢。

此時,我們可以通過2種方式:

一,子查詢的分頁方式來提高分頁效率,飄易用的SQL語句如下:

SELECT * FROM `content` WHERE id (SELECT id FROM `content` ORDER BY id desc LIMIT ".($page-1)*$pagesize.", 1) ORDER BY id desc LIMIT $pagesize

為什麼會這樣呢?因為子查詢是在索引上完成的,而普通的查詢時在資料檔案上完成的,通常來說,索引檔案要比資料檔案小得多,所以操作起來也會更有效率。(via)通過explain SQL語句發現:子查詢使用了索引!

id select_type table type possible_keys key key_len ref rows Extra

1 PRIMARY content range PRIMARY PRIMARY 4 NULL 6264 Using where

2 SUBQUERY content index NULL PRIMARY 4 NULL 27085 Using index  

7解釋什麼是死鎖,如何解決Oracle中的死鎖? 

簡言之就是存在加了鎖而沒有解鎖,可能是使用鎖沒有提交或者回滾事務,如果是表級鎖則不能操作表,客戶端處於等在狀態,如果是行級鎖則不能操作鎖定行

解決辦法:

1). 查找出被鎖的表

select b.owner,b.object_name,a.session_id,a.locked_mode

from v$locked_object a,dba_objects b

where b.object_id = a.object_id;

select b.username,b.sid,b.serial#,logon_time

from v$locked_object a,v$session b

where a.session_id = b.sid order by b.logon_time;

2). 殺程序中的會話

alter system kill session "sid,serial#";

8、列出各個部門中工資高於本部門的平均工資的員工數和部門號,並按部門號排序

employee: eid, ename, salary, dept_id

select count(*), a.dept_id

from employee a

where

a.salary > (select avg(b.salary) from employee b where b.dept_id = '本部門')

group by a.dept_id

order by a.dept_id

create or replace procedure insert_Student (_name varchar, _age int , out_id int)

declear

       a varchar

begin

       insert into studentvalue(null,_name,_age);

       select max(stuId)into _id from student;

end;

call insert_Student('wfz',23,@id);

select @id;

mysql> create trigger update_Student BEFORE update on student FOR EACH ROW

-> select * from student;

觸發器不允許返回結果

create trigger update_StudentBEFORE update on student FOR EACH ROW

insert into  student value(null,'zxx',28);

mysql的觸發器目前不能對當前表進行操作

create trigger update_StudentBEFORE update on student FOR EACH ROW

delete from articles  where id=8;

這個例子不是很好,最好是用刪除一個使用者時,順帶刪除該使用者的所有帖子

這裡要注意使用OLD.id

觸發器用處還是很多的,比如校內網、開心網、Facebook,你發一個日誌,自動通知好友,其實就是在增加日誌時做一個後觸發,再向通知表中寫入條目。因為觸發器效率高。而UCH沒有用觸發器,效率和資料處理能力都很低。

儲存過程的實驗步驟:

mysql> delimiter |

mysql> create procedure insertArticle_Procedure (pTitle varchar(50),pBid int,out

 pId int)

    -> begin

    -> insert into article1value(null,pTitle,pBid);

    -> select max(id) into pId fromarticle1;

    -> end;

    -> |

Query OK, 0 rows affected (0.05sec)

mysql> callinsertArticle_Procedure('傳智播客',1,@pid);

    -> |

Query OK, 0 rows affected (0.00sec)

mysql> delimiter ;

mysql> select @pid;

@pid

3

1 row in set (0.00 sec)

mysql> select * fromarticle1;

id

Title

bid

1

Test

1

2

chuanzhiboke

1

3

傳智播客

1

3 rows in set (0.00 sec)

觸發器的實驗步驟:

create table board1(id intprimary key auto_increment,name varchar(50),ar

ticleCount int);

create table article1(id intprimary key auto_increment,title varchar(50)

,bid int referencesboard1(id));

delimiter |

create triggerinsertArticle_Trigger after insert on article1 for each ro

w begin

    -> update board1 setarticleCount=articleCount+1 where id= NEW.bid;

    -> end;

    -> |

delimiter ;

insert into board1 value(null,'test',0);

insert into article1value(null,'test',1);

還有,每插入一個帖子,都希望將版面表中的最後發帖時間,帖子總數字段進行同步更新,用觸發器做效率就很高。下次課設計這樣一個案例,寫觸發器時,對於最後發帖時間可能需要用declare方式宣告一個變數,或者是用NEW.posttime來生成。

10、資料庫三正規化是什麼?

第一正規化(1NF):欄位具有原子性,不可再分。所有關係型資料庫系統都滿足第一正規化。

資料庫表中的欄位都是單一屬性的,不可再分。例如,姓名欄位,其中的姓和名必須作為一個整體,無法區分哪部分是姓,哪部分是名,如果要區分出姓和名,必須設計成兩個獨立的欄位。

第二正規化(2NF):在第一正規化(1NF)的基礎上建立起來的,即滿足第二正規化(2NF)必須先滿足第一正規化(1NF)。

要求資料庫表中的每個例項或行必須可以被唯一地區分。通常需要為表加上一個列,以儲存各個例項的惟一標識。這個惟一屬性列被稱為主關鍵字或主鍵。

第二正規化(2NF)要求實體的屬性完全依賴於主關鍵字。所謂完全依賴是指不能存在僅依賴主關鍵字一部分的屬性,如果存在,那麼這個屬性和主關鍵字的這一部分應該分離出來形成一個新的實體,新實體與原實體之間是一對多的關係。為實現區分通常需要為表加上一個列,以儲存各個例項的惟一標識。簡而言之,第二正規化就是非主屬性非部分依賴於主關鍵字。

第三正規化的要求如下:

滿足第三正規化(3NF)必須先滿足第二正規化(2NF)。簡而言之,第三正規化(3NF)要求一個數據庫表中不包含已在其它表中已包含的非主關鍵字資訊。

所以第三正規化具有如下特徵:

   1,每一列只有一個值

   2,每一行都能區分。

   3,每一個表都不包含其他表已經包含的非主關鍵字資訊。

例如,帖子表中只能出現發帖人的id,而不能出現發帖人的id,還同時出現發帖人姓名,否則,只要出現同一發帖人id的所有記錄,它們中的姓名部分都必須嚴格保持一致,這就是資料冗餘。

11、說出一些資料庫優化方面的經驗?

1. 程式優化,用PrepareedStatement進行增刪改查

2. 程式優化,儘量批量處理,避免逐條處理,減小IO數

3. 查詢結果不要用*來查詢所有欄位,要明確指明結果欄位

4. 減少多表連線數,儘量少的表進行連線

5. 表連線時,儘量用主鍵進行連線或用唯一索引

6. 表的查詢多時,一定建立索引

7. 根據查詢條件,建立索引,如果查詢條件不止一個時,使用組合索引

8. 在查詢條件表示式的左側儘量不要使用函式,否則索引失效

9. 如果不得不用函式,則建立函式索引

10. 使用合適的索引,例如時間索引、雜湊索引、聚簇索引

11. 如果有like話,儘量避免%xxx%兩側都有%的條件,單側%可以使用索引,多側不可以

12. 儘量不用資料庫,使用快取

13. 可以考慮用nosql資料庫提高效率

14. SQL的條件表示式,在Oracle中,是按倒序使用索引的

15. 如果用DDL改動了資料庫表字段,需要重建索引,不然索引失效

16. SQL儘量不要有多餘的空格和換行

17.使用分散式資料庫

18. 合理建立表分割槽表空間

19.建立索引時欄位不能有null值

20.使用資料庫連線池

12、union和union all有什麼不同?

union和union all都是合併結果集

區別是:

1. union去除兩個結果集的重複記錄,union all不去除重複記錄,是兩個結果集的加和

2. union效率低,union all效率高

13.用一條SQL語句查詢出每門課都大於80分的學生姓名

name   kecheng   fenshu

張三    語文      81

張三    數學      75

李四    語文      76

李四    數學      90

王五    語文      81

王五    數學      100

王五    英語      90

答案:

A:select distinct name from score where name not in (select distinct name from score where fenshu <=80)

B:select distinct name t1 from score where 80< all (select fenshu from score where name=t1);

14.所有部門之間的比賽組合

一個叫department的表,裡面只有一個欄位name,一共有4條紀錄,分別是a,b,c,d,對應四個球對,現在四個球對進行比賽,用一條sql語句顯示所有可能的比賽組合.

select a.name, b.name

from team a, team b

where a.name > b.name

15.顯示文章標題,發帖人、最後回覆時間

文章表:article_id, title, post_user, post_date

回覆表:reply_id, article_id, reply_time, content

select

a.title, a.post_user, r.reply_time

from reply r

left join article a on a.article_id = r.article_id

where

r.reply_id =

(

   select max(re.reply_id)

   from reply re

   where

   re.article_id = r.article_id

)

16.刪除除了id號不同,其他都相同的學生冗餘資訊

學生表(student)如下:

id號  學號      姓名   課程編號 課程名稱  分數

id    sid        name  cno      cname    score

1     2005001  張三   0001     數學      69

2     2005002  李四   0001     數學      89

3     2005001  張三   0001     數學      69

A: delete from student where id not in(select min(id) from student group by sid, name, cno, cname, score)

18.求出發帖最多的人:

select max(post_count), b.post_user_id, u.name

from

(

  select count(*) as post_count, a.post_user_id

  from article a

  group by a.post_user_id

) b

left join user u on u.user_id = b.post_user_id

19、一個使用者表中有一個積分欄位,假如資料庫中有100多萬個使用者,若要在每年第一天凌晨將積分清零,你將考慮什麼,你將想什麼辦法解決?

方案一:update user set score=0;

方案二:假設上面的程式碼要執行好長時間,超出我們的容忍範圍,使用alter table:

drop columnscore;alter table user add column score int

在Oracle中,動了表結構,索引失效

方案三:使用Java程式,for迴圈,效率最差

方案四:使用儲存過程loop迴圈,效率其次差

21、註冊Jdbc驅動程式的三種方式

1. Class.forName(driver)

2. ClassLoader.loadClass(driver)

3. new XXXDriver();

22、用JDBC如何呼叫儲存過程

Class.forName("com.mysql.jdbc.Driver");

String url = "jdbc:mysql:///test";

Connection cn = DriverManager.getConnection(url, "root", "root");

String sql = "{call insert_student(?,?,?)}";

CallableStatement cstmt = cn.prepareCall(sql);

cstmt.registerOutParameter(3, Types.INTEGER);

cstmt.setString(1, "wangwu");

cstmt.setInt(2, 25);

cstmt.execute();

// get第幾個,不同的資料庫不一樣,建議不寫

System.out.println(cstmt.getString(3));

23、JDBC中的PreparedStatement相比Statement的好處

一個sql命令在資料庫執行的步驟為:語法檢查,語義分析,編譯成內部指令,快取指令,執行指令等過程。

1. PrepareStatement第一次執行某SQL時可以把最終結果快取到資料中,以後再執行同一格式的SQL時,不再進行優化,直接使用快取中的優化結果,效率比較高。

2.引數傳值,可以防止SQL注入

24、Class.forName的作用?為什麼要用?

答:按引數中指定的字串形式的類名去搜索並載入相應的類,如果該類位元組碼已經被載入過,則返回代表該位元組碼的Class例項物件,否則,按類載入器的委託機制去搜索和載入該類,如果所有的類載入器都無法載入到該類,則丟擲ClassNotFoundException。載入完這個Class位元組碼後,接著就可以使用Class位元組碼的newInstance方法去建立該類的例項物件了。

有時候,我們程式中所有使用的具體類名在設計時(即開發時)無法確定,只有程式執行時才能確定,這時候就需要使用Class.forName去動態載入該類,這個類名通常是在配置檔案中配置的,例如,spring的ioc中每次依賴注入的具體類就是這樣配置的,jdbc的驅動類名通常也是通過配置檔案來配置的,以便在產品交付使用後不用修改源程式就可以更換驅動類名。

25、大資料量下的分頁解決方法。

查詢結果集如果記錄數比較多時,伺服器記憶體和瀏覽器記憶體都可能溢位,另外,資料量太大客戶端的效能會降低,滾動條較小,操作也不方便,需要資料庫分頁查詢。

SQL Server分頁:

select top #pageSize# * from students where id not in

(select top #pageSize# * (#pageNumber#-1) id from students order by id) order by id

My SQL分頁:

select * from students order by id limit #pageSize#*(#pageNumber#-1),#pageSize#

Oracle分頁:

select * from

(

    select *, rownum rid

    from

    (

        select * from students order by postime desc

    )

    where

    rid<=#pagesize#*#pagenumber#

) as t

where t.rid>#pageSize#*(#pageNumber#-1)

27、說出資料連線池的工作機制是什麼?

J2EE伺服器啟動時會建立一定數量的池連線,並一直維持不少於此數目的池連線。客戶端程式需要連線時,池驅動程式會返回一個未使用的池連線並將其表記為忙。如果當前沒有空閒連線,池驅動程式就新建一定數量的連線,新建連線的數量有配置引數決定。當使用的池連線呼叫完成後,池驅動程式將此連線標記為空閒,其他呼叫就可以使用這個連線。

實現方式,返回的Connection是原始Connection的代理,代理Connection的close方法不是真正關連線,而是把它代理的Connection物件還回到連線池中。

28、為什麼要用 ORM? 和 JDBC有何不一樣?

ORM是物件和關係型資料庫對映,是把Java中的JavaBean物件和資料庫表進行對映,使資料庫表中的記錄和JavaBean物件一一對應,從而大大簡化原來直接使用JDBC時,手工拼寫SQL帶來的不便。

ORM通過配置檔案,使資料庫表和JavaBean類對應起來,提供簡便的操作方法,增、刪、改、查記錄,不再拼寫字串生成SQL,程式設計效率大大提高,同時減少程式出錯機率,增強資料庫的移植性,方便測試。但是原生的JDBC具有更強的靈活性,適合複雜多變的SQL應用。

常用的ORM框架有:Hibernate、MyBatis、TopLink、OJB

1. 大資料可以採用分散式資料庫和建立分割槽表(PARTITION)

2. 建立有效索引:主鍵索引、聯合索引、倒序索引、函式索引(INDEX)

3. 使用物化檢視(MATERIALIZED VIEW)

4. 使用儲存過程(PROCDUDER)

5. 讀寫分離(golden gate軟體實現)

6. 歸檔舊資料(新舊資料查詢,保證新資料的效率提高),程式做調整,舊資料和新資料查詢頁面分離

答:事務就是被繫結在一起作為一個邏輯工作單元的SQL語句分組,如果任何一個語句操作失敗那麼整個操作就被失敗,以後操作就會回滾到操作前狀態,或者是上有個節點。為了確保要麼執行,要麼不執行,就可以使用事務。要將有組語句作為事務考慮,就需要通過ACID測試,即原子性,一致性,隔離性和永續性。

  鎖:在所以的DBMS中,鎖是實現事務的關鍵,鎖可以保證事務的完整性和併發性。與現實生活中鎖一樣,它可以使某些資料的擁有者,在某段時間內不能使用某些資料或資料結構。當然鎖還分級別的。

我是這樣做的,儘可能使用約束,如check,主鍵,外來鍵,非空欄位等來約束,這樣做效率最高,也最方便。其次是使用觸發器,這種方法可以保證,無論什麼業務系統訪問資料庫都可以保證資料的完整新和一致性。最後考慮的是自寫業務邏輯,但這樣做麻煩,程式設計複雜,效率低下。

答:一般我們所說的記憶體洩漏指的是堆記憶體的洩漏。堆記憶體是程式從堆中為其分配的,大小任意的,使用完後要顯示釋放記憶體。當應用程式用關鍵字new等建立物件時,就從堆中為它分配一塊記憶體,使用完後程序呼叫free或者delete釋放該記憶體,否則就說該記憶體就不能被使用,我們就說該記憶體被洩漏了。

操作的命令:

    Sqlplus  登陸使用者

    Conn    連線資料庫

    Disconn  斷開資料庫連線

    Exit或quit退出sql*plus

    Pass     修改使用者口令

    Show user 檢視當前使用者

    List      列出sql緩衝區的內容

    Run或/   執行緩衝區中的所有內容

    Save 檔名 把緩衝區的內容儲存到sql指令碼檔案

    Get 檔名   將sql指令碼檔案中的內容載入到緩衝區

    Start或@檔名  將指定sql指令碼檔案載入到緩衝區並執行

    Edit      編輯緩衝區或sql指令碼檔案的內容

    Spool 檔名 把sql*plus中的輸入結果複製到指定檔案中

    Spool off 停止sql*plus中的輸出結果複製,並關閉檔案

    Help 命令名  檢視某個命令的詳細幫助資訊。

36, 索引的優缺點優點:   1 通過建立唯一性索引,可以保證資料庫表中每一行資料的唯一性    2 可以大大加快資料的檢索速度,這也是建立索引的最主要的原因    3  可以加速表和表之間的連線,    4  在使用分組和排序子句進行資料檢索時,同樣可以減少查詢中分組和排序的時間。   缺點:    1  降低了dml操作的速度    2  建立索引和維護索引要耗費時間,這種時間隨著資料量的增加而增加    3  索引需要佔據物理空間,建立索引會加大儲存空間

37.使用oracle偽列刪除表中重複記錄:? Delete  table t  where t.rowid!=(select  max(t1.rowid)  from  table t1 where  t1.name=t.name)