php面試題之五——MySQL資料庫(基礎部分)
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) | |
郵箱 | 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 語句效能如何分析?
- 儘量選擇較小的列
- 將where中用的比較頻繁的欄位建立索引
- select子句中避免使用‘*’
- 避免在索引列上使用計算、not in 和<>等操作
- 當只需要一行資料的時候使用limit 1
- 保證單表資料不超過200W,適時分割表。
針對查詢較慢的語句,可以使用explain 來分析該語句具體的執行情況。
- 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 訪問資料庫有哪幾步?
主要有以下幾個步驟:
- 連線資料庫伺服器:mysql_connect('host','user','password');
- 選擇資料庫:mysql_select_db(資料庫名);
- 設定從資料庫提取資料的字符集:mysql_query("set names utf8");
- 執行 sql 語句:mysql_query(sql 語句);
- 處理結果集
- 關閉結果集,釋放資源:mysql_free_result($result);
- 關閉與資料庫伺服器的連線: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) | |
郵箱 | 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 語句效能如何分析?
- 儘量選擇較小的列
- 將where中用的比較頻繁的欄位建立索引
- select子句中避免使用‘*’
- 避免在索引列上使用計算、not in 和<>等操作
- 當只需要一行資料的時候使用limit 1
- 保證單表資料不超過200W,適時分割表。
針對查詢較慢的語句,可以使用explain 來分析該語句具體的執行情況。
- 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 訪問資料庫有哪幾步?
主要有以下幾個步驟:
- 連線資料庫伺服器:mysql_connect('host','user','password');
- 選擇資料庫:mysql_select_db(資料庫名);
- 設定從資料庫提取資料的字符集:mysql_query("set names utf8");
- 執行 sql 語句:mysql_query(sql 語句);
- 處理結果集
- 關閉結果集,釋放資源:mysql_free_result($result);
- 關閉與資料庫伺服器的連線: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 和應用伺服器層,不利於維護和更新。
總體來說,儲存程式可以用,但要慎重,最好只用來維護,不用於業務邏輯和支撐高併發高效能的東西。
相關文章
- PHP面試之三:MySQL資料庫PHP面試MySql資料庫
- php基礎之連線mysql資料庫和查詢資料PHPMySql資料庫
- Java面試題-基礎篇五Java面試題
- 2021-PHP面試題大全[PHP基礎]-最近在面試PHP面試題
- 面試問題記錄 一 (基礎部分)面試
- JAVA開發面試題&基礎篇&第五部分Java面試題
- JAVA面試二(資料庫部分)Java面試資料庫
- 面試題之:java基礎1面試題Java
- MySQL資料庫面試題(2020最新版)MySql資料庫面試題
- MySQL與PHP的基礎與應用專題之資料查詢SRBFMySqlPHP
- JAVA面試:mysql資料庫Java面試MySql資料庫
- Android面試之Java基礎筆試題Android面試Java筆試
- MySQL資料庫注入基礎MySql資料庫
- 資料庫面試題資料庫面試題
- 妥妥的去面試之Android基礎(五)面試Android
- MySQL資料庫基礎筆記MySql資料庫筆記
- Mysql資料庫基礎操作命令MySql資料庫
- MySQL資料庫基礎詳解MySql資料庫
- 2021稍微有點水平的PHP基礎面試題PHP面試題
- MySQL資料庫之mysql5.7基礎 檢視一個資料庫中的所有表MySql資料庫
- 資料庫篇-mysql詳解( 一 )之基礎應用資料庫MySql
- 程式設計師找工作必備 PHP 基礎面試題 - 第五天程式設計師PHP面試題
- 《面試心經》---MySQL基礎面試MySql
- 2021-PHP面試題“資料庫“相關知識點面試大全總結PHP面試題資料庫
- PHP基礎之與MySQL那些事PHPMySql
- 基礎面試題 — 資料結構與演算法面試題資料結構演算法
- mysql資料庫的基礎架構MySql資料庫架構
- java基礎面試題Java面試題
- 資料庫面試題總結資料庫面試題
- Java_資料庫面試題Java資料庫面試題
- 2020PHP面試題大全【物件導向部分】PHP面試題物件
- Java面試題總結之Java基礎(三)Java面試題
- vue面試題(vue2響應式資料基礎)Vue面試題
- PHP操作MySQL資料庫PHPMySql資料庫
- 軟體測試之資料庫系列五資料庫
- 2018年--阿里大資料面試題(部分精選)阿里大資料面試題
- 面試之道之 CSS 基礎面試CSS
- 五道Python基礎語法面試題!Python入門Python面試題
- 程式設計師面試之MySQL資料庫表的設計程式設計師面試MySql資料庫