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()。php
mysql_num_rows()mysql
防止 Sql 注入,對特殊字符進行轉義、過濾或者使用預編譯的 sql 語句綁定變量。
最小權限原則,特別是不要用 root 帳戶,爲不一樣的類型的動做或者組建使用不一樣的帳戶。
當 sql 運行出錯時,不要把數據庫返回的錯誤信息所有顯示給用戶,以防止泄露服務器和數據庫相關信息。sql
索引是一種特殊的文件(InnoDB 數據表上的索引是表空間的一個組成部分),它們包含對數據表裏全部記錄的引用指針。
普通索引(由關鍵字 KEY 或 INDEX 定義的索引)的惟一任務是加快對數據的訪問速度。
普通索引容許被索引的數據列包含重複的值。若是能肯定某個數據列將只包含彼此各不相同的值,在爲這個數據列建立索引的時候就應該用關鍵字 UNIQUE 把它定義爲一個惟一索引。
也就是說,惟一索引能夠保證數據記錄的惟一性。數據庫
主鍵,是一種特殊的惟一索引,在一張表中只能定義一個主鍵索引,主鍵用於惟一標識一條記錄,使用關鍵字 PRIMARY KEY 來建立。
索引能夠覆蓋多個數據列,如像 INDEX(columnA, columnB)索引,這就是聯合索引。
索引能夠極大的提升數據的查詢速度,可是會下降插入、刪除、更新表的速度,由於在執行這些寫操做時,還要操做索引文件。數組
請實現下列需求:
(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函數
(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)
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;
區別一,定長和變長
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 的效率高,沒有碎片,尤爲更新比較頻繁的時候,方便數據文件指針的操做。但不夠靈活,在實際使用時,應根據實際需求來選用合適的數據類型。
(65535 - 1 - 2 - 4 - 30 * 3 )/3
最簡單的辦法是使用字符串(varchar)來保存,若是從效率考慮的話,能夠將 ip 保存爲整型(unsigned int),使用 php 或 mysql 提供的函數將 ip 轉換爲整型,而後存儲便可。
PHP 函數:long2ip()和 ip2long()
MySQL 函數:inet_aton()和 inet_ntop
編號 | 姓名 | 科目 | 分數 |
---|---|---|---|
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;
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';
表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;
current_time()用於取得當前時間
date_format(datetime, format)用於格式化日期,如:select date_format(now(),'%Y%m%d');
SELECT members.username
FROM members
ORDER BY posts DESC
LIMIT 10;
針對查詢較慢的語句,可使用explain 來分析該語句具體的執行狀況。
#建立表 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;
表 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>"; }
表名 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 = '張四'
整型,並設置爲 AUTO_INCREMENT
事務(transaction)是做爲一個單元的一組有序的數據庫操做。若是組中的全部操做都成功,則認爲事務成功,即便只有一個操做失敗,事務也不成功。若是全部操做完成,事務則提交,其修改將做用於全部其餘數據庫進程。若是一個操做失敗,則事務將回滾,該事務全部操做的影響都將取消。
ACID 四大特性,原子性、隔離性、一致性、持久性。
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() 那樣)。
方法一,使用 show table status ,而後獲取 auto_increment 的值
方法二,使用 select max(id) + 1 from table
方法三,若是是剛插入記錄,可使用 last_insert_id() + 1 得到
SELECT * FROM login WHERE name LIKE ‘%admin%’ LIMIT 10;
使用case語句,以下:
SELECT CASE WHEN A > B THEN A ELSE B END, CASE WHEN B > C THEN B ELSE C END FROM table
MyISAM、InnoDB、BDB(Berkeley DB)、Merge、Memory(Heap)、Example、Federated、Archive、CSV、Blackhole、MaxDB 等等十幾個引擎。
通常第 3 範式就足以,用於表結構的優化,這樣作既能夠避免應用程序過於複雜同時也避免了 SQL 語句過於龐大所形成系統效率低下。
第一範式:若關係模式 R 的每個屬性是不可再分解的,且有主鍵,則屬於第一範式。
第二範式:若 R 屬於第一範式,且全部的非主鍵屬性都徹底函數依賴於主鍵屬性,則知足第二範式。
第三範式:若 R 屬於第二範式,且全部的非主鍵屬性沒有一個是傳遞函數依賴於候選主鍵屬性,則知足第三範式。
在實際使用中,能夠根據需求適當的逆範式。
mysql_insert_id();若是上一查詢沒有產生 AUTO_INCREMENT 的值,則 mysql_insert_id()返回 0。
mysql_query(「set names utf8」);
主要有如下幾個步驟:
查詢優化
MyISAM,innoDB
題目多了一個括號,在 where 後面,但不影響題目的意思,能夠將 sql 語句優化以下:
select * from table example where a and b and c
先說什麼是交叉鏈接,交叉鏈接又叫笛卡爾積,它是指不使用任何條件,直接將一個表的全部記錄和另外一個表中的全部記錄一一匹配。
內鏈接則是隻有條件的交叉鏈接,根據某個條件篩選出符合條件的記錄,不符合條件的記錄不會出如今結果集中,即內鏈接只鏈接匹配的行。
而外鏈接其結果集中不只包含符合鏈接條件的行,並且還會包括左表、右表或兩個表中的全部數據行,這三種狀況依次稱之爲左外鏈接,右外鏈接,和全外鏈接。
左外鏈接,也稱左鏈接,左表爲主表,左表中的全部記錄都會出如今結果集中,對於那
些在右表中並無匹配的記錄,仍然要顯示,右邊對應的那些字段值以 NULL 來填充。
右外鏈接,也稱右鏈接,右表爲主表,右表中的全部記錄都會出如今結果集中。
左鏈接和右鏈接能夠互換,MySQL 目前還不支持全外鏈接。
MySQL,SQL Server, Oracle,Sybase, informix, DB2 等
首先是有用戶表,以下:
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 ;
```
當須要處理複雜的查詢和運算時,可使用存儲過程。 從應用分層的原則,大量使用存儲過程致使業務邏輯分散在 DB 和應用服務器層,不利於維護和更新。 整體來講,存儲程序能夠用,但要慎重,最好只用來維護,不用於業務邏輯和支撐高併發高性能的東西。