最全的MySQL基础【燕十八传世】
1.課前準備!
開啟mysql服務:1).配置環境變量;2).net start mysql
將該sql文件導入到你的數據庫中,以下所有操作都是基于該數據庫表操作的!!!
【此筆記是本人看著視頻加上自己理解一個一個字符慢慢敲的,僅供自己學習,本人已取得視頻筆記主人燕十八同意,未經允許不得轉載傳播!如違背一切法律責任本人概不負責!!】
【該筆記由于是我自己看著視頻+自己理解了一下記錄的,如理解或記錄有錯歡迎指正~感謝燕老師】
create table goods (goods_id mediumint(8) unsigned primary key auto_increment,goods_name varchar(120) not null default '',cat_id smallint(5) unsigned not null default '0',brand_id smallint(5) unsigned not null default '0',goods_sn char(15) not null default '',goods_number smallint(5) unsigned not null default '0',shop_price decimal(10,2) unsigned not null default '0.00',market_price decimal(10,2) unsigned not null default '0.00',click_count int(10) unsigned not null default '0' ) engine=myisam default charset=utf8; insert into `goods` values (1,'kd876',4,8,'ecs000000',1,1388.00,1665.60,9), (4,'諾基亞n85原裝充電器',8,1,'ecs000004',17,58.00,69.60,0), (3,'諾基亞原裝5800耳機',8,1,'ecs000002',24,68.00,81.60,3), (5,'索愛原裝m2卡讀卡器',11,7,'ecs000005',8,20.00,24.00,3), (6,'勝創kingmax內存卡',11,0,'ecs000006',15,42.00,50.40,0), (7,'諾基亞n85原裝立體聲耳機hs-82',8,1,'ecs000007',20,100.00,120.00,0), (8,'飛利浦9@9v',3,4,'ecs000008',1,399.00,478.79,10), (9,'諾基亞e66',3,1,'ecs000009',4,2298.00,2757.60,20), (10,'索愛c702c',3,7,'ecs000010',7,1328.00,1593.60,11), (11,'索愛c702c',3,7,'ecs000011',1,1300.00,0.00,0), (12,'摩托羅拉a810',3,2,'ecs000012',8,983.00,1179.60,13), (13,'諾基亞5320 xpressmusic',3,1,'ecs000013',8,1311.00,1573.20,13), (14,'諾基亞5800xm',4,1,'ecs000014',1,2625.00,3150.00,6), (15,'摩托羅拉a810',3,2,'ecs000015',3,788.00,945.60,8), (16,'恒基偉業g101',2,11,'ecs000016',0,823.33,988.00,3), (17,'夏新n7',3,5,'ecs000017',1,2300.00,2760.00,2), (18,'夏新t5',4,5,'ecs000018',1,2878.00,3453.60,0), (19,'三星sgh-f258',3,6,'ecs000019',12,858.00,1029.60,7), (20,'三星bc01',3,6,'ecs000020',12,280.00,336.00,14), (21,'金立 a30',3,10,'ecs000021',40,2000.00,2400.00,4), (22,'多普達touch hd',3,3,'ecs000022',1,5999.00,7198.80,16), (23,'諾基亞n96',5,1,'ecs000023',8,3700.00,4440.00,17), (24,'p806',3,9,'ecs000024',100,2000.00,2400.00,35), (25,'小靈通/固話50元充值卡',13,0,'ecs000025',2,48.00,57.59,0), (26,'小靈通/固話20元充值卡',13,0,'ecs000026',2,19.00,22.80,0), (27,'聯通100元充值卡',15,0,'ecs000027',2,95.00,100.00,0), (28,'聯通50元充值卡',15,0,'ecs000028',0,45.00,50.00,0), (29,'移動100元充值卡',14,0,'ecs000029',0,90.00,0.00,0), (30,'移動20元充值卡',14,0,'ecs000030',9,18.00,21.00,1), (31,'摩托羅拉e8 ',3,2,'ecs000031',1,1337.00,1604.39,5), (32,'諾基亞n85',3,1,'ecs000032',4,3010.00,3612.00,9); create table category ( cat_id smallint unsigned auto_increment primary key, cat_name varchar(90) not null default '', parent_id smallint unsigned )engine myisam charset utf8; INSERT INTO `category` VALUES (1,'手機類型',0), (2,'CDMA手機',1), (3,'GSM手機',1), (4,'3G手機',1), (5,'雙模手機',1), (6,'手機配件',0), (7,'充電器',6), (8,'耳機',6), (9,'電池',6), (11,'讀卡器和內存卡',6), (12,'充值卡',0), (13,'小靈通/固話充值卡',12), (14,'移動手機充值卡',12), (15,'聯通手機充值卡',12); CREATE TABLE `result` (`name` varchar(20) DEFAULT NULL,`subject` varchar(20) DEFAULT NULL,`score` tinyint(4) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8; insert into result values ('張三','數學',90), ('張三','語文',50), ('張三','地理',40), ('李四','語文',55), ('李四','政治',45), ('王五','政治',30); create table a ( id char(1), num int )engine myisam charset utf8; insert into a values ('a',5),('b',10),('c',15),('d',10); create table b ( id char(1), num int )engine myisam charset utf8; insert into b values ('b',5),('c',15),('d',20),('e',99); create table m(mid int,hid int,gid int,mres varchar(10),matime date )engine myisam charset utf8; create table t (tid int,tname varchar(20) )engine myisam charset utf8; insert into mvalues(1,1,2,'2:0','2006-05-21'),(2,2,3,'1:2','2006-06-21'),(3,3,1,'2:5','2006-06-25'),(4,2,1,'3:2','2006-07-21'); insert into tvalues(1,'國安'),(2,'申花'),(3,'布爾聯隊'); create table mian ( num int) engine myisam; insert into mian values (3), (12), (15), (25), (23), (29), (34), (37), (32); create table user ( uid int primary key auto_increment, name varchar(20) not null default '', age smallint unsigned not null default 0 ) engine myisam charset utf8; create table boy (hid char(1),bname varchar(20) )engine myisam charset utf8; insert into boy (bname,hid)values('屌絲','A'),('楊過','B'),('陳冠希','C'); create table girl (hid char(1),gname varchar(20))engine myisam charset utf8; insert into girl(gname,hid)values('小龍女','B'),('張柏芝','C'),('死宅女','D'); 1.數據庫查詢的重要思想:將查詢的結果集當成一張新關系二維"表" 2.數據表==>二維多列的一個表結構 注意:此處只是告訴你一些在校期間MySQL需要掌握的知識!但是如何用PHP來操作這些知識,需要不斷練習1.數據庫--客戶端
?
mysqld --服務器端==>安裝mysql之后,內存中就有這個這個服務了! mysql -- 客戶端 ==>連通服務所使用的軟件 mysql -h localhost -uroot -p ==>客戶端有很多【例如:網絡服務(服務器端)==瀏覽器(IE/Firefox)】 表==(多個表)===>數據庫===(多個數據庫)==>數據庫服務?
2.phpmyadmin允許空密碼登錄配置
==>config.sample.inc.php-->復制(config.inc.php)==>$cfg['Servers'][$i]['AllowNoPassword'] = true;
3.什么是SQL(Structured Query Language) 結構查詢語句
-----SQL語句是一種what型語言【想要什么,給你】,而非how語言【要我怎么做才能給你】--php....編程語言
4.SQL語言分類:
1)DML is Data Manipulation Languages statements .Some examples:數據庫操作語言,SQL中處理數據【使用者角度--接觸率占據80%】--相當于"員工" ?
2)DDLis Data Definition Language statements.Some example:數據定義語言,用于定義管理SQL數據庫中所有對象--建表,建庫,建視圖....等【建設的角度--接觸率15%】--相當于"總經理" ?
3)DCL is Data Control Language statements.Some example:數據控制語言,用于授予或回收訪問數據庫的某種權限,并控制數據庫操作事務發生的時間及效果,對數據庫實行監視...等【管理者角度--接觸率5%】---相當于"董事長"
5.我常用的表操作語句:
1.mysql -h localhost -uroot -p123456 -- 以root用戶連接本地數據庫2. show databases; -- 查看MySQL服務中所有的數據庫
3. use database; -- 更改操作的數據庫對象
4.\c --取消執行當前未輸入mysql語句
5. show tables; -- 查看該操作數據庫對象中所有的數據表名和視圖名
6.desc table_name/view_name;--查看表/視圖結構;
7.truncate table_name; --清空表數據【表結構依然不變】-- 和delete from table_name;是不同的
8.show create table table_name/view; --查看建表/視圖過程
9.show table status [\G]; -- 查看數據庫中所有表信息【\G:以豎行顯示信息】
10.show table status where name = table_name [\G]; -- 查看數據庫中指定表信息【\G:以豎行顯示信息】
11.rename table_name; --改表名
12.drop table table_name; --刪除表
13.drop view view_name; -- 刪除視圖
SQL語言之DML部分@數據庫操作語言【搬運數據】--"員工"
6.常用操作:增[insert] 刪[delete] 改[update] 查[select]
1.INSERT:
2.DELETE
3.UPDATE
4.★★★SELECT★★★
7.SELECT條件查詢模型深入理解【重點】
====列是"變量"=====變量就可以計算===== select uid, name, age+1 from user;--從user表中查找所有uid, name,age三列,并給age列所在值+1 ==where是"表達式"==值為真【true】假【false】== select * from user where id=5;--從user表中查找所有列,當id為5 【判斷所在行id=5?==>返回true則輸出】 select * from user where 1;--從user表中查找所有列,當條件恒真--【輸出所有】select * from user where 0;--從user表中查找所有列,當條件恒假--【返回Empty】 select 語句還可以配合算數運算符、邏輯運算符和位運算符以及相關函數寫出更高效率的查詢語句 【當然要注意運算符的優先級】 查詢的實質:對磁盤上的數據文件進行查詢得到結果集,并將結果集存放到內存中,其余就是對內存結果集的操作
?
查詢練習:
查詢出第4和第11列的信息:select goods_id, goods_name, shop_price from goods where goods_id =4 or goods_id=11;
select goods_id, goods_name, shop_price from goods where goods_id in(4,11);
查詢出第4到第11列間的信息:
select goods_id, goods_name, shop_price from goods where goods_id>4 and goods_id < 11;
select goods_id, goods_name, shop_price from goods where goods_id between 4 and 11;
模糊查詢(like)--%通配任意字符; _ 通配單一字符
取出名字以"諾基亞"開頭的商品select goods_id,cat_id,goods_name,shop_price from e cs_goods where goods_name like '諾基亞%'; 取出名字為"諾基亞Nxx"的手機
select goods_id,cat_id,goods_name,shop_price from ecs_goods where goods_name like '諾基亞N__'; 取出名字不以"諾基亞"開頭的商品 select goods_id,cat_id,goods_name,shop_price from ecs_goos where goods_name not like '諾基亞%'; 當涉及到多重條件查詢需要用到運算符,and , or ,not,...之類的來修飾條件時候:
1)一定要先弄清楚條件之間的分類
2)使用( ) 將其分類--避免因為優先級問題
一道關于查詢的面試題 有如下表和數組
把num值處于[20,29]之間,改為20:update main set num=20 where num between 20 and 29;
num值處于[30,39]之間的,改為30:mian表
+------+
| num |
+------+
| 3 |
| 12 |
| 15 |
| 25 |
| 23 |
| 29 |
| 34 |
| 37 |
| 32 |
| 45 |
| 48 |
| 52 |
+------+
floor(X):返回一個不大于X的最大整數值 update mian set num=( floor(num/10)*10 ) where num between 20 and 39;
練習題: 把good表中商品名為'諾基亞xxxx'的商品,改為'HTCxxxx',
提示:大膽的把列看成變量,參與運算,甚至調用函數來處理 .
substring(),--concat() select goods_id, concat( 'LMS', substring(goods_name,4) ,shop_price from goods where goods_name like '諾基亞%';
奇怪的NULL查詢
對于NULL=NULL==>返回假;==>NULL是什么都沒有,所以不能比較!使用is null 才能查詢select * from user where name is not null --查詢出user表中name字段不為空的信息
【對于數據表中,null不利于數據表優化操作,所以數據表中一般都對字段設置not null】
GOUP BY分組與統計函數
group by -- 當出現group by分組中不能配對的情況,該字段取查詢時候第一次出現的值統計函數:
max()--最大值;
min()--取最小值;
avg()--求平均值;
sum()--求和;
count()--計算行數/條數;
distinct()--求有多少種不同解;
?
【時間是以時間戳的形式存放的,是int型,max() --最新商品; min() -- 最舊商品】having篩選結果集
1.查詢goods表中商品比市場價低出多少?select goods_id, goods_name,(market_price-shop_price) from goods
2.查詢goods表中商品比市場價低出至少200的商品?
select goods_id, goods_name,(market_price-shop_price) from goods where (market_price - shop_price) > 200;
error:查詢goods表中商品比市場價低出至少200的商品?
select goods_id, goods_name,(market_price-shop_price) as 'min' from goods where min > 200;
報錯:不識別min這個列!
【where子句針對的對象是磁盤上的數據表文件去select的,而select出來后的數據是存放在內存中的一個零時"結果集"】 --因此:當使用where min >200 ;去篩選結果集的時候是不能識別出min字段的
having--針對的對象是內存表結構中的"結果集"
3.查詢goods表中商品比市場價低出至少200的商品?
select goods_id, goods_name,(market_price-shop_price) as '節省' from goods where 1 having '節省' >200;
【如果同時寫了where和having子句,where子句肯定要寫在having子句前面,因為having子句是針對where子句查詢出來的結果集來操作的】
?
★★★where-having-group綜合練習題
有如下表及數據+------+---------+-------+
| name | subject | score |
+------+---------+-------+
| 張三 | 數學 | 90 |
| 張三 | 語文 | 50 |
| 張三 | 地理 | 40 |
| 李四 | 語文 | 55 |
| 李四 | 政治 | 45 |
| 王五 | 政治 | 30 |
+------+---------+-------+要求:查詢出2門及2門以上不及格者的平均成績 ## 一種錯誤做法【錯在:對count和比較運算兩者結合的理解錯誤】 mysql> select name,count(score < 60) as k,avg(score) from stu group by name having k>=2; +------+---+------------+
| name | k | avg(score) |
+------+---+------------+
| 張三 | 3 | 60.0000 |
| 李四 | 2 | 50.0000 |
+------+---+------------+
2 rows in set (0.00 sec) ? mysql> select name,count(score < 60) as k,avg(score) from stu group by name; +------+---+------------+
| name | k | avg(score) |
+------+---+------------+
| 張三 | 3 | 60.0000 |
| 李四 | 2 | 50.0000 |
| 王五 | 1 | 30.0000 |
+------+---+------------+
3 rows in set (0.00 sec) ? mysql> select name,count(score < 60) as k,avg(score) from stu group by name having k>=2; +------+---+------------+
| name | k | avg(score) |
+------+---+------------+
| 張三 | 3 | 60.0000 |
| 李四 | 2 | 50.0000 |
+------+---+------------+
2 rows in set (0.00 sec) ? #加上趙六后錯誤暴露
mysql> insert into stu -> values -> ('趙六','A',100), -> ('趙六','B',99), -> ('趙六','C',98);
Query OK, 3 rows affected (0.05 sec)Records: 3 Duplicates: 0 Warnings: 0 ? #錯誤顯現 mysql> select name,count(score < 60) as k,avg(score) from stu group by name having k>=2; +------+---+------------+
| name | k | avg(score) |
+------+---+------------+
| 張三 | 3 | 60.0000 |
| 李四 | 2 | 50.0000 |
| 趙六 | 3 | 99.0000 |
+------+---+------------+
3 rows in set (0.00 sec) #正確思路,先查看每個人的平均成績 mysql> select name,avg(score) from stu group by name;
+------+------------+
| name | avg(score) |
+------+------------+
| 張三 | 60.0000 |
| 李四 | 50.0000 |
| 王五 | 30.0000 |
| 趙六 | 99.0000 |
+------+------------+
4 rows in set (0.00 sec)mysql> # 1.看每個人掛科情況
mysql> select name,score < 60 from stu;
+------+------------+
| name | score < 60 |
+------+------------+
| 張三 | 0 |
| 張三 | 1 |
| 張三 | 1 |
| 李四 | 1 |
| 李四 | 1 |
| 王五 | 1 |
| 趙六 | 0 |
| 趙六 | 0 |
| 趙六 | 0 |
+------+------------+
9 rows in set (0.00 sec)
mysql> select name,sum(score < 60) from stu group by name; #2.計算每個人的掛科科目
+------+-----------------+
| name | sum(score < 60) |
+------+-----------------+
| 張三 | 2 |
| 李四 | 2 |
| 王五 | 1 |
| 趙六 | 0 |
+------+-----------------+
4 rows in set (0.00 sec)
mysql> select name,sum(score < 60),avg(score) as pj from stu group by name;#3.同時計算每人的平均分
+------+-----------------+---------+
| name | sum(score < 60) | pj |
+------+-----------------+---------+
| 張三 | 2 | 60.0000 |
| 李四 | 2 | 50.0000 |
| 王五 | 1 | 30.0000 |
| 趙六 | 0 | 99.0000 |
+------+-----------------+---------+
4 rows in set (0.00 sec) mysql> select name,sum(score < 60) as gk ,avg(score) as pj from stu group by name having gk >=2;#利用having篩選掛科2門以上的. +------+------+---------+
| name | gk | pj |
+------+------+---------+
| 張三 | 2 | 60.0000 |
| 李四 | 2 | 50.0000 |
+------+------+---------+
2 rows in set (0.00 sec) 錯誤原因【以下幾點】: ① score < 60 ? 比較運算 ? 返回值:真(1)、假(0)
②count() ? 返回的結果是總行數 ? count(socre)和count( score < 60 )得到結果是一樣的
③對sum()和count()函數理解的不到位?想要計算至少有2門課掛了的人,使用count()函數,結果是 ?
④sum()和score< 60 結合的理解:sum( score < 60) >=2 ==>計算出至少掛了2門課的人
order by排序查詢【在內存中排序】 與 limit范圍查詢【--經典應用:分頁類】
1:按價格由高到低排序select goods_id,goods_name,shop_price from goods order by shop_price desc;
2:按發布時間由早到晚排序
select goods_id,goods_name,add_time from goods order by add_time;
3:接欄目由低到高排序,欄目內部按價格由高到低排序【有沖突時,順序決定優先】
select goods_id,cat_id,goods_name,shop_price from goods order by cat_id ,shop_price desc;
4:取出價格最高的前三名商品
select goods_id,goods_name,shop_price from goods order by shop_price desc limit 3;
5:取出點擊量前三名到前5名的商品
select goods_id,goods_name,click_count from goods order by click_count desc limit 2,3;
子句的查詢陷阱
如何:查詢goods表中,每個欄目(cat_id) 下最新(goods_id最大)的那件商品? 錯誤示范:【正確答案見下】思路:1)最新的商品 -- max(good_id)
2)每個欄目--group by cat_id
mysql> select max(goods_id), goods_name, cat_id, shop_price from goods group by cat_id; +---------------+-----------------------+--------+------------+
| max(goods_id) | goods_name | cat_id | shop_price |
+---------------+-----------------------+--------+------------+
| 16 | 恒基偉業g101 | 2 | 823.33 |
| 32 | 飛利浦9@9v | 3 | 399.00 | 除了數據goods_id對了其他 ? | 18 | kd876 | 4 | 1388.00 |
| 23 | 諾基亞n96 | 5 | 3700.00 |
| 7 | 諾基亞n85原裝充電器 | 8 | 58.00 |
| 6 | 索愛原裝m2卡讀卡器 | 11 | 20.00 |
| 26 | 小靈通/固話50元充值卡 | 13 | 48.00 |
| 30 | 移動100元充值卡 | 14 | 90.00 |
| 28 | 聯通100元充值卡 | 15 | 95.00 |
+---------------+-----------------------+--------+------------+
這里錯在:“先查詢在排序”==>group by cat_id ,但goods_name, shop_price,我們應該取誰的呢?--解決思路:用到“子查詢”/連接查詢==>先排序再查詢子查詢 之 where子查詢[以內層查詢結果作為外層的比較條件]
1:查找出goods表中最新的那件商品信息?思考問題:1.如何保證每次更新商品后,取得都是最新的呢?? 涉及到了"變量"?"列"就是變量
2.查詢的條件可以是個表達式?但是表示得到的要是一個“明確”的量才可以查詢
3.數據庫查詢?"投影式"查詢[要那列查那列,查的那列和其他列沒關系]
--第3點典型錯誤: select max(goods_id), goods_name, shop_price from goods;--除了goods_id對,其余都是錯的!這是個有語義缺陷的語句
子語句查詢:select goods_id,goods_name,shop_price from goods where goods_id =
( select max(goods_id) from goods );
以查詢select max( goods_id ) from user;的返回結果【存放在內存中,且無論如何該結果都是一個"定值"】作為對前方查詢語句的條件 2.如何:查詢goods表中,每個欄目(cat_id) 下最新(goods_id最大)的那件商品? 思路整理:(從上面的錯誤范例已可以得到正確思路==>先"排序" 再"查詢")
1.排序==>有題目可知,排序的變量應該是cat_id字段,通過排序找到每一個cat_id下中goods_id最大的那個商品ID號
2.查詢==>用排序得到的那個最大ID號作為條件表達式的對比條件,查找出商品信息 1.先"排序:"mysql> select max(goods_id), cat_id, shop_price from goods group by cat_id;
+---------------+--------+------------+
| max(goods_id) | cat_id | shop_price |
+---------------+--------+------------+
| 16 | 2 | 823.33 |
| 32 | 3 | 399.00 |
| 18 | 4 | 1388.00 |
| 23 | 5 | 3700.00 |
| 7 | 8 | 58.00 |
| 6 | 11 | 20.00 |
| 26 | 13 | 48.00 |
| 30 | 14 | 90.00 |
| 28 | 15 | 95.00 |
+---------------+--------+------------+
9 rows in set (0.00 sec)
2.再"查詢":mysql> select good_id, goods_name, shop_price from goods where goods_id in (select max(goods_id) from goods group by cat_id); +----------+------------------------------+------------+
| goods_id | goods_name | shop_price |
+----------+------------------------------+------------+
| 6 | 勝創kingmax內存卡 | 42.00 |
| 7 | 諾基亞n85原裝立體聲耳機hs-82 | 100.00 |
| 16 | 恒基偉業g101 | 823.33 |
| 18 | 夏新t5 | 2878.00 |
| 23 | 諾基亞n96 | 3700.00 |
| 26 | 小靈通/固話20元充值卡 | 19.00 |
| 28 | 聯通50元充值卡 | 45.00 |
| 30 | 移動20元充值卡 | 18.00 |
| 32 | 諾基亞n85 | 3010.00 |
+----------+------------------------------+------------+ 2.查詢出編號為19的商品的欄目名稱[欄目名稱放在category表中](用左連接查詢和子查詢分別) WHERE型子查詢:
1.先找出外層條件的內層結果--goods表中第19號商品的cat_id:select cat_id from goods where goods_id = 19;
2.查詢:select cat_name from category where cat_id = ( select cat_id from goods where goods_id = 19 );
子查詢 之 from子查詢【將查詢出來的結果集當成一個新"表"來操作】
2.如何:查詢goods表中,每個欄目(cat_id) 下最新(goods_id最大)的那件商品?--使用from子查詢同樣的思路==>先排序再查詢
排序:mysql> select goods_id, goods_name, shop_price from order by cat_id asc, goods_id DESC;
得到一張優先按照cat_id升序,再goods_id降序的"表"-----同一個cat_id的商品,它在"表"里出現的位置是第一個
排序:mysql> select goods_id, goods_name, shop_price from order by cat_id asc, goods_id DESC;
查詢:mysql> select goods_id, goods_name,shop_price from
(select goods_id,cat_id, goods_name, shop_price from goods order by cat_id ) as tmp
group by cat_id;
子查詢 之 exists子查詢【"存在"】
1.用exists型子查詢,查出所有商品的欄目下有商品的欄目mysql> select * from category where exists (select * from goods where goods.cat_id = category.cat_id);
查找category這個表,如果select * from goods where goods.cat_id = category.cat_id這個"表"中對應的數據存在則查詢+--------+-------------------+-----------+
| cat_id | cat_name | parent_id |
+--------+-------------------+-----------+
| 2 | CDMA手機 | 1 |
| 3 | GSM手機 | 1 |
| 4 | 3G手機 | 1 |
| 5 | 雙模手機 | 1 |
| 8 | 耳機 | 6 |
| 11 | 讀卡器和內存卡 | 6 |
| 13 | 小靈通/固話充值卡 | 12 |
| 14 | 移動手機充值卡 | 12 |
| 15 | 聯通手機充值卡 | 12 |
+--------+-------------------+-----------+
9 rows in set (0.00 sec)
內連接查詢[inner join]、左連接[left join]、右連接[right join]
【MySQL中沒有外連接】 詳解:http://www.dedecms.com/knowledge/data-base/sql-server/2012/0709/2872.html內連接:select xxxx from table1 inner join table2 on table1.xx=table2.xx ? 交集
左連接:select xxxx from table1 left join table2 on table1.xx=table2.xx ? 左表為基礎的查詢
右連接:select xxxx from table1 right join table2 on table1.xx=table2.xx ? 右表為基礎的查詢 1.查詢價格大于2000元的商品及其欄目名稱
思路:
--涉及到兩個表;--基礎表為goods表,連接表為category表,條件為shop_price > 2000
--goods表cat_id中的和category表中的cat_id對應
mysql > select goods.goods_id, category.cat_name, goods.goods_name, goods.shop price from
- > goods left join category
- > on goods.cat_id = category.cat_id
- > where goods.shop_price > 2000;
2.取出第4個欄目下的商品的商品名,欄目名,與品牌名
select goods_name,cat_name,shop_price from goods left join category on goods.cat_id=category.cat_id where goods.cat_id = 4
用友面試題
根據給出的表結構按要求寫出SQL語句。Match 賽程表
| 字段名稱 | 字段類型 | 描述 |
| matchID | int | 主鍵 |
| hostTeamID | int | 主隊的ID |
| guestTeamID | int | 客隊的ID |
| matchResult | varchar(20) | 比賽結果,如(2:0) |
| matchTime | date | 比賽開始時間 |
| 字段名稱 | 字段類型 | 描述 |
| teamID | int | 主鍵 |
| teamName | varchar(20) | 隊伍名稱 |
查出 2006-6-1 到2006-7-1之間舉行的所有比賽,并且用以下形式列出:
拜仁 2:0 不來梅 2006-6-21 mysql> select * from m;
+-----+------+------+------+------------+
| mid | hid | gid | mres | matime |
+-----+------+------+------+------------+
| 1 | 1 | 2 | 2:0 | 2006-05-21 |
| 2 | 2 | 3 | 1:2 | 2006-06-21 |
| 3 | 3 | 1 | 2:5 | 2006-06-25 |
| 4 | 2 | 1 | 3:2 | 2006-07-21 |
+-----+------+------+------+------------+
4 rows in set (0.00 sec) mysql> select * from t;
+------+----------+
| tid | tname |
+------+----------+
| 1 | 國安 |
| 2 | 申花 |
| 3 | 傳智聯隊 |
+------+----------+
3 rows in set (0.00 sec) 思路:--使用Team表中tname代替Match表中對應的hid和gid,然后對時間用between做出做出范圍限制查詢
1.先代替hid:
mysql> select m.*, t.tname as htname
? ? ? ? -> from m inner join t
? ? ? ? -> on m.hid = t.tid;
+------+------+------+------+------------+----------+
| mid | hid | gid | mres | matime | htname |
+------+------+------+------+------------+----------+
| 1 | 1 | 2 | 2:0 | 2006-05-21 | 國安 |
| 2 | 2 | 3 | 1:2 | 2006-06-21 | 申花 |
| 3 | 3 | 1 | 2:5 | 2006-06-25 | 布爾聯隊|
| 4 | 2 | 1 | 3:2 | 2006-07-21 | 申花 |
+------+------+------+------+------------+----------+
2.再將查詢出來的結果集當做是一張新的表對Team表再來一次內連接查詢mysql> select m.*, t.tname as htname,t1.tname as gtname from m inner join t on m.hid = t.tid
? ? ? ? ->inner join t as t1
? ? ? ??->on m.gid=t1.tid;
+------+------+------+------+------------+----------+----------+
| mid | hid | gid | mres | matime | htname | gtname |
+------+------+------+------+------------+----------+----------+
| 1 | 1 | 2 | 2:0 | 2006-05-21 | 國安 | 申花 |
| 2 | 2 | 3 | 1:2 | 2006-06-21 | 申花 | 布爾聯隊|
| 3 | 3 | 1 | 2:5 | 2006-06-25 | 布爾聯隊 | 國安 |
| 4 | 2 | 1 | 3:2 | 2006-07-21 | 申花 | 國安 |
+------+------+------+------+------------+----------+----------+
4 rows in set (0.00 sec) ==>3.替換后結果如下:
mysql> select hid,t1.tname as hname ,mres,gid,t2.tname as gname,matime
? ? ? ??-> from
? ? ? ??-> m left join t as t1
? ? ? ??-> on m.hid = t1.tid
? ? ? ??-> left join t as t2
? ? ? ??-> on m.gid = t2.tid;
+------+----------+------+------+----------+------------+
| hid | hname | mres | gid | gname | matime |
+------+----------+------+------+----------+------------+
| 1 | 國安 | 2:0 | 2 | 申花 | 2006-05-21 |
| 2 | 申花 | 1:2 | 3 | 傳智聯隊 | 2006-06-21 |
| 3 | 傳智聯隊 | 2:5 | 1 | 國安 | 2006-06-25 |
| 2 | 申花 | 3:2 | 1 | 國安 | 2006-07-21 |
+------+----------+------+------+----------+------------+
4 rows in set (0.00 sec) ==>3.最終結果如下:
mysql> select hid,t1.tname as hname ,mres,gid,t2.tname as gname,matime
? ? ? ??-> from
? ? ? ??-> m left join t as t1
? ? ? ??-> on m.hid = t1.tid
? ? ? ??-> left join t as t2
? ? ? ??-> on m.gid = t2.tid
? ? ? ??-> where matime between "2006-06-01" and "2006-07-01"; +------+----------+------+------+----------+------------+
| hid | hname | mres | gid | gname | matime |
+------+----------+------+------+----------+------------+
| 2 | 申花 | 1:2 | 3 | 布爾聯隊 | 2006-06-21 |
| 3 | 布爾聯隊 | 2:5 | 1 | 國安 | 2006-06-25 |
+------+----------+------+------+----------+------------+
2 rows in set (0.00 sec)
union查詢:將2條或多條SQL的查詢結果合并成1個結果集
注意:1)取的兩個表投影查找的字段列數要相同,列名可不一致(默認使用第一個表的列名)否則
2)如果碰到完全相同的行,將會被合并【合并是非常耗時的?使用 union all 就不需要比較字段合并了】
3)union查詢的內部子句中不用寫order by子句,意義不大!但是可以對查詢合并后id結果集進行排列 1.同時查詢goods表中cat_id為2和4的商品 select goods_id,cat_id,goods_name from goods where cat_id =2
union
select goods_id, cat_id,goods_name from goods where cat_id = 4 (order by )
union查詢面試題
將A、B表中id值相同的兩個num值相加 A表:+------+------+
| id | num |
+------+------+
| a | 5 |
| b | 10 |
| c | 15 |
| d | 10 |
+------+------+ B表:
+------+------+
| id | num |
+------+------+
| b | 5 |
| c | 15 |
| d | 20 |
| e | 99 |
+------+------+mysql> # 合并 ,注意all的作用
mysql> select * from ta
? ? ? ??-> union all
? ? ? ??-> select * from tb;
+------+------+
| id | num |
+------+------+
| a | 5 |
| b | 10 |
| c | 15 |
| d | 10 |
| b | 5 |
| c | 15 |
| d | 20 |
| e | 99 |
+------+------+ 將上面查詢的"結果集"當做是一個新表
參考答案:
mysql> # sum,group求和
mysql> select id,sum(num)
? ? ? ? ->from
? ? ? ? ->(select * from ta union all select * from tb) as tmp
? ? ? ??->group by id;
+------+----------+
| id | sum(num) |
+------+----------+
| a | 5 |
| b | 15 |
| c | 25 |
| d | 30 |
| e | 99 |
+------+----------+
5 rows in set (0.00 sec)
SQL語言之DDL部分@數據定義語言【建庫、建表】--"總經理"
1.創建表table
1)建"表"過程 ? 申明數據庫中各個"列"的過程? creat table_name ( 列名 列類型 [列屬性 列默認值]) ENGINE = 存儲引擎 default charset=字符集;
★★★
2)設計"表"結構?對"列"的優化?"列"選什么類型?列選什么屬性最好?
2.列類型知識:
數值型:整型、浮點型、定點型 字符串:char varchar text,... 日期時間:datetime, time,一種類型,占得字節越多,存儲越大,也越浪費
2_1:整型列
bigint 8個字節int 4個字節【1個字節=8位?4個字節=32位--也就是"1"這個int型只占了32位中1個位】
mediumint 3個字節
smallint 2個字節
tinyint 1個字節 【8位==> 0-255 或 -128 - 127】 1)像tinyint中,默認數值型都是對半正負分配的==>即:正常情況下tinyint是不能存儲大于128的數字的! 那么,如何讓tinyint存儲0-255之間的數呢?
使用unsigned屬性【無符號】修飾;
zerofill==>用0填充至固定寬度【學號:1->0001;255 ->0255】
M -> 寬度 tinyint(5)-->寬度為5;varchar(10)->寬度為10
注意:①zerofill屬性就已經代表了該類型為是unsigned屬性了==>負數不需要用0填充
②M屬性只有和zerofill配合使用才有意義!寬度是指0填充的寬度,而不是指該列存儲的寬度【如:tinyint(1) 可以存儲111】
2_2.浮點列[float/doule]與定點列[decimal]
浮點列:float/double (M,D) [UNSIGNED] [ZEROFILL] -- M表示精度【總位數】,D表示小數點后面的位數如:float(3,2)--存10==>錯誤:其實這里有4位了10.00;
float(3,2)==>存9.99正確
定點列decimal[整數部分和小數部分分開來存儲的]
浮點數是有精度損失的!定點列更準確
2_3字符型列[char/varchar]
①char(M)--定長;varchar(M) -- 變長
例如:char(10) -- 放10個字符長度,但是存放1個字符,在內存中依然是占10個字符長度
--char(M) 在磁盤上就占M個字節,磁盤空間利用率可能達到100%
varchar(10) -- 放10個字符長度,但是存放1個字符,在內存中就占了1個字符長度的空格鍵
--varchar(M) 在內存表中存儲時,在表頭會增加1-2說明字節存儲該字符串長度==>那么內存尋址的時候就能準確找到每一行數據==>實際varchar占M+[1/2]字節 小技巧:一般對于M較小的,都用char! 1).因為varchar的利用率是不可能達到100%! 2).內存的定長尋址會快很多
3).char型,如果不夠M個寬度,內存存儲時候會用空格在字符右邊補齊,取出時候把右側空格刪除
如果用char存儲' hello ',取出之后' hello';用varchar存,取出時候' hello '
②text -- 大文本類型;blob -- 二進制類型
例如:論文、博客...等大段文本text圖像、音頻等二進制信息用blob類型來存儲
意義:blob是使用二進制來存儲信息的,因此不需要考慮字符集的問題!
例如0xFF這個字節,在ASCII字符集中被認為是非法的,在入庫的時候就會被過濾掉!如果使用blob來存儲則不會被過濾
?
③enum('value1','value2',...) -- 枚舉類型;set('value1','value2',...) -- 集合類型
例如:enum('男','女') ? 該列所存儲的值就只能是'男'或'女' ? 是個單選值存儲
set('value1','value2',...) ? 是個復選值存儲,但值也只能在列舉的元素中選取
注意:set()最多只能列舉64個值!
2_4日期時間型列[char/varchar]
year 年 [1個字節] 范圍:[1901-2155] ? 在insert是,可以簡寫年后面對兩位,但是這樣不推薦【00-69】+2000;【70-99】+1900 ? 填寫兩位,表示1970-2069年?不要只寫后面2個數字
Date 日期 1994-10-29
? 以'YYYY-MM-DD HH:MM:SS'格式檢索和顯示DATETIME值。支持的范圍為'1000-01-01 00:00:00'到'9999-12-31 23:59:59'
time 時間 13:02:29
? 用'YYYY-MM-DD'格式檢索和顯示DATE值。支持的范圍是'1000-01-01'到 '9999-12-31'
datetime 日期
? 以'YYYY-MM-DD HH:MM:SS'格式檢索和顯示DATETIME值。支持的范圍為'1000-01-01 00:00:00'到'9999-12-31 23:59:59'
int unsigned 時間戳 1970-01-01 00:00:00 到當前的秒數
? 一般存注冊時間,商品發布時間等,并不是用datetime,而是用時間戳存儲,因為datetime存儲雖然直觀,但不便計算
2_5 列屬性 ? 默認值[ default ]&& not null
1.NULL不便于查詢【注意:空字數串,0都不是NULL--NULL是什么都沒有,是不存在】not null default xxxx
2_6 列屬性 ? 主鍵[ primary key ] && 自增[ auto_increment ]
1.此列不重復,能夠區分每一行==>列名 primary key auto_increment一般主鍵和自增是一起使用的[int類型],不一定一要一起使用!一張表中只能有一個自增的列!
小技巧:
1.很多時候都是用tinyint存儲?性別:0/1 --> 男/女;體重:tinyint 【0-255】....
2.定長存儲尋址快,效率高--常用的字段建議定長存儲【對于一張表,只有一個變長大字段其他都是定長字段情況下,可考慮將變長單獨分出來】
3.一般mysql的列名都用小寫
2_7 列的增add/刪/改 ? 這是對表結構的修改
增:alter table 表名 add 列名 列類型 [列屬性] -- 默認該列是存放在表最后的【使用 after 列名 --放在指定列】刪:alter table 表名 drop column 列名 列類型 [列屬性]
改:alter table 表名 change 舊列名 新列名 [新列類型] [新列屬性]
改:alter table 表名 modify 列名 [新列類型] [新列屬性] --modify 不能修改列名
3. 視圖
1).什么是視圖?
view 又稱虛擬表,view其實就一條查詢SQL語句的結果集==>將常用的SQL查詢結果集虛擬為一張表存放在內存中create view as 視圖名 (查詢SQL語句結果集);--當再次使用時:select * from 視圖名
2).視圖有什么用?【視圖實際上存儲的就是SQL語句】
①權限的控制!比如:某幾個列允許用戶查詢,而其他列不允許,可以通過視圖開放其中的一部分列,達到權限的控制②簡化復雜的查詢!比如:查詢每個欄目下的商品的平均價格并按平均價格排序,然后查出平均價格前3高的欄目
①create view v as select cat_id, avg(shop_price) as pj from goods group by cat_id
②select * from v order by pj limit 0,3
3).視圖能不能更新刪除修改
①視圖【虛擬表】? 是物理表的一個"投影",兩者是相互影響的?更改物理表,虛擬表也會更改,同理,更改虛擬表,物理表也會更改! 但是:如果虛擬表中含有函數(經過計算...),則不能修改!【即物理表和虛擬表的列能一一對應,則虛擬表中該列能修改--改一行影響一行】 ①create view as v select cat_id, avg(shop_price) as pj from goods group by cat_id ②update v set pj = 80 where cat_id=11;--報錯!因為修改結果不能正確映射回到goods表中所有shop_price中 同理:增加和刪除操作也是和修改一樣4).視圖放在什么地方?
①對于VIEW存儲的SQL語句是簡單的select語句,所以當對視圖查詢時候就是對SQL語句的拼接==>對物理表的間接拼接查詢(合并:merge)②對于VIEW存儲的SQL語句已經是邏輯復雜的select語句了,這時對視圖的拼接查詢會更麻煩!
==>這時候mysql會先執行視圖的創建語句,把結果集形成一張臨時表,再對臨時表(temptable)進行操作
MySQL數據庫中可以通過algorithm(算法)定義對視圖的處理情況 create algorithm = merge/temptalbe view v_name as ...
[不寫該屬性,則由MySQL自行判斷]
4. 存儲引擎[ENGINE]
1).什么是存儲引擎?
即:保存"數據"的形式【格式】MYISAM:【處理快-相對不安全-不支持事務】
good.frm--說明書[聲明表結構的表具體語句]
good.MYD--數據內容
goods.MYI--目錄[索引文件]
InnoDB【安全-處理慢-支持事務】--只有.frm文件,其余表的其余全部內容存放在了一個文件中
Memory【存放在內存中--一關機就沒有了】
5.字符集與亂碼問題
1.什么是亂碼?
對計算機來說,沒有"亂碼",只有0/1==>亂碼:人看不懂!2.為什么會亂碼?
①導致原因:文字本來的字符集與展示的字符集不一致==>一般統一utf8;
②服務器和客戶端字符集不一致!
客戶端[GBK提交數據]==>連接器處理[轉換為數據庫字符集]==>數據庫[UTF8存放數據]【無論連接器轉不轉,最終存放到數據庫中都是UTF8】
數據庫[UTF8存放數據]==>連接器處理[轉換為客戶端字符集]==>客戶端[GBK顯示數據]
?由于客戶端和數據庫字符集不同導致的亂碼==>在提交和顯示數據的時候,要"說清楚"字符集
==>"我"要什么字符集?==>客戶端:set character_set_client =gbk;【誰連接服務器誰就是客戶端,客戶端字符集是多變的】
==>"你"接受什么字符集?==>數據庫:set character_set_results=utf8;
==>"轉換"用什么字符集?==>連接器:set character_set_connection = gbk/utf8[都可以]
只需要將3者的字符集設置一致不會亂碼了!==>set names gbk/utf8 ==> 1句好比3句強
UTF8:包含中文,韓文,日文,英語,繁體字...國際化
GBK:只有簡體中文
gbk2123:簡體中文+英文
3.怎么能不亂碼?
①文件保存時是否保存為utf8格式②HTML頁面顯示時候 :
③創建數據表的時候: create table () charset utf8;
④查詢數據的時候:set names utf8;
4.什么是字符校對集?
[utf8-bin==>bin : 二進制排序]==>校對集就是查詢排序的標準?
6. 索引[ index ]
1).查詢方式?
當表中有大量記錄時,若要對表進行查詢:①全表搜索,是將所有記錄一一取出,和查詢條件進行一一對比,然后返回滿足條件的記錄
?消耗大量數據庫系統時間,并造成大量磁盤I/O操作
②第二種就是在表中建立索引,然后在索引中找到符合查詢條件的索引值,最后通過保存在索引中的ROWID(相當于頁碼)快速找到表中對應的記錄
2).什么是索引?
索引是對數據庫表中一列或多列的值進行排序的一種結構,使用索引可快速訪問數據庫表中的特定信息! --相當于圖書的"目錄",根據目錄,迅速定位查找內容的位置3).索引優/缺點?
優點:①加快了查詢時對數據的檢索速度
②創建唯一性索引,保證數據庫表中每一行數據的唯一性
③加速表和表之間的連接
④在使用分組和排序子句進行數據檢索時,可以顯著減少查詢中分組和排序的時間
缺點:
①索引是另外獨立于數據外存放的一個二進制文件==>需要占物理空間( .MYI )
②對表數據進行增、刪和改的維護操作時,索引也要動態的變化==>降低了數據增、刪、改的維護速度
?在創建索引之前,您必須確定要使用哪些列以及要創建的索引類型!
?索引不是越多越好==>一般在查詢頻率多、且重復度小的列上加! 例如:性別和身份號都需要頻繁查詢,且表數據量大
==>性別:就只有男和女,定位的時候有太多重復的了,添加索引反而是占用了空間!
==>身份證號:添加索引,身份證號是唯一的,只要快速找到索引就能快速定位
4).索引類型
①key 列名(索引名)==> 普通索引==>純粹提高查詢速度②unique key 列名(索引名)==> 唯一索引 ==>提高速度,且約束數據唯一性
③primary key 列名 ==> 主鍵索引==>唯一主鍵
④fulltext ==> 全文索引 ==> 在中文環境下,基本不起作用,要分詞索引,一般用第三方解決方案(如:sphinx)?
5).索引長度:
[在建立索引時,對列中一部分字符進行索引]①unique key / key 列名(索引名 (索引長度) )
例如:對于唯一的Email,形式都是.....@qq.com
6).多列索引:
[在建立索引時,對2個或多個列進行索引]7).冗余索引:
[索引存在覆蓋]==>冗余索引有時候在開發中是必要的8).操作索引:
①查看索引:show index table_name;②添加索引:alter table table_name add index column( index_name )
③刪除索引:alter table table_name
添加主鍵索引: alter table table_name add primary key column
刪除主鍵索引: alter table table_name drop primary key;
1.explain select .... ==>查看該語句執行信息==>可以查看使用到的索引
2.索引有一個左前綴查找原則==> ".......xxx"這樣對xxx發揮不了作用
7. 常用九大類函數==>看一次就好!要用的時候至少知道
數據庫是用來存儲管理數據的,能夠少用函數來處理盡量少用==>效率慢1)、數學函數
abs(x) 返回x的絕對值bin(x) 返回x的二進制(oct返回八進制,hex返回十六進制)
ceiling(x) 返回大于x的最小整數值==>向上取整
exp(x) 返回值e(自然對數的底)的x次方
floor(x) 返回小于x的最大整數值==>向下取整
greatest(x1,x2,...,xn)返回集合中最大的值
least(x1,x2,...,xn) 返回集合中最小的值
ln(x) 返回x的自然對數
log(x,y)返回x的以y為底的對數
mod(x,y) 返回x/y的模(余數)
pi()返回pi的值(圓周率)
rand()返回0或1的隨機值,可以通過提供一個參數(種子)使rand()生成器生成1.
round(x,y)返回參數x的四舍五入的有y位小數的值
sign(x) 返回代表數字x的符號的值
sqrt(x) 返回一個數的平方根
truncate(x,y) 返回數字x截短為y位小數的結果
2)、聚合函數(常用于group by從句的select查詢中)
avg(col)返回指定列的平均值count(col)返回指定列中非null值的個數
min(col)返回指定列的最小值
max(col)返回指定列的最大值
sum(col)返回指定列的所有值之和
group_concat(col) 返回由屬于一組的列值連接組合而成的結果
3)、字符串函數
ascii(char)返回字符的ascii碼值bit_length(str)返回字符串的比特長度
concat(s1,s2...,sn)將s1,s2...,sn連接成字符串
concat_ws(sep,s1,s2...,sn)將s1,s2...,sn連接成字符串,并用sep字符間隔
insert(str,x,y,instr) 將字符串str從第x位置開始,y個字符長的子串替換為字符串instr,返回結果
find_in_set(str,list)分析逗號分隔的list列表,如果發現str,返回str在list中的位置
lcase(str)或lower(str) 返回將字符串str中所有字符改變為小寫后的結果
left(str,x)返回字符串str中最左邊的x個字符
length(s)返回字符串str中的字符數
ltrim(str) 從字符串str中切掉開頭的空格
position(substr,str) 返回子串substr在字符串str中第一次出現的位置
quote(str) 用反斜杠轉義str中的單引號
repeat(str,srchstr,rplcstr)返回字符串str重復x次的結果
reverse(str) 返回顛倒字符串str的結果
right(str,x) 返回字符串str中最右邊的x個字符
rtrim(str) 返回字符串str尾部的空格
strcmp(s1,s2)比較字符串s1和s2
trim(str)去除字符串首部和尾部的所有空格
ucase(str)或upper(str) 返回將字符串str中所有字符轉變為大寫后的結果
4)、日期和時間函數
curdate()或current_date() 返回當前的日期curtime()或current_time() 返回當前的時間
date_add(date,interval int keyword)返回日期date加上間隔時間int的結果(int必須按照關鍵字進行格式化),如:selectdate_add(current_date,interval 6 month);
date_format(date,fmt) 依照指定的fmt格式格式化日期date值
date_sub(date,interval int keyword)返回日期date加上間隔時間int的結果(int必須按照關鍵字進行格式化),如:selectdate_sub(current_date,interval 6 month);
dayofweek(date) 返回date所代表的一星期中的第幾天(1~7)
dayofmonth(date) 返回date是一個月的第幾天(1~31)
dayofyear(date) 返回date是一年的第幾天(1~366)
dayname(date) 返回date的星期名,如:select dayname(current_date);
from_unixtime(ts,fmt) 根據指定的fmt格式,格式化unix時間戳ts
hour(time) 返回time的小時值(0~23)
minute(time) 返回time的分鐘值(0~59)
month(date) 返回date的月份值(1~12)
monthname(date) 返回date的月份名,如:select monthname(current_date);
now() 返回當前的日期和時間
quarter(date) 返回date在一年中的季度(1~4),如select quarter(current_date);
week(date) 返回日期date為一年中第幾周(0~53)
year(date) 返回日期date的年份(1000~9999)
一些示例:
獲取當前系統時間:select from_unixtime(unix_timestamp());
select extract(year_month from current_date);
select extract(day_second from current_date);
select extract(hour_minute from current_date);
返回兩個日期值之間的差值(月數):select period_diff(200302,199802);
在mysql中計算年齡:
select date_format(from_days(to_days(now())-to_days(birthday)),'%y')+0 as age from employee;
這樣,如果brithday是未來的年月日的話,計算結果為0。
下面的sql語句計算員工的絕對年齡,即當birthday是未來的日期時,將得到負值。
select date_format(now(), '%y') - date_format(birthday, '%y') -(date_format(now(), '00-%m-%d') < date_format(birthday, '00-%m-%d')) as age from employee
5)、加密函數
aes_encrypt(str,key) 返回用密鑰key對字符串str利用高級加密標準算法加密后的結果,調用aes_encrypt的結果是一個二進制字符串,以blob類型存儲
aes_decrypt(str,key) 返回用密鑰key對字符串str利用高級加密標準算法解密后的結果
decode(str,key) 使用key作為密鑰解密加密字符串str
encrypt(str,salt) 使用unixcrypt()函數,用關鍵詞salt(一個可以惟一確定口令的字符串,就像鑰匙一樣)加密字符串str
encode(str,key) 使用key作為密鑰加密字符串str,調用encode()的結果是一個二進制字符串,它以blob類型存儲
md5() 計算字符串str的md5校驗和
password(str) 返回字符串str的加密版本,這個加密過程是不可逆轉的,和unix密碼加密過程使用不同的算法。
sha() 計算字符串str的安全散列算法(sha)校驗和
示例:
select encrypt('root','salt');
select encode('xufeng','key');
select decode(encode('xufeng','key'),'key');#加解密放在一起
select aes_encrypt('root','key');
select aes_decrypt(aes_encrypt('root','key'),'key');
select md5('123456');
select sha('123456');
6)、控制流函數
mysql有4個函數是用來進行條件操作的,這些函數可以實現sql的條件邏輯,允許開發者將一些應用程序業務邏輯轉換到數據庫后臺。 mysql控制流函數: case when[test1] then [result1]...else [default] end如果testn是真,則返回resultn,否則返回default case [test] when[val1] then [result]...else [default]end 如果test和valn相等,則返回resultn,否則返回default if(test,t,f) 如果test是真,返回t;否則返回f ifnull(arg1,arg2) 如果arg1不是空,返回arg1,否則返回arg2 nullif(arg1,arg2) 如果arg1=arg2返回null;否則返回arg1 這些函數的第一個是ifnull(),它有兩個參數,并且對第一個參數進行判斷。==>如果第一個參數不是null,函數就會向調用者返回第一個參數;如果是null,將返回第二個參數。 如:select ifnull(1,2), ifnull(null,10),ifnull(4*null,'false'); nullif()函數將會檢驗提供的兩個參數是否相等,如果相等,則返回null,如果不相等,就返回第一個參數。 如:select nullif(1,1),nullif('a','b'),nullif(2+3,4+1); 和許多腳本語言提供的if()函數一樣,mysql的if()函數也可以建立一個簡單的條件測試,這個函數有三個參數:==>第一個是要被判斷的表達式,如果表達式為真,if()將會返回第二個參數,如果為假,if()將會返回第三個參數。 如:selectif(1<10,2,3),if(56>100,'true','false'); if()函數在只有兩種可能結果時才適合使用。然而,在現實世界中,我們可能發現在條件測試中會需要多個分支。---在這種情況下,mysql提供了case函數,它和php及perl語言的switch-case條件例程一樣。 case函數的格式有些復雜,通常如下所示: case [expression to be evaluated] when [val 1] then [result 1] when [val 2] then [result 2] when [val 3] then [result 3] ...... when [val n] then [result n] else [default result] end這里,第一個參數是要被判斷的值或表達式,接下來的是一系列的when-then塊,每一塊的第一個參數指定要比較的值,如果為真,就返回結果。所有的when-then塊將以else塊結束,當end結束了所有外部的case塊時==>如果前面的每一個塊都不匹配就會返回else塊指定的默認結果。如果沒有指定else塊,而且所有的when-then比較都不是真,mysql將會返回null。 case函數還有另外一種句法,有時使用起來非常方便,如下: case when [conditional test 1] then [result 1] when [conditional test 2] then [result 2] else [default result] end 這種條件下,返回的結果取決于相應的條件測試是否為真。 示例: mysql>select case 'green'when 'red' then 'stop'when 'green' then 'go' end; select case 9 when 1 then 'a' when 2 then 'b' else 'n/a' end; select case when (2+2)=4 then 'ok' when(2+2)<>4 then 'not ok' end asstatus; select name,if((isactive = 1),'已激活','未激活') as result fromuserlogininfo; select fname,lname,(math+sci+lit) as total, case when (math+sci+lit) < 50 then 'd' when (math+sci+lit) between 50 and 150 then 'c' when (math+sci+lit) between 151 and 250 then 'b' else 'a' end as grade from marks; select if(encrypt('sue','ts')=upass,'allow','deny') as loginresultfrom users where uname = 'sue';#一個登陸驗證?
7)、格式化函數
date_format(date,fmt) 依照字符串fmt格式化日期date值
format(x,y) 把x格式化為以逗號隔開的數字序列,y是結果的小數位數
inet_aton(ip) 返回ip地址的數字表示
inet_ntoa(num) 返回數字所代表的ip地址
time_format(time,fmt) 依照字符串fmt格式化時間time值
其中最簡單的是format()函數,它可以把大的數值格式化為以逗號間隔的易讀的序列。
示例:
select format(34234.34323432,3);
select date_format(now(),'%w,%d %m %y %r');
select date_format(now(),'%y-%m-%d');
select date_format(19990330,'%y-%m-%d');
select date_format(now(),'%h:%i %p');
select inet_aton('10.122.89.47');
select inet_ntoa(175790383);
8)、類型轉化函數
為了進行數據類型轉化,mysql提供了cast()函數,它可以把一個值轉化為指定的數據類型。類型有:binary,char,date,time,datetime,signed,unsigned 示例:
select cast(now() as signed integer),curdate()+0;
select 'f'=binary 'f','f'=cast('f' as binary);
9)、系統信息函數
database() 返回當前數據庫名
benchmark(count,expr) 將表達式expr重復運行count次
connection_id() 返回當前客戶的連接id
found_rows() 返回最后一個select查詢進行檢索的總行數
user()或system_user() 返回當前登陸用戶名
version() 返回mysql服務器的版本
示例:
select database(),version(),user();
selectbenchmark(9999999,log(rand()*pi()));#該例中,mysql計算log(rand()*pi())表達式9999999次。
8. 事務的概念
1.什么是事務?
將一個業務下的SQL語句作為一個單元統一操作==>"同生共死"!【MyISAM不支持事務】例如:A"打賬"500給B,打完之后A減少500,B增加500!如果這兩個動作有一個沒完成則整個打賬過程取消失敗--[原子性]
2.如何啟用事務?
start transaction;3.如何結束事務?
commit;4.如何撤銷事務?【回滾事務】
rollback; ? 事務的中間狀態是不可見的--隔離性 事務發生結束了之后是不能恢復的--持久性 事務之前和之后它們的業務邏輯上要保持一致!兩人總賬額度9000,相互轉帳后依然是9000 -- 一致性對于MySQL索引優化,DCL...等部分,工作之后就會遇到!現在可以不必要學!現在學了也不一定會,會了也不一定能用得上,用得上也不一定能記得!
轉載于:https://www.cnblogs.com/lms520/p/5427685.html
總結
以上是生活随笔為你收集整理的最全的MySQL基础【燕十八传世】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql数据库保存中文乱码解决参考方案
- 下一篇: 网页开发中文本编辑器UEditor的使用