MYSQL 專案中的實際運用(一)
目錄
1、CAST
CAST強轉函式語法規則是:Cast(欄位名 as 轉換的型別 ),其中型別可以為:CHAR(N) ,DATE ,TIME,DATETIME ,DECIMAL,BINARY,SIGNED,UNSIGNED
一般用法: select cast(Id aschar(64)) as Id from Building_table
2、select 1
select 1 from table
作用一:select 1 from mytable;與select anycol(目的表集合中的任意一行) from mytable;與select * from mytable 作用上來說是沒有差別的,都是檢視是否有記錄,一般是作條件用的。select 1 from 中的1是一常量,查到的所有行的值都是它,但從效率上來說,1>anycol>*,因為不用查字典表。
作用二:select id, 'xxxx’ from table 給結果集增加臨時列,每行的列值是寫在select後的數或字元,這條sql語句中是xxxx
3、CASE WHEN THEN ELSE END
CASE WHEN THEN ELSE END
注意:其實從case到end的這段語句完全可以看作一個欄位名,後邊可以也必須加AS,給結果集中的這個欄位新增別名,不然欄位名顯示的就是從case到end的這段語句!!!!
注意:其實case語句的本質就是對每行記錄的某些欄位進行比較,然後根據結果,返回一個自定義的新值,最終這些值組成了一個新欄位,而行列轉換也不過是在這基礎上,用了分組聚合!!!!
注意:Case函式只返回第一個符合條件的值,剩下的Case部分將會被自動忽略!!!
--比如說,下面這段SQL,你永遠無法得到“第二類”這個結果
CASE WHEN col_1 IN ( 'a', 'b') THEN '第一類'
WHEN col_1 IN ('a') THEN '第二類'
ELSE'其他' END
用法一 :列舉一個欄位所有可能的值,然後根據這些值衍生出新的值,這些值將作為一個自定義欄位新增到結果集中
SELECT NAME '英雄', CASE NAME WHEN '德萊文' THEN '斧子' WHEN '德瑪西亞-蓋倫' THEN '大寶劍' WHEN '暗夜獵手-VN' THEN '弩' ELSE '無' END '裝備' FROM user_info;
用法二:判斷欄位範圍,根據判斷結果的不同衍生出不同的值,這些值將作為一個自定義欄位新增到結果集中
-- when 表示式中可以使用 and 連線條件
SELECT
NAME '英雄',
age '年齡',
CASE
WHEN age < 18 THEN
'少年'
WHEN age < 30 THEN
'青年'
WHEN age >= 30
AND age < 50 THEN
'中年'
ELSE
'老年'
END '狀態'
FROM
user_info;
用法三:使用 case when 配合 聚合函式 實現行轉列,即行資料變列欄位,可以大幅減少結果集的記錄量,更符合非程式設計師使用者的閱讀習慣,但是想要行列轉換,就必須要用聚合函式和分組!!!
舉個例子,平時資料庫想要查學生成績,結果集都是三列N行,姓名,科目,成績,有N個科目就有N行,但是上過學的都知道,平時發的成績條,哪有那麼多行,直接一行搞定,要你是使用者你覺得這兩種方式哪種看著舒服?
例項程式碼和詳細用法都在下邊三個連結裡面:
4、對錶欄位名的操作
select語句中,對錶欄位名的所有操作,其實是對欄位對應的記錄值進行操作,比如+,-,聚合函式,concat拼接函式等
關鍵點:distinct去重關鍵字,直接使用即可,例如SELECT DISTINCT stu_id
關鍵點:+號,在mysql中+號不能作為字串連線符,如果兩個字串用+連線,會自動把兩邊轉化成數字型別再進行相加操作,如果哪一邊字串不能轉為數字,哪一邊就返回0。
5、派生表
派生表和子查詢通常可互換使用。當SELECT
語句的FROM
子句中使用獨立子查詢時,我們將其稱為派生表。
派生表必須具有別名。
6、巢狀查詢
巢狀查詢
定義:一個內層查詢語句(select-from-where)塊可以巢狀在另外一個外層查詢塊的where子句中,其中外層查詢也稱為父查詢,主查詢。內層查詢也稱子查詢,從查詢。子查詢一般不使用order by子句,只能對最終查詢結果進行排序。
巢狀查詢的工作方式是:先處理內查詢,由內向外處理,外層查詢利用內層查詢的結果巢狀查詢不僅僅可以用於父查詢select語句使用。還可以用於insert、update、delete語句或其他子查詢中。
子查詢的語法規則:子查詢的select查詢總是使用圓括號括起來;任何可以使用表示式的地方都可以使用子查詢,只要它返回的是單個值;如果某個表只出現在子查詢中二不出現在外部查詢中,那麼該表的列就無法包含在輸出中;一般,對於子查詢生成的表都給它起個別名。
任何可以使用表示式的地方都可以使用子查詢(一般用在WHERE後),這句話是重點,可以分為兩種情況:
注意:從本質上來說,這種巢狀查詢就是每行的特定欄位值代入表示式之後,只有表示式結果為true的那行記錄才會被輸出。
一、當子查詢的返回值只有一個時,可以使用比較運算子如=、<、>、>=、<=、!=等
二、如果子查詢的返回值不止一個,而是一個集合時,則不能直接使用比較運算子:(子查詢關鍵字來啦)
any必須與=、>、>=、<、<=、<>結合起來使用,分別表示等於、大於、大於等於、小於、小於等於、不等於其中的任何一個數據。
注意:some是any的別名,用法相同,也就是說知道就行,沒卵用
all必須與=、>、>=、<、<=、<>結合是來使用,分別表示等於、大於、大於等於、小於、小於等於、不等於其中的其中的所有資料。
例如:
select s1 from t1 where s1 > any (select s1 from t2);
假設表t1中有一行包含(10),t2包含(21,14,6),則表示式為true;如果t2包含(20,10),或者表t2為空表,則表示式為false。如果表t2包含(null,null,null),則表示式為unkonwn。
all的意思是“對於子查詢返回的列中的所有值,如果比較結果為true,則返回true”
例如:
select s1 from t1 where s1 > all(select s1 from t2);
假設表t1中有一行包含(10)。如果表t2包含(-5,0,+5),則表示式為true,因為10比t2中的查出的所有三個值大。如果表t2包含(12,6,null,-100),則表示式為false,因為t2中有一個值12大於10。如果表t2包含(0,null,1),則表示式為unknown。如果t2為空表,則結果為true。
in查詢相當於多個or條件的疊加,這個比較好理解,比如下面的兩個等效查詢
select * from user where userId in (1, 2, 3);
select * from user where userId = 1 or userId = 2 or userId = 3;
not in與in相反,例如:
select * from user where userId not in (1, 2, 3);
select * from user where userId != 1 and userId != 2 and userId != 3;
總的來說,in查詢就是先將子查詢條件的記錄全都查出來,假設結果集為B,如果父表字段值在B中,就返回true,且返回其對應的那條記錄!!!!
值得一提的是,in查詢的子條件返回結果必須只有一個欄位,例如:
select * from user where userId in (select id from B);
而不能是
select * from user where userId in (select id, age from B);
exists表示存在,它常常和子查詢配合使用,例如下面的SQL語句
SELECT * FROM `user`
WHERE exists (SELECT * FROM `order` WHERE user.id = order.user_id)
exists用於檢查子查詢是否至少會返回一行資料,該子查詢實際上並不返回任何資料,而是返回值True或False。
當子查詢返回為真時,則外層查詢語句將進行查詢。
當子查詢返回為假時,外層查詢語句將不進行查詢或者查詢不出任何記錄。
7、while,if
while迴圈
# while迴圈語法:
# while 條件 DO
# 迴圈體;
# end while;
# */
-- 例項:
create procedure sum1(a int)
begin
declare sum int default 0; -- default 是指定該變數的預設值
declare i int default 1;
while i<=a DO -- 迴圈開始
set sum=sum+i;
set i=i+1;
end while; -- 迴圈結束
select sum; -- 輸出結果
end
IF ELSE 作為流程控制語句使用
IF search_condition Then
statement_list
[ELSEIF search_condition Then]
[ELSE
statemeny_list]
END IF;
最關鍵也是最坑爹的一點,while迴圈和if只能在儲存過程中使用!!!!!
但有一種特殊情況:
如果存在表則刪除表然後建立
drop table if exists address_book
但是也只能這麼寫,不能擴充套件加and什麼的!!!!!
8、臨時表
臨時表主要用於對大資料量的表上作一個子集,提高查詢效率。
臨時表使用有一些限制條件:
* 不能使用rename來重新命名臨時表。但是可以alter table rename代替:
mysql>ALTER TABLE orig_name RENAME new_name;
* 可以複製臨時表得到一個新的臨時表,如:
mysql>create temporary table new_table select * from old_table;
* 但在同一個query語句中,相同的臨時表只能出現一次。如:
可以使用:mysql> select * from temp_tb;
但不能使用:mysql> select * from temp_tb, temp_tb as t;
錯誤資訊: ERROR 1137 (HY000): Can't reopen table: 'temp_tb'
同樣相同臨時表不能在儲存函式中出現多次,如果在一個儲存函式裡,用不同的別名查詢一個臨時表多次,或者在這個儲存函式裡用不同的語句查詢,都會出現這個錯誤。
既然子查詢中不能再次開啟臨時表,那麼就使用其他臨時表 先把子查詢的資料存起來,然後再處理。
* 但不同的臨時表可以出現在同一個query語句中,如臨時表temp_tb1, temp_tb2:
Mysql> select * from temp_tb1, temp_tb2;
臨時表可以手動刪除:
DROP TEMPORARY TABLE IF EXISTS temp_tb;
9、讀寫操作的影響行數
讀操作的影響行數:select fount_rows();
寫操作的影響行數:select row_count();
但切記:只對一次操作有效!!也就是隻返回最後一次操作的影響的行數的值.
10、NULL相關函式
第一步,is NULL要比ISNULL()的比較
SELECT * from 表名 where 欄位名 is NULL
SELECT * from 表名 where ISNULL(欄位名)
由上面可以看出,is NULL要比ISNULL()快一點。
第二步,is NULL和IFNULL()的比較
SELECT * from 表名 where 欄位名 is NULL
SELECT * from 表名 where IFNULL(欄位名,'0') = '0';
由上面可以看出,可看出IFNULL()要比is NULL快一點。
綜上所述,查詢空值的執行速度基本上為IFNULL()>is NULL>ISNULL()。
重點:
IFNULL(expr1,expr2)的用法:
假如expr1 不為 NULL,則 IFNULL() 的返回值為 expr1;
否則其返回值為 expr2。IFNULL()的返回值是數字或是字串,具體情況取決於其所使用的語境。
1 2 3 4 5 6 7 8 9 |
|
NULLIF(expr1,expr2) 的用法:
如果expr1 = expr2 成立,那麼返回值為NULL,否則返回值為 expr1。這和CASE WHEN expr1 = expr2
THEN NULL ELSE expr1 END相同。
1 2 3 4 5 |
|
IF(exPR1,expr2,expr3) 的用法:
如果 expr1 是TRUE (expr1 <> 0 and expr1 <> NULL),則 IF()的返回值為expr2; 否則返回值則為 expr3。IF() 的返回值為數字值或字串值,具體情況視其所在語境而定。
SELECT IF(1>2,2,3);
11、分組聚合
分組一般和聚合一塊出現!!!!!
分組,說白就是找相同,根據欄位值(欄位組),相同就是一組
分組聚合,在已經分好組的前提上,對每組進行操作,返回對每組操作的結果,也就是一組只有一個結果。比如,如果想知道每組裡有多少條記錄,可以用count(1)
分組查詢,如果查詢的欄位名和group by 的欄位名是一樣的,輸出結果集就是不同的各個組名(欄位名),這很好理解;但如果查詢的不光是group by的欄位名,那結果集是每組查到的第一條記錄,注意是一條,如果你想看每個分組的所有資料,建議你用order by和where。
分組排序:是先排序後分組,造成的結果是,如果查詢的不光是group by的欄位名,那結果集會因為順序不同而變化,當然,也只是每個分組裡的一條不同記錄罷了。
12、時間戳
mysql時間戳
獲得當前日期+時間(date + time)函式:now()
13、變數賦值
在MySQL儲存過程中使用SELECT …INTO語句為變數賦值:
用來將查詢返回的一行的各個列值儲存到區域性變數中。
要求:
查詢的結果集中只能有1行。
SELECT col_name[,...] INTO var_name[,...] table_expr
使用SELECT …INTO語句在資料庫中進行查詢,並將得到的結果賦值給變數。
①col_name:要從資料庫中查詢的列欄位名;
②var_name:變數名,列欄位名按照在列清單和變數清單中的位置對應,將查詢得到的值賦給對應位置的變數;
③table_expr:SELECT語句中的其餘部分,包括可選的FROM子句和WHERE子句。
14、備份表
MySQL不支援Select Into語句直接備份表結構和資料
錯誤方法:
MYSQL不支援:
Select * Into new_table_name from old_table_name; 這是sql server中的用法
替代方法:
Create table new_table_name (Select * from old_table_name);
15、DATE函式
DATE_ADD() 函式向日期新增指定的時間間隔。
語法
DATE_ADD(date,INTERVAL expr type)
date 引數是合法的日期表示式。expr 引數是您希望新增的時間間隔。
type 引數可以是下列值DAY,HOUR,等等一堆
例項
假設我們有如下的表:
OrderId | ProductName | OrderDate |
---|---|---|
1 | 'Computer' | 2008-12-29 16:25:46.635 |
現在,我們希望向 "OrderDate" 新增 2 天,這樣就可以找到付款日期。
我們使用下面的 SELECT 語句:
SELECT OrderId,DATE_ADD(OrderDate,INTERVAL 2 DAY)
AS OrderPayDate
FROM Orders
結果:
OrderId | OrderPayDate |
---|---|
1 | 2008-12-31 16:25:46.635 |