php面試題之五——MySQL資料庫(基礎部分)

suxue720發表於2017-06-22

mysql_num_rows()
mysql_affected_rows()
這兩個函式都作用於 mysql_query($query)操作的結果,mysql_num_rows() 返回結果集中行的數目。mysql_affected_rows() 取得前一次 MySQL 操作所影響的記錄行數。
mysql_num_rows()僅對 SELECT 語句有效,要取得被 INSERT,UPDATE 或者 DELETE 查詢所影響到的行的數目,用 mysql_affected_rows()。

相關題目:取得查詢結果集總數的函式是?

mysql_num_rows()

2. sql 語句應該考慮哪些安全性?(新浪網技術部)

防止 Sql 注入,對特殊字元進行轉義、過濾或者使用預編譯的 sql 語句繫結變數。
最小許可權原則,特別是不要用 root 賬戶,為不同的型別的動作或者組建使用不同的賬戶。
當 sql 執行出錯時,不要把資料庫返回的錯誤資訊全部顯示給使用者,以防止洩露伺服器和資料庫相關資訊。

3. 簡單描述 mysql 中,索引,主鍵,唯一索引,聯合索引的區別,對資料庫的效能有什麼影響(從讀寫兩方面)(新浪網技術部)

索引是一種特殊的檔案(InnoDB 資料表上的索引是表空間的一個組成部分),它們包含對資料表裡所有記錄的引用指標。
普通索引(由關鍵字 KEY 或 INDEX 定義的索引)的唯一任務是加快對資料的訪問速度
普通索引允許被索引的資料列包含重複的值。如果能確定某個資料列將只包含彼此各不相同的值,在為這個資料列建立索引的時候就應該用關鍵字 UNIQUE 把它定義為一個唯一索引
也就是說,唯一索引可以保證資料記錄的唯一性

主鍵,是一種特殊的唯一索引,在一張表中只能定義一個主鍵索引,主鍵用於唯一標識一條記錄,使用關鍵字 PRIMARY KEY 來建立。
索引可以覆蓋多個資料列,如像 INDEX(columnA, columnB)索引,這就是聯合索引
索引可以極大的提高資料的查詢速度,但是會降低插入、刪除、更新表的速度,因為在執行這些寫操作時,還要操作索引檔案。

4. 有一個留言板,用 mysql 做資料庫,使用者資訊包括:使用者名稱,密碼,email,留言內容包括:留言 ID,標題,內容,發表時間,狀態(稽核,未稽核)(新浪網技術部)

請實現下列需求:
(1).資料庫結構。無需寫建表語句,用類似下面的表格,描述清楚即可,注意,要在索引欄中註明是否需要建立索引,以及要建立的索引的型別

表名 table_aaa
欄位名 欄位說明 欄位型別 索引
name 姓名 varchar(64) 唯一索引
gender 性別 enum(‘M’,‘F’)

(2).用一個 sql 語句查詢出發表留言數量大於 10 條的使用者名稱及其留言數量,查詢結果按文章數量降序排列

參考答案:
使用者表結構如下:

表名 user
欄位名 欄位說明 欄位型別 索引
user_id 使用者編號 int unsigned 主鍵
name 使用者名稱 varchar(30)  
password 密碼 char(32)  
email 郵箱 varchar(50)  

留言表結構如下:

表名 message
欄位名 欄位說明 欄位型別 索引
message_id 留言編號 int unsigned 主鍵
title 標題 varchr(100)  
content 內容 text  
user_id 使用者 id int unsigned 普通索引
pubtime 發表時間 int unsigned  
state 狀態 tinyint 0 未稽核 1 稽核  

查詢語句如下:
SELECT u.name, COUNT(*) AS total
FROM user AS u INNER JOIN message AS m
ON u.user_id = m.user_id
GROUP BY u.name
HAVING total > 10
ORDER BY total DESC

5. 如何用命令把 mysql 裡的資料備份出來(酷訊 PHP 工程師筆試題)

(1). 匯出一張表
mysqldump -u 使用者名稱 -p 密碼 庫名 表名 > 檔名(如 D:/a.sql)
(2). 匯出多張表
mysqldump -u 使用者名稱 -p 密碼 庫名 表名 1 表名 2 表名 3 > 檔名(如 D:/a.sql)
(3). 匯出所有表
mysqldump -u 使用者名稱 -p 密碼 庫名 > 檔名(如 D:/a.sql)
(4). 匯出一個庫
mysqldump -u 使用者名稱 -p 密碼 -B 庫名 > 檔名(如 D:/a.sql)

6. 兩張表 city 表和 province 表。分別為城市與省份的關係表。

city:

id city provinceid
1 廣州 1
2 深圳 1
3 惠州 1
4 長沙 2
5 武漢 3

province:

id province
1 廣東
2 湖南
3 湖北

(1). 寫一條 sql 語句關係兩個表,實現:顯示城市的基本資訊。
顯示欄位:城市 id ,城市名, 所屬省份 。如:
id(城市 id) cityname(城市名) privence(所屬省份)
……
SELECT c.id AS id,c.city AS cityname,p.province
FROM city c LEFT JOIN province p ON c.provinceid=p.id

(2). 如果要統計每個省份有多少個城市,請用 group by 查詢出來。
顯示欄位:省份 id ,省份名,包含多少個城市。
SELECT p.id,p.province,count(c.id) AS num
FROM province p LEFT JOIN city c ON p.id = c.provinceid
GROUP BY p.id;

7. MySQL 資料庫中的欄位型別 varchar 和 char 的主要區別是什麼?哪種欄位的查詢效率要高,為什麼?
  • 區別一,定長和變長
    char 表示定長,長度固定,varchar表示變長,即長度可變。當所插入的字串超出它們的長度時,視情況來處理,如果是嚴格模式,則會拒絕插入並提示錯誤資訊,如果是寬鬆模式,則會擷取然後插入。如果插入的字串長度小於定義長度時,則會以不同的方式來處理,如char(10),表示儲存的是10個字元,無論你插入的是多少,都是10個,如果少於10個,則用空格填滿。而varchar(10),小於10個的話,則插入多少個字元就存多少個。
    varchar怎麼知道所儲存字串的長度呢?實際上,對於varchar欄位來說,需要使用一個(如果字串長度小於255)或兩個位元組(長度大於255)來儲存字串的長度。

  • 區別之二,儲存的容量不同
    對 char 來說,最多能存放的字元個數 255,和編碼無關。
    而 varchar 呢,最多能存放 65532 個字元。VARCHAR 的最大有效長度由最大行大小和使用的字符集確定。整體最大長度是 65,532位元組

最大有效長度是 65532 位元組,在 varchar 存字串的時候,第一個位元組是空的,不存任何的資料,然後還需要兩個位元組來存放字串的長度。所以有效長度就是 65535 - 1 - 2= 65532

由字符集來確定,字符集分單位元組和多位元組
Latin1 一個字元佔一個位元組,最多能存放 65532 個字元
GBK 一個字元佔兩個位元組, 最多能存 32766 個字元
UTF8 一個字元佔三個位元組, 最多能存 21844 個字元
注意,char 和 varchar 後面的長度表示的是字元的個數,而不是位元組數。

兩相比較,char 的效率高,沒有碎片,尤其更新比較頻繁的時候,方便資料檔案指標的操作。但不夠靈活,在實際使用時,應根據實際需求來選用合適的資料型別。

相關題目:若一個表定義為 create table t1(c int, c2 char(30), c3 varchar(N)) charset=utf8; 問N 的最大值又是多少?

(65535 - 1 - 2 - 4 - 30 * 3 )/3

8. IP 該如何儲存?

最簡單的辦法是使用字串(varchar)來儲存,如果從效率考慮的話,可以將 ip 儲存為整型(unsigned int),使用 PHP mysql 提供的函式將 ip 轉換為整型,然後儲存即可。
php 函式:long2ip()和 ip2long()
MySQL 函式:inet_aton()和 inet_ntop

9. 設有成績表如下所示,試查詢兩門及兩門以上不及格同學的平均分。
編號 姓名 科目 分數
1 張三 數學 90
2 張三 語文 50
3 張三 地理 40
4 李四 語文 55
5 李四 政治 45
6 王五 政治 30

#建立一個成績表
CREATE TABLE grade(
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(10) NOT NULL,
subject VARCHAR(10) NOT NULL,
score TINYINT UNSIGNED NOT NULL
);

#插入記錄
INSERT INTO grade(name,subject,score) VALUES('張三','數學',90);
INSERT INTO grade(name,subject,score) VALUES('張三','語文',50);
INSERT INTO grade(name,subject,score) VALUES('張三','地理',40);
INSERT INTO grade(name,subject,score) VALUES('李四','語文',55);
INSERT INTO grade(name,subject,score) VALUES('李四','政治',45);
INSERT INTO grade(name,subject,score) VALUES('王五','政治',30);

#查詢語句
SELECT name,AVG(score),SUM(score<60) AS gk
FROM grade
GROUP BY name
HAVING gk>=2;

10. 為了記錄足球比賽的結果,設計表如下:

team:參賽隊伍表

欄位名稱 型別 描述
teamID int 主鍵
teamname varchar(20) 隊伍名稱

match:賽程表

欄位名稱 型別 描述
matchID int 主鍵
hostTeamID int 主隊的 ID
gusetTeamID int 客隊的 ID
marchResult varchar(20) 比賽結果
matchTime date 比賽日期

其中,match 賽程表中的 hostTeamID 與 guestTeamID 都和 team 表中的 teamID 關聯,查出2006-6-1 到 2006-7-1 之間舉行的所有比賽,並且用以下形式列出:
拜仁 2:0 不萊梅 2006-6-21

#建立參賽隊伍表
CREATE TABLE team(
teamID INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
teamName VARCHAR(30) NOT NULL
);
#向參賽隊伍表中插入記錄
INSERT INTO team(teamName) VALUES('拜仁');
INSERT INTO team(teamName) VALUES('不萊梅');
INSERT INTO team(teamName) VALUES('皇家馬德里');
INSERT INTO team(teamName) VALUES('巴塞羅那');
INSERT INTO team(teamName) VALUES('切爾西');
INSERT INTO team(teamName) VALUES('曼聯');
INSERT INTO team(teamName) VALUES('AC 米蘭');
INSERT INTO team(teamName) VALUES('國際米蘭');
#建立 match 賽程表
CREATE TABLE mat(
matchID INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEy,
hostTeamID INT UNSIGNED NOT NULL,
guestTeamID INT UNSIGNED NOT NULL,
matchResult VARCHAR(20) NOT NULL,
matchTime DATE NOT NULL
);
#向賽程表中插入幾條記錄
INSERT INTO mat(hostTeamID,guestTeamID,matchResult,matchTime)
VALUES(1,2,'3:1','2006-6-15');
INSERT INTO mat(hostTeamID,guestTeamID,matchResult,matchTime)
VALUES(3,4,'2:2','2006-6-28');
INSERT INTO mat(hostTeamID,guestTeamID,matchResult,matchTime)
VALUES(5,6,'0:2','2006-7-10');
INSERT INTO mat(hostTeamID,guestTeamID,matchResult,matchTime)
VALUES(7,8,'5:3','2006-5-30');
#查詢語句
SELECT t1.teamName,matchResult,t2.teamName,matchTime FROM mat
LEFT JOIN team AS t1
ON hostTeamID = t1.teamID
LEFT JOIN team AS t2
ON guestTeamID = t2.teamID
WHERE matchTime BETWEEN '2006-6-1' AND '2006-7-1';
11. 有如下兩張表 a 和 b,請寫出得到結果表的查詢語句

表a:

id num
a 5
b 10
c 15
d 10

表b:

id num
b 5
c 15
d 20
e 99

結果表:

id sum(num)
a 5
b 15
c 30
d 30
e 99
#建立表 a
CREATE TABLE t1_uni(
id CHAR(1),
num TINYINT
)engine=MyISAM charset=utf8;

#建立表 b
CREATE TABLE t2_uni(
id CHAR(1),
num TINYINT
)engine=MyISAM charset=utf8;

#向 a 表中插入記錄
INSERT INTO t1_uni VALUES('a',5),('b',10),('c',15),('d',10);
#向 b 表中插入記錄
INSERT INTO t2_uni VALUES('b',5),('c',15),('d',20),('e',99);
#查詢語句
SELECT id,SUM(num) FROM(
SELECT id,num FROM t1_uni
UNION ALL
SELECT id,num FROM t2_uni) AS tmp
GROUP BY id;
12. MYSQL 取得當前時間的函式是?格式化日期的函式是?

current_time()用於取得當前時間
date_format(datetime, format)用於格式化日期,如:select date_format(now(),'%Y%m%d');

13. 寫出發貼數最多的十個人名字的 SQL,利用下表:members(id,username,posts,pass,email)

SELECT members.username
FROM members
ORDER BY posts DESC
LIMIT 10;

[!!]14. 請簡述專案中優化 sql 語句執行效率的方法,從哪些方面,sql 語句效能如何分析?
  1. 儘量選擇較小的列
  2. 將where中用的比較頻繁的欄位建立索引
  3. select子句中避免使用‘*’
  4. 避免在索引列上使用計算、not in 和<>等操作
  5. 當只需要一行資料的時候使用limit 1
  6. 保證單表資料不超過200W,適時分割表。

針對查詢較慢的語句,可以使用explain 來分析該語句具體的執行情況。

  1. SQL 中 LEFT JOIN 的含義是________,如果 tbl_user 記錄了學生的姓名(name)和學號(ID),tbl_score 記錄了學生(有的學生考試以後被開除了,沒有其記錄)的學號(ID)和考試成績(score)以及考試科目(subject),要想列印出各個學生姓名及對應的的各科總成績,則可以用 SQL 語句_________。
    left join 表示左外連線,以左表為準,左表中的記錄都會出現在查詢結果中,如果對應的記錄在右表中沒有匹配的記錄,則右表的欄位值以 NULL 填充。
#建立表 tbl_user
CREATE TABLE tbl_user(
id INT NOT NULL,
name VARCHAR(50) NOT NULL,
PRIMARY KEY (id)
);

#建立表 tbl_socre
CREATE TABLE tbl_score(
id INT NOT NULL,
score DEC(6,2) NOT NULL,
subject VARCHAR(20) NOT NULL
);

#插入記錄
INSERT INTO tbl_user (id, name) VALUES (1, 'beimu');
INSERT INTO tbl_user (id, name) VALUES (2, 'aihui');
INSERT INTO tbl_score (id, score, subject) VALUES (1, 90, '語文');
INSERT INTO tbl_score (id, score, subject) VALUES (1, 80, '數學');
INSERT INTO tbl_score (id, score, subject) VALUES (2, 86, '數學');
INSERT INTO tbl_score (id, score, subject) VALUES (2, 96, '語文');
#查詢語句
SELECT a.id,SUM(b.score) AS sumscore
FROM tbl_user a LEFT JOIN tbl_score b
ON a.id=b.id
GROUP BY a.id;
16. 使用 php 寫一段簡單查詢,查出所有姓名為“張三”的內容並列印出來

表 user

name tel content date
張三 13333663366 大專畢業 2006-10-11
張三 13612312331 本科畢業 2006-10-15
張四 021-55665566 中專畢業 2006-10-15

請根據上面的題目完成程式碼:


$mysql_db=mysql_connect("local","root","pass");
mysql_select_db("DB",$mysql_db);
$result=mysql_query("select * from user where name='張三'");

while($row=mysql_fetch_array($result)){
    echo $row['name']. $row['tel']. $row['content']. $row['date'];
    echo "<br>";
}
17. 寫出 SQL 語句的格式 : 插入 ,更新 ,刪除(卓望)

表名 user

name tel content date
張三 13333663366 大專畢業 2006-10-11
張三 13612312331 本科畢業 2006-10-15
張四 021-55665566 中專畢業 2006-10-15

(a).有一新記錄(小王 13254748547 高中畢業 2007-05-06)請用 SQL 語句新增至表中
(b).請用 sql 語句把張三的時間更新成為當前系統時間
(c).請寫出刪除名為張四的全部記錄

INSERT INTO user(name,tel,content,date)VALUES('小王','13254748547','高中畢業','2007-05-06');
UPDATE user SET date = date_format(now(),'%Y-%m-%d') WHERE name = '張三'
DELETE FROM user WHERE name = '張四'
8. MySQL 自增型別(通常為表 ID 欄位)必需將其設為()

整型,並設定為 AUTO_INCREMENT

19. 資料庫中的事務是什麼?

事務(transaction)是作為一個單元的一組有序的資料庫操作。如果組中的所有操作都成功,則認為事務成功,即使只有一個操作失敗,事務也不成功。如果所有操作完成,事務則提交,其修改將作用於所有其他資料庫程式。如果一個操作失敗,則事務將回滾,該事務所有操作的影響都將取消。
ACID 四大特性,原子性、隔離性、一致性、永續性。

20. What's the difference between mysql_fetch_row() and mysql_fetch_array()? (Yahoo)

mysql_fetch_row() 從和指定的結果標識關聯的結果集中取得一行資料並作為陣列返回。每個結果的列儲存在一個陣列的單元中,偏移量從 0 開始。
mysql_fetch_array() 是 mysql_fetch_row() 的擴充套件版本。除了將資料以數字索引方式儲存在陣列中之外,還可以將資料作為關聯索引儲存,用欄位名作為鍵名。
mysql_fetch_array() 中可選的第二個引數 result_type 是一個常量,可以接受以下值:
MYSQL_ASSOC,MYSQL_NUM 和 MYSQL_BOTH。其預設值是 MYSQL_BOTH。
如 果 用 了 MYSQL_BOTH , 將 得 到 一 個 同 時 包 含 關 聯 和 數 字 索 引 的 數 組 。 用MYSQL_ASSOC 只得到關聯索引(如同 mysql_fetch_assoc() 那樣),用 MYSQL_NUM 只得到數字索引(如同 mysql_fetch_row() 那樣)。

21. 請寫出 php 連 mysql 連線中,獲取下一個自增長 id 值的方法,可以寫多個(酷訊)

方法一,使用 show table status ,然後獲取 auto_increment 的值
方法二,使用 select max(id) + 1 from table
方法三,如果是剛插入記錄,可以使用 last_insert_id() + 1 獲得

22. 從表 login 中選出 name 欄位包含 admin 的前 10 條結果所有資訊的 sql 語句 (酷訊)

SELECT * FROM login WHERE name LIKE ‘%admin%’ LIMIT 10;

23. 表中有 A B C 三列,用 SQL 語句實現:當 A 列大於 B 列時選擇 A 列,否則選擇 B 列,當B 列大於 C 列時選擇 B 列否則選擇 C 列。

使用case語句,如下:
SELECT CASE WHEN A > B THEN A ELSE B END, CASE WHEN B > C THEN B ELSE C END FROM table

24. 寫出三種以上 MySQL 資料庫儲存引擎的名稱(提示:不區分大小寫)

MyISAM、InnoDB、BDB(Berkeley DB)、Merge、Memory(Heap)、Example、Federated、Archive、CSV、Blackhole、MaxDB 等等十幾個引擎。

[!]25. 請簡述資料庫設計的正規化及應用。

一般第 3 正規化就足以,用於表結構的優化,這樣做既可以避免應用程式過於複雜同時也避免了 SQL 語句過於龐大所造成系統效率低下。
第一正規化:若關係模式 R 的每一個屬性是不可再分解的,且有主鍵,則屬於第一正規化。
第二正規化:若 R 屬於第一正規化,且所有的非主鍵屬性都完全函式依賴於主鍵屬性,則滿足第二正規化。
第三正規化:若 R 屬於第二正規化,且所有的非主鍵屬性沒有一個是傳遞函式依賴於候選主鍵屬性,則滿足第三正規化。
在實際使用中,可以根據需求適當的逆正規化。

26. 取得最新一次新增記錄(假設 id 為主鍵,並且是自增型別)所產生的 id 的函式是什麼?

mysql_insert_id();如果上一查詢沒有產生 AUTO_INCREMENT 的值,則 mysql_insert_id()返回 0。

27. php 連線 mysql 之後,如何設定 mysql 的字符集編碼為 utf8?

mysql_query(“set names utf8”);

28. php 訪問資料庫有哪幾步?

主要有以下幾個步驟:

  1. 連線資料庫伺服器:mysql_connect('host','user','password');
  2. 選擇資料庫:mysql_select_db(資料庫名);
  3. 設定從資料庫提取資料的字符集:mysql_query("set names utf8");
  4. 執行 sql 語句:mysql_query(sql 語句);
  5. 處理結果集
  6. 關閉結果集,釋放資源:mysql_free_result($result);
  7. 關閉與資料庫伺服器的連線:mysql_close($link);
29. 在平常 mysql 優化方面,最基本的也是最重要的優化是()。(奇矩互動)

查詢優化

30. 列出 mysql 資料庫常用的幾種型別 HEAP、()、()。 (奇矩互動)

MyISAM,innoDB

31. 請對於據 select * from table example where((a and b)and c or(((a and b)and(c and d)))優化的語句。(奇矩互動)

題目多了一個括號,在 where 後面,但不影響題目的意思,可以將 sql 語句優化如下:
select * from table example where a and b and c

[!!]32. 解釋 MySQL 外連線、內連線與自連線的區別 (小米)

先說什麼是交叉連線,交叉連線又叫笛卡爾積,它是指不使用任何條件,直接將一個表的所有記錄和另一個表中的所有記錄一一匹配。
內連線則是隻有條件的交叉連線,根據某個條件篩選出符合條件的記錄,不符合條件的記錄不會出現在結果集中,即內連線只連線匹配的行。
外連線其結果集中不僅包含符合連線條件的行,而且還會包括左表、右表或兩個表中的所有資料行,這三種情況依次稱之為左外連線,右外連線,和全外連線。

左外連線,也稱左連線,左表為主表,左表中的所有記錄都會出現在結果集中,對於那
些在右表中並沒有匹配的記錄,仍然要顯示,右邊對應的那些欄位值以 NULL 來填充。
右外連線,也稱右連線,右表為主表,右表中的所有記錄都會出現在結果集中。
左連線和右連線可以互換,MySQL 目前還不支援全外連線。

34. 寫出你所知道的資料庫。(億郵)

MySQL,SQL Server, Oracle,Sybase, informix, DB2 等

35. 使用者互為好友的 SNS 儲存結構怎麼設計。(億郵)

首先是有使用者表,如下:

CREATE TABLE user(
id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(30) NOT NULL DEFAULT '' COMMENT '使用者名稱',
email VARCHAR(50) NOT NULL DEFAULT '' COMMENT '郵箱',
password CHAR(32) NOT NULL DEFAULT '' COMMENT '密碼'
)engine=MyISAM charset=utf8 comment='使用者表';
``

其次是使用者間的關係,如下:

CREATE TABLE relation(
rel_id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
fuid INT UNSIGNED NOT NULL COMMENT '關注人的 id',
suid INT UNSIGNED NOT NULL COMMENT '被關注人的 id',
relation_type ENUM('S','D') NOT NULL DEFAULT 'S' COMMENT '關係,s 為關注,
d 表示為好友'
)engine=MyISAM charset=utf8 comment='使用者關係表';


###### 36. 假設現在有一個資料庫伺服器,伺服器地址為 192.168.0.110,使用者名稱為 root 密碼為password 請使用 PHP 編寫一個程式導向化的連線該資料庫的指令碼程式碼 (億郵)
`$conn = mysql_connect('192.168.0.110','root','password') or die('資料庫連線失敗');`

###### [!!!]37. 簡述在 MySQL 資料庫中 MyISAM 和 InnoDB 的區別 (億郵)
區別主要有以下幾個:
1. 構成上,MyISAM 的表在磁碟中有三個檔案組成,分別是表定義檔案( .frm)、資料檔案(.MYD)、索引檔案(.MYI),而 InnoDB 的表由表定義檔案(.frm)、表空間資料和日誌檔案組成。
1. 安全方面,MyISAM 強調的是效能,其查詢效率較高,但不支援事務和外來鍵等安全性方面的功能,而 InnoDB 支援事務和外來鍵等高階功能,查詢效率稍低。
1. 對鎖的支援,MyISAM 支援表鎖,而 InnoDB 支援行鎖。

###### 38. 現在有下面一個查詢語句 select * from tabname where id=2 and password='abc’如何判斷它是現在是最優的。(億郵)
可以使用 explain select * from tabname where id=2 and password='abc’來分析其執行情況。

###### 39. 請問如何在 Mysql 操作中如何寫入 utf8 格式資料 (億郵)
首先確保資料庫中的表是基於 utf8 編碼的,其次 php 檔案是 utf8 編碼,在執行 mysql操作之前,執行 mysql_query(‘set names utf8’)操作,對於要操作的文字如果是 utf8編碼,則可以直接操作,如果是其它編碼,則可以使用 iconv 函式將其轉化為 utf8 編碼,然後寫入。

###### 40. mysql 中 varchar 的 最 大 長 度 是 多 少 ? 用 什 麼 類 型 的 字 段 存 儲 大 文 本 ?date 和datetime 和 timestamp 什麼區別?怎麼看資料庫中有哪些 sql 正在執行? (卓望)
varchar 的最大有效長度由最大行大小和使用的字符集確定。整體最大長度是 65532 位元組。
在 varchar 存字串的時候,第一個位元組是空的,不存任何的資料,然後還需要兩個位元組來存放字串的長度。所以有效長度就是 65535 - 1 - 2 = 65532。
由字符集來確定,字符集分單位元組和多位元組,如果是單位元組,如 latin1,則最多可以存放 65532 個字元,如果是多位元組,如 GBK 則可以存放 32766 個字元,UTF8 則可以存放 21844個字元。

儲存大文字可以使用 text 型別。
date 表示日期,其範圍為 1000-01-01 ~ 9999-12-31
datetime 表示日期時間,其範圍為 1000-01-01 00:00:00 ~ 9999-12-31 23:59:59
timestamp 是 unix 時 間 戳 的 日 期 時 間 表 示 方 式 , 其 範 圍 較 小 為 1970-01-01 00:00:00~2038-01-19 03:14:07 ,timestamp 具備自動初始化和自動更新功能。

檢視資料庫中正在執行的 sql 語句可以使用日誌,也可以使用 show processlist 命令。


41. 現在有一個 mysql 資料庫表 visits 記錄使用者訪問情況,表結構如下:

visits(
id int unsigned auto_increment,
user_id int unsigned comment ‘本次訪問頁面數’,
visit_time timestamp comment‘本次訪問開始時間’,
primary key(id)
);

使用者每訪問過一次網站(從進入到離開),會增加一條記錄。記錄使用者的 ID(user_id),以及訪問的頁面總數。比如:
1,208,2,//208 這個使用者訪問 2 個頁面
2,2073,3,
3,208,1,//208 使用者訪問了 1 個頁面

(1).請寫一個 SQL 語句挑出你是累計訪問頁面數最多的 10 個使用者(user_id)和對應的訪問頁面數。
(2).請寫一個 SQL 語句,輸出累計訪問頁面數分別等於 1,2,3,4,5,6,7,8,9,10 的唯一使用者的數量,如果某個數量對應的使用者數為 0,可以不輸出。 (嘀嗒團)

從題目的描述來看,表結構貌似有些問題,user_id 應為使用者 ID,而不是訪問頁面數,增加一個欄位 pages 表示訪問頁面數。
查詢訪問頁面數最多的 10 個使用者的查詢語句如下:

SELECT user_id, sum(pages) as total
FROM visits
GROUP BY user_id
ORDER BY total DESC LIMIT 10;


輸出累計訪問頁面數分別等於 1,2,3,4,5,6,7,8,9,10 的唯一使用者的數量的查詢語句如下:

SELECT total,count(user_id)
FROM (
SELECT user_id, sum(pages) AS total
FROM visits
GROUP BY user_id) AS temp
WHERE total IN (1,2,3,4,5,6,7,8,9,10)
GROUP BY total ;
```

[!!]42. 簡述儲存過程的適用情況

當需要處理複雜的查詢和運算時,可以使用儲存過程。
從應用分層的原則,大量使用儲存過程導致業務邏輯分散在 DB 和應用伺服器層,不利於維護和更新。
總體來說,儲存程式可以用,但要慎重,最好只用來維護,不用於業務邏輯和支撐高併發高效能的東西。

mysql_num_rows()
mysql_affected_rows()
這兩個函式都作用於 mysql_query($query)操作的結果,mysql_num_rows() 返回結果集中行的數目。mysql_affected_rows() 取得前一次 MySQL 操作所影響的記錄行數。
mysql_num_rows()僅對 SELECT 語句有效,要取得被 INSERT,UPDATE 或者 DELETE 查詢所影響到的行的數目,用 mysql_affected_rows()。

相關題目:取得查詢結果集總數的函式是?

mysql_num_rows()

2. sql 語句應該考慮哪些安全性?(新浪網技術部)

防止 Sql 注入,對特殊字元進行轉義、過濾或者使用預編譯的 sql 語句繫結變數。
最小許可權原則,特別是不要用 root 賬戶,為不同的型別的動作或者組建使用不同的賬戶。
當 sql 執行出錯時,不要把資料庫返回的錯誤資訊全部顯示給使用者,以防止洩露伺服器和資料庫相關資訊。

3. 簡單描述 mysql 中,索引,主鍵,唯一索引,聯合索引的區別,對資料庫的效能有什麼影響(從讀寫兩方面)(新浪網技術部)

索引是一種特殊的檔案(InnoDB 資料表上的索引是表空間的一個組成部分),它們包含對資料表裡所有記錄的引用指標。
普通索引(由關鍵字 KEY 或 INDEX 定義的索引)的唯一任務是加快對資料的訪問速度
普通索引允許被索引的資料列包含重複的值。如果能確定某個資料列將只包含彼此各不相同的值,在為這個資料列建立索引的時候就應該用關鍵字 UNIQUE 把它定義為一個唯一索引
也就是說,唯一索引可以保證資料記錄的唯一性

主鍵,是一種特殊的唯一索引,在一張表中只能定義一個主鍵索引,主鍵用於唯一標識一條記錄,使用關鍵字 PRIMARY KEY 來建立。
索引可以覆蓋多個資料列,如像 INDEX(columnA, columnB)索引,這就是聯合索引
索引可以極大的提高資料的查詢速度,但是會降低插入、刪除、更新表的速度,因為在執行這些寫操作時,還要操作索引檔案。

4. 有一個留言板,用 mysql 做資料庫,使用者資訊包括:使用者名稱,密碼,email,留言內容包括:留言 ID,標題,內容,發表時間,狀態(稽核,未稽核)(新浪網技術部)

請實現下列需求:
(1).資料庫結構。無需寫建表語句,用類似下面的表格,描述清楚即可,注意,要在索引欄中註明是否需要建立索引,以及要建立的索引的型別

表名 table_aaa
欄位名 欄位說明 欄位型別 索引
name 姓名 varchar(64) 唯一索引
gender 性別 enum(‘M’,‘F’)

(2).用一個 sql 語句查詢出發表留言數量大於 10 條的使用者名稱及其留言數量,查詢結果按文章數量降序排列

參考答案:
使用者表結構如下:

表名 user
欄位名 欄位說明 欄位型別 索引
user_id 使用者編號 int unsigned 主鍵
name 使用者名稱 varchar(30)  
password 密碼 char(32)  
email 郵箱 varchar(50)  

留言表結構如下:

表名 message
欄位名 欄位說明 欄位型別 索引
message_id 留言編號 int unsigned 主鍵
title 標題 varchr(100)  
content 內容 text  
user_id 使用者 id int unsigned 普通索引
pubtime 發表時間 int unsigned  
state 狀態 tinyint 0 未稽核 1 稽核  

查詢語句如下:
SELECT u.name, COUNT(*) AS total
FROM user AS u INNER JOIN message AS m
ON u.user_id = m.user_id
GROUP BY u.name
HAVING total > 10
ORDER BY total DESC

5. 如何用命令把 mysql 裡的資料備份出來(酷訊 PHP 工程師筆試題)

(1). 匯出一張表
mysqldump -u 使用者名稱 -p 密碼 庫名 表名 > 檔名(如 D:/a.sql)
(2). 匯出多張表
mysqldump -u 使用者名稱 -p 密碼 庫名 表名 1 表名 2 表名 3 > 檔名(如 D:/a.sql)
(3). 匯出所有表
mysqldump -u 使用者名稱 -p 密碼 庫名 > 檔名(如 D:/a.sql)
(4). 匯出一個庫
mysqldump -u 使用者名稱 -p 密碼 -B 庫名 > 檔名(如 D:/a.sql)

6. 兩張表 city 表和 province 表。分別為城市與省份的關係表。

city:

id city provinceid
1 廣州 1
2 深圳 1
3 惠州 1
4 長沙 2
5 武漢 3

province:

id province
1 廣東
2 湖南
3 湖北

(1). 寫一條 sql 語句關係兩個表,實現:顯示城市的基本資訊。
顯示欄位:城市 id ,城市名, 所屬省份 。如:
id(城市 id) cityname(城市名) privence(所屬省份)
……
SELECT c.id AS id,c.city AS cityname,p.province
FROM city c LEFT JOIN province p ON c.provinceid=p.id

(2). 如果要統計每個省份有多少個城市,請用 group by 查詢出來。
顯示欄位:省份 id ,省份名,包含多少個城市。
SELECT p.id,p.province,count(c.id) AS num
FROM province p LEFT JOIN city c ON p.id = c.provinceid
GROUP BY p.id;

7. MySQL 資料庫中的欄位型別 varchar 和 char 的主要區別是什麼?哪種欄位的查詢效率要高,為什麼?
  • 區別一,定長和變長
    char 表示定長,長度固定,varchar表示變長,即長度可變。當所插入的字串超出它們的長度時,視情況來處理,如果是嚴格模式,則會拒絕插入並提示錯誤資訊,如果是寬鬆模式,則會擷取然後插入。如果插入的字串長度小於定義長度時,則會以不同的方式來處理,如char(10),表示儲存的是10個字元,無論你插入的是多少,都是10個,如果少於10個,則用空格填滿。而varchar(10),小於10個的話,則插入多少個字元就存多少個。
    varchar怎麼知道所儲存字串的長度呢?實際上,對於varchar欄位來說,需要使用一個(如果字串長度小於255)或兩個位元組(長度大於255)來儲存字串的長度。

  • 區別之二,儲存的容量不同
    對 char 來說,最多能存放的字元個數 255,和編碼無關。
    而 varchar 呢,最多能存放 65532 個字元。VARCHAR 的最大有效長度由最大行大小和使用的字符集確定。整體最大長度是 65,532位元組

最大有效長度是 65532 位元組,在 varchar 存字串的時候,第一個位元組是空的,不存任何的資料,然後還需要兩個位元組來存放字串的長度。所以有效長度就是 65535 - 1 - 2= 65532

由字符集來確定,字符集分單位元組和多位元組
Latin1 一個字元佔一個位元組,最多能存放 65532 個字元
GBK 一個字元佔兩個位元組, 最多能存 32766 個字元
UTF8 一個字元佔三個位元組, 最多能存 21844 個字元
注意,char 和 varchar 後面的長度表示的是字元的個數,而不是位元組數。

兩相比較,char 的效率高,沒有碎片,尤其更新比較頻繁的時候,方便資料檔案指標的操作。但不夠靈活,在實際使用時,應根據實際需求來選用合適的資料型別。

相關題目:若一個表定義為 create table t1(c int, c2 char(30), c3 varchar(N)) charset=utf8; 問N 的最大值又是多少?

(65535 - 1 - 2 - 4 - 30 * 3 )/3

8. IP 該如何儲存?

最簡單的辦法是使用字串(varchar)來儲存,如果從效率考慮的話,可以將 ip 儲存為整型(unsigned int),使用 php 或 mysql 提供的函式將 ip 轉換為整型,然後儲存即可。
PHP 函式:long2ip()和 ip2long()
MySQL 函式:inet_aton()和 inet_ntop

9. 設有成績表如下所示,試查詢兩門及兩門以上不及格同學的平均分。
編號 姓名 科目 分數
1 張三 數學 90
2 張三 語文 50
3 張三 地理 40
4 李四 語文 55
5 李四 政治 45
6 王五 政治 30

#建立一個成績表
CREATE TABLE grade(
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(10) NOT NULL,
subject VARCHAR(10) NOT NULL,
score TINYINT UNSIGNED NOT NULL
);

#插入記錄
INSERT INTO grade(name,subject,score) VALUES('張三','數學',90);
INSERT INTO grade(name,subject,score) VALUES('張三','語文',50);
INSERT INTO grade(name,subject,score) VALUES('張三','地理',40);
INSERT INTO grade(name,subject,score) VALUES('李四','語文',55);
INSERT INTO grade(name,subject,score) VALUES('李四','政治',45);
INSERT INTO grade(name,subject,score) VALUES('王五','政治',30);

#查詢語句
SELECT name,AVG(score),SUM(score<60) AS gk
FROM grade
GROUP BY name
HAVING gk>=2;

10. 為了記錄足球比賽的結果,設計表如下:

team:參賽隊伍表

欄位名稱 型別 描述
teamID int 主鍵
teamname varchar(20) 隊伍名稱

match:賽程表

欄位名稱 型別 描述
matchID int 主鍵
hostTeamID int 主隊的 ID
gusetTeamID int 客隊的 ID
marchResult varchar(20) 比賽結果
matchTime date 比賽日期

其中,match 賽程表中的 hostTeamID 與 guestTeamID 都和 team 表中的 teamID 關聯,查出2006-6-1 到 2006-7-1 之間舉行的所有比賽,並且用以下形式列出:
拜仁 2:0 不萊梅 2006-6-21

#建立參賽隊伍表
CREATE TABLE team(
teamID INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
teamName VARCHAR(30) NOT NULL
);
#向參賽隊伍表中插入記錄
INSERT INTO team(teamName) VALUES('拜仁');
INSERT INTO team(teamName) VALUES('不萊梅');
INSERT INTO team(teamName) VALUES('皇家馬德里');
INSERT INTO team(teamName) VALUES('巴塞羅那');
INSERT INTO team(teamName) VALUES('切爾西');
INSERT INTO team(teamName) VALUES('曼聯');
INSERT INTO team(teamName) VALUES('AC 米蘭');
INSERT INTO team(teamName) VALUES('國際米蘭');
#建立 match 賽程表
CREATE TABLE mat(
matchID INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEy,
hostTeamID INT UNSIGNED NOT NULL,
guestTeamID INT UNSIGNED NOT NULL,
matchResult VARCHAR(20) NOT NULL,
matchTime DATE NOT NULL
);
#向賽程表中插入幾條記錄
INSERT INTO mat(hostTeamID,guestTeamID,matchResult,matchTime)
VALUES(1,2,'3:1','2006-6-15');
INSERT INTO mat(hostTeamID,guestTeamID,matchResult,matchTime)
VALUES(3,4,'2:2','2006-6-28');
INSERT INTO mat(hostTeamID,guestTeamID,matchResult,matchTime)
VALUES(5,6,'0:2','2006-7-10');
INSERT INTO mat(hostTeamID,guestTeamID,matchResult,matchTime)
VALUES(7,8,'5:3','2006-5-30');
#查詢語句
SELECT t1.teamName,matchResult,t2.teamName,matchTime FROM mat
LEFT JOIN team AS t1
ON hostTeamID = t1.teamID
LEFT JOIN team AS t2
ON guestTeamID = t2.teamID
WHERE matchTime BETWEEN '2006-6-1' AND '2006-7-1';
11. 有如下兩張表 a 和 b,請寫出得到結果表的查詢語句

表a:

id num
a 5
b 10
c 15
d 10

表b:

id num
b 5
c 15
d 20
e 99

結果表:

id sum(num)
a 5
b 15
c 30
d 30
e 99
#建立表 a
CREATE TABLE t1_uni(
id CHAR(1),
num TINYINT
)engine=MyISAM charset=utf8;

#建立表 b
CREATE TABLE t2_uni(
id CHAR(1),
num TINYINT
)engine=MyISAM charset=utf8;

#向 a 表中插入記錄
INSERT INTO t1_uni VALUES('a',5),('b',10),('c',15),('d',10);
#向 b 表中插入記錄
INSERT INTO t2_uni VALUES('b',5),('c',15),('d',20),('e',99);
#查詢語句
SELECT id,SUM(num) FROM(
SELECT id,num FROM t1_uni
UNION ALL
SELECT id,num FROM t2_uni) AS tmp
GROUP BY id;
12. MYSQL 取得當前時間的函式是?格式化日期的函式是?

current_time()用於取得當前時間
date_format(datetime, format)用於格式化日期,如:select date_format(now(),'%Y%m%d');

13. 寫出發貼數最多的十個人名字的 SQL,利用下表:members(id,username,posts,pass,email)

SELECT members.username
FROM members
ORDER BY posts DESC
LIMIT 10;

[!!]14. 請簡述專案中優化 sql 語句執行效率的方法,從哪些方面,sql 語句效能如何分析?
  1. 儘量選擇較小的列
  2. 將where中用的比較頻繁的欄位建立索引
  3. select子句中避免使用‘*’
  4. 避免在索引列上使用計算、not in 和<>等操作
  5. 當只需要一行資料的時候使用limit 1
  6. 保證單表資料不超過200W,適時分割表。

針對查詢較慢的語句,可以使用explain 來分析該語句具體的執行情況。

  1. SQL 中 LEFT JOIN 的含義是________,如果 tbl_user 記錄了學生的姓名(name)和學號(ID),tbl_score 記錄了學生(有的學生考試以後被開除了,沒有其記錄)的學號(ID)和考試成績(score)以及考試科目(subject),要想列印出各個學生姓名及對應的的各科總成績,則可以用 SQL 語句_________。
    left join 表示左外連線,以左表為準,左表中的記錄都會出現在查詢結果中,如果對應的記錄在右表中沒有匹配的記錄,則右表的欄位值以 NULL 填充。
#建立表 tbl_user
CREATE TABLE tbl_user(
id INT NOT NULL,
name VARCHAR(50) NOT NULL,
PRIMARY KEY (id)
);

#建立表 tbl_socre
CREATE TABLE tbl_score(
id INT NOT NULL,
score DEC(6,2) NOT NULL,
subject VARCHAR(20) NOT NULL
);

#插入記錄
INSERT INTO tbl_user (id, name) VALUES (1, 'beimu');
INSERT INTO tbl_user (id, name) VALUES (2, 'aihui');
INSERT INTO tbl_score (id, score, subject) VALUES (1, 90, '語文');
INSERT INTO tbl_score (id, score, subject) VALUES (1, 80, '數學');
INSERT INTO tbl_score (id, score, subject) VALUES (2, 86, '數學');
INSERT INTO tbl_score (id, score, subject) VALUES (2, 96, '語文');
#查詢語句
SELECT a.id,SUM(b.score) AS sumscore
FROM tbl_user a LEFT JOIN tbl_score b
ON a.id=b.id
GROUP BY a.id;
16. 使用 php 寫一段簡單查詢,查出所有姓名為“張三”的內容並列印出來

表 user

name tel content date
張三 13333663366 大專畢業 2006-10-11
張三 13612312331 本科畢業 2006-10-15
張四 021-55665566 中專畢業 2006-10-15

請根據上面的題目完成程式碼:


$mysql_db=mysql_connect("local","root","pass");
mysql_select_db("DB",$mysql_db);
$result=mysql_query("select * from user where name='張三'");

while($row=mysql_fetch_array($result)){
    echo $row['name']. $row['tel']. $row['content']. $row['date'];
    echo "<br>";
}
17. 寫出 SQL 語句的格式 : 插入 ,更新 ,刪除(卓望)

表名 user

name tel content date
張三 13333663366 大專畢業 2006-10-11
張三 13612312331 本科畢業 2006-10-15
張四 021-55665566 中專畢業 2006-10-15

(a).有一新記錄(小王 13254748547 高中畢業 2007-05-06)請用 SQL 語句新增至表中
(b).請用 sql 語句把張三的時間更新成為當前系統時間
(c).請寫出刪除名為張四的全部記錄

INSERT INTO user(name,tel,content,date)VALUES('小王','13254748547','高中畢業','2007-05-06');
UPDATE user SET date = date_format(now(),'%Y-%m-%d') WHERE name = '張三'
DELETE FROM user WHERE name = '張四'
8. MySQL 自增型別(通常為表 ID 欄位)必需將其設為()

整型,並設定為 AUTO_INCREMENT

19. 資料庫中的事務是什麼?

事務(transaction)是作為一個單元的一組有序的資料庫操作。如果組中的所有操作都成功,則認為事務成功,即使只有一個操作失敗,事務也不成功。如果所有操作完成,事務則提交,其修改將作用於所有其他資料庫程式。如果一個操作失敗,則事務將回滾,該事務所有操作的影響都將取消。
ACID 四大特性,原子性、隔離性、一致性、永續性。

20. What's the difference between mysql_fetch_row() and mysql_fetch_array()? (Yahoo)

mysql_fetch_row() 從和指定的結果標識關聯的結果集中取得一行資料並作為陣列返回。每個結果的列儲存在一個陣列的單元中,偏移量從 0 開始。
mysql_fetch_array() 是 mysql_fetch_row() 的擴充套件版本。除了將資料以數字索引方式儲存在陣列中之外,還可以將資料作為關聯索引儲存,用欄位名作為鍵名。
mysql_fetch_array() 中可選的第二個引數 result_type 是一個常量,可以接受以下值:
MYSQL_ASSOC,MYSQL_NUM 和 MYSQL_BOTH。其預設值是 MYSQL_BOTH。
如 果 用 了 MYSQL_BOTH , 將 得 到 一 個 同 時 包 含 關 聯 和 數 字 索 引 的 數 組 。 用MYSQL_ASSOC 只得到關聯索引(如同 mysql_fetch_assoc() 那樣),用 MYSQL_NUM 只得到數字索引(如同 mysql_fetch_row() 那樣)。

21. 請寫出 php 連 mysql 連線中,獲取下一個自增長 id 值的方法,可以寫多個(酷訊)

方法一,使用 show table status ,然後獲取 auto_increment 的值
方法二,使用 select max(id) + 1 from table
方法三,如果是剛插入記錄,可以使用 last_insert_id() + 1 獲得

22. 從表 login 中選出 name 欄位包含 admin 的前 10 條結果所有資訊的 sql 語句 (酷訊)

SELECT * FROM login WHERE name LIKE ‘%admin%’ LIMIT 10;

23. 表中有 A B C 三列,用 SQL 語句實現:當 A 列大於 B 列時選擇 A 列,否則選擇 B 列,當B 列大於 C 列時選擇 B 列否則選擇 C 列。

使用case語句,如下:
SELECT CASE WHEN A > B THEN A ELSE B END, CASE WHEN B > C THEN B ELSE C END FROM table

24. 寫出三種以上 MySQL 資料庫儲存引擎的名稱(提示:不區分大小寫)

MyISAM、InnoDB、BDB(Berkeley DB)、Merge、Memory(Heap)、Example、Federated、Archive、CSV、Blackhole、MaxDB 等等十幾個引擎。

[!]25. 請簡述資料庫設計的正規化及應用。

一般第 3 正規化就足以,用於表結構的優化,這樣做既可以避免應用程式過於複雜同時也避免了 SQL 語句過於龐大所造成系統效率低下。
第一正規化:若關係模式 R 的每一個屬性是不可再分解的,且有主鍵,則屬於第一正規化。
第二正規化:若 R 屬於第一正規化,且所有的非主鍵屬性都完全函式依賴於主鍵屬性,則滿足第二正規化。
第三正規化:若 R 屬於第二正規化,且所有的非主鍵屬性沒有一個是傳遞函式依賴於候選主鍵屬性,則滿足第三正規化。
在實際使用中,可以根據需求適當的逆正規化。

26. 取得最新一次新增記錄(假設 id 為主鍵,並且是自增型別)所產生的 id 的函式是什麼?

mysql_insert_id();如果上一查詢沒有產生 AUTO_INCREMENT 的值,則 mysql_insert_id()返回 0。

27. php 連線 mysql 之後,如何設定 mysql 的字符集編碼為 utf8?

mysql_query(“set names utf8”);

28. php 訪問資料庫有哪幾步?

主要有以下幾個步驟:

  1. 連線資料庫伺服器:mysql_connect('host','user','password');
  2. 選擇資料庫:mysql_select_db(資料庫名);
  3. 設定從資料庫提取資料的字符集:mysql_query("set names utf8");
  4. 執行 sql 語句:mysql_query(sql 語句);
  5. 處理結果集
  6. 關閉結果集,釋放資源:mysql_free_result($result);
  7. 關閉與資料庫伺服器的連線:mysql_close($link);
29. 在平常 mysql 優化方面,最基本的也是最重要的優化是()。(奇矩互動)

查詢優化

30. 列出 mysql 資料庫常用的幾種型別 HEAP、()、()。 (奇矩互動)

MyISAM,innoDB

31. 請對於據 select * from table example where((a and b)and c or(((a and b)and(c and d)))優化的語句。(奇矩互動)

題目多了一個括號,在 where 後面,但不影響題目的意思,可以將 sql 語句優化如下:
select * from table example where a and b and c

[!!]32. 解釋 MySQL 外連線、內連線與自連線的區別 (小米)

先說什麼是交叉連線,交叉連線又叫笛卡爾積,它是指不使用任何條件,直接將一個表的所有記錄和另一個表中的所有記錄一一匹配。
內連線則是隻有條件的交叉連線,根據某個條件篩選出符合條件的記錄,不符合條件的記錄不會出現在結果集中,即內連線只連線匹配的行。
外連線其結果集中不僅包含符合連線條件的行,而且還會包括左表、右表或兩個表中的所有資料行,這三種情況依次稱之為左外連線,右外連線,和全外連線。

左外連線,也稱左連線,左表為主表,左表中的所有記錄都會出現在結果集中,對於那
些在右表中並沒有匹配的記錄,仍然要顯示,右邊對應的那些欄位值以 NULL 來填充。
右外連線,也稱右連線,右表為主表,右表中的所有記錄都會出現在結果集中。
左連線和右連線可以互換,MySQL 目前還不支援全外連線。

34. 寫出你所知道的資料庫。(億郵)

MySQL,SQL Server, oracle,Sybase, informix, DB2 等

35. 使用者互為好友的 SNS 儲存結構怎麼設計。(億郵)

首先是有使用者表,如下:

CREATE TABLE user(
id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(30) NOT NULL DEFAULT '' COMMENT '使用者名稱',
email VARCHAR(50) NOT NULL DEFAULT '' COMMENT '郵箱',
password CHAR(32) NOT NULL DEFAULT '' COMMENT '密碼'
)engine=MyISAM charset=utf8 comment='使用者表';
``

其次是使用者間的關係,如下:

CREATE TABLE relation(
rel_id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
fuid INT UNSIGNED NOT NULL COMMENT '關注人的 id',
suid INT UNSIGNED NOT NULL COMMENT '被關注人的 id',
relation_type ENUM('S','D') NOT NULL DEFAULT 'S' COMMENT '關係,s 為關注,
d 表示為好友'
)engine=MyISAM charset=utf8 comment='使用者關係表';


###### 36. 假設現在有一個資料庫伺服器,伺服器地址為 192.168.0.110,使用者名稱為 root 密碼為password 請使用 PHP 編寫一個程式導向化的連線該資料庫的指令碼程式碼 (億郵)
`$conn = mysql_connect('192.168.0.110','root','password') or die('資料庫連線失敗');`

###### [!!!]37. 簡述在 MySQL 資料庫中 MyISAM 和 InnoDB 的區別 (億郵)
區別主要有以下幾個:
1. 構成上,MyISAM 的表在磁碟中有三個檔案組成,分別是表定義檔案( .frm)、資料檔案(.MYD)、索引檔案(.MYI),而 InnoDB 的表由表定義檔案(.frm)、表空間資料和日誌檔案組成。
1. 安全方面,MyISAM 強調的是效能,其查詢效率較高,但不支援事務和外來鍵等安全性方面的功能,而 InnoDB 支援事務和外來鍵等高階功能,查詢效率稍低。
1. 對鎖的支援,MyISAM 支援表鎖,而 InnoDB 支援行鎖。

###### 38. 現在有下面一個查詢語句 select * from tabname where id=2 and password='abc’如何判斷它是現在是最優的。(億郵)
可以使用 explain select * from tabname where id=2 and password='abc’來分析其執行情況。

###### 39. 請問如何在 Mysql 操作中如何寫入 utf8 格式資料 (億郵)
首先確保資料庫中的表是基於 utf8 編碼的,其次 php 檔案是 utf8 編碼,在執行 mysql操作之前,執行 mysql_query(‘set names utf8’)操作,對於要操作的文字如果是 utf8編碼,則可以直接操作,如果是其它編碼,則可以使用 iconv 函式將其轉化為 utf8 編碼,然後寫入。

###### 40. mysql 中 varchar 的 最 大 長 度 是 多 少 ? 用 什 麼 類 型 的 字 段 存 儲 大 文 本 ?date 和datetime 和 timestamp 什麼區別?怎麼看資料庫中有哪些 sql 正在執行? (卓望)
varchar 的最大有效長度由最大行大小和使用的字符集確定。整體最大長度是 65532 位元組。
在 varchar 存字串的時候,第一個位元組是空的,不存任何的資料,然後還需要兩個位元組來存放字串的長度。所以有效長度就是 65535 - 1 - 2 = 65532。
由字符集來確定,字符集分單位元組和多位元組,如果是單位元組,如 latin1,則最多可以存放 65532 個字元,如果是多位元組,如 GBK 則可以存放 32766 個字元,UTF8 則可以存放 21844個字元。

儲存大文字可以使用 text 型別。
date 表示日期,其範圍為 1000-01-01 ~ 9999-12-31
datetime 表示日期時間,其範圍為 1000-01-01 00:00:00 ~ 9999-12-31 23:59:59
timestamp 是 unix 時 間 戳 的 日 期 時 間 表 示 方 式 , 其 範 圍 較 小 為 1970-01-01 00:00:00~2038-01-19 03:14:07 ,timestamp 具備自動初始化和自動更新功能。

檢視資料庫中正在執行的 sql 語句可以使用日誌,也可以使用 show processlist 命令。


41. 現在有一個 mysql 資料庫表 visits 記錄使用者訪問情況,表結構如下:

visits(
id int unsigned auto_increment,
user_id int unsigned comment ‘本次訪問頁面數’,
visit_time timestamp comment‘本次訪問開始時間’,
primary key(id)
);

使用者每訪問過一次網站(從進入到離開),會增加一條記錄。記錄使用者的 ID(user_id),以及訪問的頁面總數。比如:
1,208,2,//208 這個使用者訪問 2 個頁面
2,2073,3,
3,208,1,//208 使用者訪問了 1 個頁面

(1).請寫一個 SQL 語句挑出你是累計訪問頁面數最多的 10 個使用者(user_id)和對應的訪問頁面數。
(2).請寫一個 SQL 語句,輸出累計訪問頁面數分別等於 1,2,3,4,5,6,7,8,9,10 的唯一使用者的數量,如果某個數量對應的使用者數為 0,可以不輸出。 (嘀嗒團)

從題目的描述來看,表結構貌似有些問題,user_id 應為使用者 ID,而不是訪問頁面數,增加一個欄位 pages 表示訪問頁面數。
查詢訪問頁面數最多的 10 個使用者的查詢語句如下:

SELECT user_id, sum(pages) as total
FROM visits
GROUP BY user_id
ORDER BY total DESC LIMIT 10;


輸出累計訪問頁面數分別等於 1,2,3,4,5,6,7,8,9,10 的唯一使用者的數量的查詢語句如下:

SELECT total,count(user_id)
FROM (
SELECT user_id, sum(pages) AS total
FROM visits
GROUP BY user_id) AS temp
WHERE total IN (1,2,3,4,5,6,7,8,9,10)
GROUP BY total ;
```

[!!]42. 簡述儲存過程的適用情況

當需要處理複雜的查詢和運算時,可以使用儲存過程。
從應用分層的原則,大量使用儲存過程導致業務邏輯分散在 DB 和應用伺服器層,不利於維護和更新。
總體來說,儲存程式可以用,但要慎重,最好只用來維護,不用於業務邏輯和支撐高併發高效能的東西。

相關文章