1. 程式人生 > >Java面試題2018---資料庫

Java面試題2018---資料庫

一、運算子


a.算數運算子

+: 
insert into sums values(12,13,age+height);//age和height型別是int。 
select 1+3;

-: 
insert into sums values(12,13,age-height);//age和height型別是int。

*: 
insert into sums values(12,13,age*height);//age和height型別是int。

/,div: 
insert into sums values(12,13,age div height);//age和height型別是int,第三個欄位被插入了0。

%,mod: 
insert into sums values(12,13,age%height);//第三欄位被插入0,12%13=12;

b.比較運算子: 
<>、!=:不等於
select 1<>2;//顯示1,代表true 
select 1<>1;//顯示0,代表false

<=>:NULL安全的等於 
select null<=>null;//顯示1 
<:   <=:  

select 1<2,1<=2,1>2,1>=2;//顯示1,1,0,0

c.邏輯運算子 
not或者!:非 
示例:select not 0;//顯示1,MySQL中,0是假,其他都是真。 
and或&&:與 
示例:select 44 && 0;//顯示0 
or或||:或 
示例:select 13 or 0;//顯示1 
xor(異或): 
示例:select 12 xor 12;//顯示0,兩個相同,為假,即0。兩個數不同,為真,即1.


二、儲存過程基本函式 


字串函式

select LOWER('RGFRG')--大寫字母變為小寫字母
select UPPER('ggfgrt')--小寫字母變為大寫字母
select LTRIM()--去掉左側字元空格
select RTRIM()--去掉字串右側空格
select LEFT(Title,5)from News--從某列中左側起擷取多少長度的字串
select RIGHT(Title,5)from News--從某列中右側起擷取多上長度的字串
select SUBSTRING(Title,3,5) from News--從某一列中第幾個字元開始擷取幾個字元
select REVERSE (Title) from News --翻轉某一列
select CHARINDEX('中國',Title)from News --查詢目標內容在指定區域有沒有出現以及出現位置
select REPLACE(Title,'中國','美國')from News--替換字串。例搜尋關鍵字並明顯標註
select STUFF(Title,3,4,'chine')from News
select LEN('chine')--取字串長度

數值函式

select CEILING ( COUNT(*)/5.0) from News--取大於結果的最小整數
select floor ( COUNT(*)/5.0) from News--取小於結果的最大整數
select SQRT(2)--數值開平方
select ROUND(3.45645,2)
select abs(-5):絕對值函式,取此數的絕對值,可以應用於資料庫中一些比較亂的值的加減操作。
select CEILING (RAND()*10)--隨機生成-1之間的數字,可以以乘以的方式增大隨機數範圍

日期和時間函式

 ps:對於日期,無論插入更新還是使用where子句進行過濾,日期格式必須為yyyy-mm-dd,而且應始終使用4位數字的年份。一般來說應用程式不適用用來儲存日期和時間的格式,因此日期和時間函式總是被用來讀取、統計和處理這些值

select GETDATE()--獲取當前時間
select YEAR(sbirthday)from student--取時間年份
select month(sbirthday)from student--取日期時間月份
select day(sbirthday)from student3--取時間天
select datepart(yy,sbirthday)from student4-- yy,mm,dd分別代表年月日
select CAST ('123'as int)--轉換字串
例子1:select column1, column2 from table where date(table_date) between '2013-05-20' and '2014-5-20';

      其中between操作符用來把2013-05-20和2014-05-20定義為一個要匹配的日期範圍

例子2:select column1, column2 from table where year(table-date) = 2013 and month(table_date) = 5;

      year()是一個日期(從日期時間)中返回年份的函式,month()從日期中返回月份;

      因此,where year(table-date) = 2013 and month(table_date) = 9檢索出table_date為2013年5月的所有行! 

三、查詢條件


去重:union、union all、distinct

UNION 的語法如下:

  •      [SQL 語句 1]
  •       UNION
  •      [SQL 語句 2]

例:select name from A

       union

       select name(或其他欄位) from B

結果:會將兩個select語句的內容組合在一起,注意,如果有重複的語句會進行過濾;只要select語句中欄位的個數相同就不會報錯,和欄位名稱資訊沒關係

UNION ALL 的語法如下:
     [SQL 語句 1]
      UNION ALL
     [SQL 語句 2]

例:select name from A

       union all

       select name(或其他欄位) from B

結果:會將兩個select語句的內容組合在一起,注意,不會過濾重複的資料,都顯示出來;只要select語句中欄位的個數相同就不會報錯,和欄位名稱資訊沒關係;

效率:
UNION和UNION ALL關鍵字都是將兩個結果集合併為一個,但這兩者從使用和效率上來說都有所不同。
1、對重複結果的處理:UNION在進行錶鏈接後會篩選掉重複的記錄,Union All不會去除重複記錄。
2、對排序的處理:Union將會按照欄位的順序進行排序;UNION ALL只是簡單的將兩個結果合併後就返回。
從效率上說,UNION ALL 要比UNION快很多,所以,如果可以確認合併的兩個結果集中不包含重複資料且不需要排序時的話,那麼就使用UNION ALL。
簡要回答:
UNION去重且排序
UNION ALL不去重不排序
此處有參考部落格:https://www.cnblogs.com/areyouready/p/7827779.html

distinct

SELECT DISTINCT company FROM Orders   :查詢company欄位並去重

SELECT DISTINCT company,name FROM Orders  :查詢company,name欄位並去重,這倆欄位都相同才會去重

SELECT count(DISTINCT company) FROM Orders  :統計去重後查出的個數

SELECT count(DISTINCT company,name) FROM Orders   :統計去重後查出的個數,mysql中支援多引數查詢

注意:

distinct必須放在所有欄位開頭


子查詢select

子查詢分為如下幾類: 

  • 標量子查詢:返回單一值的標量,最簡單的形式。 
  • 列子查詢:返回的結果集是 N 行一列。 
  • 行子查詢:返回的結果集是一行 N 列。 
  • 表子查詢:返回的結果集是 N 行 N 列。

1. 標量子查詢:

是指子查詢返回的是單一值的標量,如一個數字或一個字串,也是子查詢中最簡單的返回形式。 可以使用 = > < >= <= <> 這些操作符對子查詢的標量結果進行比較,通常子查詢的位置在比較式的右側

示例:

SELECT * FROM article WHERE uid = (SELECT uid FROM user WHERE status=1 ORDER BY uid DESC LIMIT 1)
SELECT * FROM t1 WHERE column1 = (SELECT MAX(column2) FROM t2)
SELECT * FROM article AS t WHERE 2 = (SELECT COUNT(*) FROM article WHERE article.uid = t.uid)

2. MySQL 列子查詢:

指子查詢返回的結果集是 N 行一列,該結果通常來自對錶的某個欄位查詢返回。 
可以使用 IN、ANY、SOME 和 ALL 操作符,不能直接使用 = > < >= <= <> 這些比較標量結果的操作符。 
示例:

SELECT * FROM article WHERE uid IN(SELECT uid FROM user WHERE status=1)

3. MySQL 行子查詢:

指子查詢返回的結果集是一行 N 列,該子查詢的結果通常是對錶的某行資料進行查詢而返回的結果集。 
例子:

SELECT * FROM table1 WHERE (1,2) = (SELECT column1, column2 FROM table2)
注:(1,2) 等同於 row(1,2)
SELECT * FROM article WHERE (title,content,uid) = (SELECT title,content,uid FROM blog WHERE bid=2)

4. MySQL 表子查詢:

指子查詢返回的結果集是 N 行 N 列的一個表資料。 
例子:

SELECT * FROM article WHERE (title,content,uid) IN (SELECT title,content,uid FROM blog)

子查詢優化:

很多查詢中需要使用子查詢。使用子查詢可以一次性的完成很多邏輯上需要多個步驟才能完成的SQL操作,同時也可以避免事務或者表鎖死。子查詢可以使查詢語 句很靈活,但子查詢的執行效率不高。

子查詢時,MySQL需要為內層查詢語句的查詢結果建立一個臨時表。然後外層查詢語句再臨時表中查詢記錄。查詢完畢 後,MySQL需要撤銷這些臨時表。因此,子查詢的速度會受到一定的影響。如果查詢的資料量比較大,這種影響就會隨之增大。

在MySQL中可以使用連線查 詢來替代子查詢。連線查詢不需要建立臨時表,其速度比子查詢要快。

使用連線(JOIN)來代替子查詢:

例子:

SELECT * FROM article WHERE (title,content,uid) IN (SELECT title,content,uid FROM blog)

優化後:

SELECT * FROM article

inner join blog 

on (article.title=blog.title AND article.content=blog.content AND article.uid=blog.uid)

參考部落格:https://www.cnblogs.com/zhuiluoyu/p/5822481.html


is null / is not null

**查詢某個欄位的值是否為NULL

mysql> select * from tmp ;
+------+----------+
| id   | name     |
+------+----------+
|    2 | lisi          |
|    1 | zhangsan |
|    3 | NULL     |
+------+----------+
3 rows in set (0.00 sec)

mysql> select * from tmp where name is null;
+------+------+
| id   | name |
+------+------+
|    3 | NULL |
+------+------+
1 row in set (0.00 sec)

mysql> select * from tmp where name is not null;
+------+------------+
| id   | name       |
+------+------------+
|    2 | lisi            |
|    1 | zhangsan |
+------+------------+
2 rows in set (0.00 sec)


limit

limit是mysql的語法, limit子句可以用於強制select語句返回制定的記錄數,limit接受一個或兩個數字的引數,如果給定兩個引數第一個指定返回記錄行的偏移量,第二個指定返回記錄行的最大數目。

1、select * from table limit m,n
     其中m是指記錄開始的index,從0開始,表示第一條記錄
     n是指從第m+1條開始,取n條。

/*即取出第3條至第6條,4條記錄*/
SELECT * FROM YourTableName LIMIT 2,4;

2、select * from table limit n  相當於select * from table limit 0, n

/*當沒有指定位置偏移量時預設偏移量為0,即從第一條開始取4條;
limit 4相當於limit 0,4*/
SELECT * FROM YourTableName LIMIT 4;

應用場合:分頁

// 後臺計算出頁碼、頁數(頁大小)
 int curPage = 2;
 int pageSize = 10;
 int startRow = (curPage - 1) * pageSize;

SELECT * FROM YourTableName LIMIT startRow,pageSize;

表連線 join

有兩個表:

內連線:

select * from A join B on A.name = B.name

相當於:select * from A, B where A.name = B.name

外連線:

select * from A left join B on A.name = B.name

select * from A right join B on A.name = B.name

select * from A full join B on A.name = B.name


分組聚集(group by)

  • 聚集函式:平均值(avg)、最小值(min)、最大值(max)、總和(sum)、計數(count)。
  • select中的屬性必須寫在group by 中或聚集函式中

select dept_name,avg(salary) as avg_salary from instructor2 group by dept_name having avg(salary)>3000

having與where的區別:

  • where 子句的作用是在對查詢結果進行分組前,將不符合where條件的行去掉,即在分組之前過濾資料,where條件中不能包含聚組函式,使用where條件過濾出特定的行。

having 子句的作用是篩選滿足條件的組,即在分組之後過濾資料,條件中經常包含聚組函式,使用having 條件過濾出特定的組,也可以使用多個分組標準進行分組。


between⋯and⋯

select * from instructor2 where 屬性名 between ... and ... ;


in和 not in

  • in:測試元組是否是集合的成員
  • not in:測試元組是否不是集合的成員
  • in和 not in 操作符用於列舉集合

select * from instructor2 where name not in('ai','ye','er');

如果有子查詢:

select * from instructor2 where name in (select name from instructor2 where salary>3000 );

則,相當於兩層for迴圈:


空關係測試(exists)

EXISTS是一個非常牛叉的謂詞,它允許資料庫高效地檢查指定查詢是否產生某些行。根據子查詢是否返回行,該謂詞返回TRUE或FALSE。與其 它謂詞和邏輯表示式不同的是,無論輸入子查詢是否返回行,EXISTS都不會返回UNKNOWN,對於EXISTS來說,UNKNOWN就是FALSE。 

select course_id
from section as S
where semester='Fall' and year=2009 and exists(select *
                 from section as T
                 where semester='Spring' and year=2010
                 and S.course_id=T.course_id
                );

in和exists的區別:

關於IN和EXISTS的主要區別在於三值邏輯的判斷上。EXISTS總是返回TRUE或FALSE,而對於IN,除了TRUE、FALSE值外, 還有可能對NULL值返回UNKNOWN。但是在過濾器中,UNKNOWN的處理方式與FALSE相同,因此使用IN與使用EXISTS一樣,SQL優化 器會選擇相同的執行計劃。

not in 和 not exists的區別:

說到了IN和EXISTS幾乎是一樣的,但是,就不得不說到NOT IN和NOT EXISTS,對於輸入列表中包含NULL值時,NOT EXISTS和NOT IN之間的差異就表現的非常大了。輸入列表包含NULL值時,IN總是返回TRUE和UNKNOWN,因此NOT IN就會得到NOT TRUE和NOT UNKNOWN,即FALSE和UNKNOWN。


case when...then..else..end(條件判斷)

select date, sum(case when result = "win" then 1 else 0 end) as "win", sum(case when result = "lose" then 1 else 0 end) as "lose" from info group by date; 


字串運算(like)

  • 百分號(%):匹配任意子串
  • 下劃線(_):匹配任意一個字元

select * from instructor2 where salary like '%0_.%';

結果:

匹配的結果如:   122202.222   32309.323   32301.432


顯示次序(order by)

  • 預設升序:asc
  • 降序:desc

select * from instructor2 order by salary desc;


什麼是儲存過程?為什麼儲存過程要比單純的Sql 語句執行起來要快?

儲存過程:是一組預先編譯好的T-SQL程式碼 在建立儲存過程時經過了語法和效能優化,執行不必重複的步驟,使用儲存過程可提高執行效率

MySQL儲存過程的引數用在儲存過程的定義,共有三種引數型別,IN,OUT,INOUT,形式如: 
CREATE PROCEDURE([[IN |OUT |INOUT ] 引數名 資料型別…]) 
IN 輸入引數:表示該引數的值必須在呼叫儲存過程時指定,在儲存過程中修改該引數的值不能被返回,為預設值 
OUT 輸出引數:該值可在儲存過程內部被改變,並可返回 
INOUT 輸入輸出引數:呼叫時指定,並且可被改變和返回

DELIMITER $$
DROP PROCEDURE IF EXISTS `prc_test1`;

CREATE DEFINER = `root`@`localhost` PROCEDURE `prc_test1`(in parameter int,out name varchar(50))
BEGIN
     select name from test where id= parameter
END$$

DELIMITER ;

呼叫:

call prc_test1(1,@school);
select @school as school

引數說明

DELIMITER $$

作用,將MySQL的結束符設定為$$,因為,MySQL預設的語句結束符號為分號;,為了避免與儲存過程中,SQL語句結束符相沖突,需要使用DELIMTER改變儲存過程的結束符,並且,以END $$結束儲存過程

儲存過程,定義完畢之後,再使用DELIMITER,恢復預設結束符

DELIMITER,可以指定其他符號作為結束符

注意,DELIMITER與設定的結束符之間,一定要有一個空格,否則設定無效


oracle和mysql的區別

1,Oracle沒有offet,limit,在mysql中我們用它們來控制顯示的行數,最多的是分頁了。oracle要分頁的話,要換成rownum。

2,oracle建表時,沒有auto_increment,所有要想讓表的一個欄位自增,要自己新增序列,插入時,把序列的值,插入進去。

3,oracle有一個dual表,當select後沒有表時,加上的。不加會報錯的。select 1 這個在mysql不會報錯的,oracle下會。select 1 from dual這樣的話,oracle就不會報錯了。

4,對空值的判斷,name != ""這樣在mysql下不會報錯的,但是oracle下會報錯。在oracle下的要換成name is not null

5,oracle下對單引號,雙引號要求的很死,一般不準用雙引號,用了會報

ERROR at line 1:
ORA-00904: "t": invalid identifier

MySQL要求就沒有那麼嚴格了,單引號,雙引號都可以。

6,oracle有to_number,to_date這樣的轉換函式,oracle表字段是number型的,如果你$_POST得到的引數是123456,入庫的時候,你還要to_number來強制轉換一下,不然後會被當成字串來處理。而mysql卻不會。

7,group_concat這個函式,oracle是沒有的,如果要想用自已寫方法。

8,mysql的使用者許可權管理,是放到mysql自動帶的一個資料庫mysql裡面的,而oracle是使用者許可權是根著表空間走的。

9,group by,在下oracle下用group by的話,group by後面的欄位必須在select後面出現,不然會報錯的,而mysql卻不會。

10,mysql儲存引擎有好多,常用的mysiam,innodb等,而建立oracle表的時候,不要這樣的,好像只有一個儲存引擎。

11,oracle欄位無法選擇位置,alter table add column before|after,這樣會報錯的,即使你用sql*plus這樣的工具,也沒法改欄位的位置。

12,oracle的表字段型別也沒有mysql多,並且有很多不同,例如:mysql的int,float合成了oracle的number型等。

13,oracle查詢時from 表名後面 不能加上as 不然會報錯的,select t.username from test as t而在mysql下是可以的。

14,oracle中是沒有substring這個函式的,mysql有的。

參考部落格:https://www.cnblogs.com/TaoLeonis/p/7043543.html


 

資料庫索引

合適的索引,可以大大減小mysql伺服器掃描的資料量,避免記憶體排序和臨時表,提高應用程式的查詢效能。

mysql資料中有多種索引型別,primary key,unique,normal,但底層儲存的資料結構都是BTREE;有些儲存引擎還提供hash索引,全文索引。

BTREE是最常見的優化要面對的索引結構,都是基於BTREE的討論。


本篇文章參考部落格:

https://blog.csdn.net/weixin_40087851/article/details/81978347

https://www.cnblogs.com/imyalost/p/6381703.html

https://www.cnblogs.com/woniu-net/p/4770337.html