1》查詢語句的基本語法
語法:
SELECT 屬性列表
FROM 表名
[WHERE 條件表達式 1]
[GROUP BY 屬性名1 [HAVING 條件表達式2]]
[ORDER BY 屬性名2 [ASC | DESC]]
屬性列表表示需要查詢的字段名
表名表示指的表名
WHERE 表示指定查詢的條件
GROUP BY 指定的字段進行分組
如果GROUP BY 子句后面帶着HAVING關鍵字,那么只有滿足條件2才能輸出。
2》在單表上查詢數據:
v 列出表的所有字段
root@zytest 16:19>select order_num,order_date,cust_id from orders;
v 使用*查出單表所有字段
root@zytest 16:22>select * from orders;
v 查詢指定的字段
在orders表中有3個字段,order_num、order_date、cust_id,我們查詢其中2個。
root@zytest 16:22>select order_num,order_date from orders;
v where查詢指定記錄
root@zytest 16:53>select * from orders where cust_id=10003;
*****比較
root@zytest 16:53>select * from orders where cust_id<=10003;小於或者等於
root@zytest 16:56>select * from orders where cust_id>=10003;大於或者等於
root@zytest 16:56>select * from orders where cust_id>10003;大於
root@zytest 16:56>select * from orders where cust_id<10003;小於
root@zytest 16:57>select * from orders where cust_id != 10003; 不等於
root@zytest 16:57>select * from orders where cust_id <> 10003;排除掉10003
指定范圍
root@zytest 16:57>select * from orders where cust_id between 10003 and 10004;
root@zytest 16:57>select * from orders where cust_id not between 10003 and 10004;
指定集合
root@zytest 16:57>select * from orders where cust_id in(10001,10004);
root@zytest 16:57>select * from orders where cust_id not in(10003,10004);
匹配字符
root@zytest 16:57>select * from orders where cust_id like ‘10001’;
root@zytest 16:57>select * from orders where cust_id not like ‘10001’;
是否為空值
root@zytest 16:57>select * from vendors where vend_state is null;
root@zytest 16:57>select * from vendors where vend_state is not null;
多條件查詢
root@zytest 16:57>select * from orders where cust_id=10003 and order_num=20005;
root@zytest 16:57>select * from orders where cust_id=10003 or cust_id=10005;
查詢結果不重復(distinct)字段名
語法:select distinct 字段名
select distinct cust_id from orders;
查詢結果進行排序
語法:order by 屬性名 [ASC|DESC]
select distinct cust_id from orders where cust_id>10003 order by cust_id desc;
查詢數據進行分組group by
語法:group by 屬性名 [having 條件表達式][with rollup]
having用來限制分組后的顯示,滿足條件表達式的結果將被顯示
with rollup 關鍵字將會在所有記錄的最后加上一條記錄,該記錄是上面所有記錄的總和.
group關鍵字通常和group_concat()函數一起使用.group_concat把每個分組指定的字段值顯示出來.
group by 使用having條件約束過濾having 跟where作用一樣。但是having只能用於group by 。
select sex,count(sex),group_concat(name) from student group by sex having sex='女';
group by 多個字段進行分組
select sex,count(sex),group_concat(name) from student group by sex,user_id having sex='女';
group by 與with rollup一起使用
root@zytest 10:02>select sex,count(sex) from student group by sex;
得出了分組出來的數量。如果想得到分組出來的總和怎么辦?
我們后面再加上with rollup就可以得出。
root@zytest 10:02>select sex,count(sex) from student group by sex with rollup;
對單個字段進行普通分組
root@zytest 06:56>select * from student group by address;
結合group_concat()進行指定每個分組的值
root@zytest 08:48>select sex,group_concat(name) from student group by sex;
使用limint限制查詢結果的數量
root@zytest 10:07>select * from student where user_id >2 limit 2;
3》使用集合函數查詢數據:
集合函數包括:
count() 用來統計記錄的條數
sum() 用來計算字段的值和總數
avg() 用來計算字段的值的平均值
max() 用來查詢字段的最大值
min() 用來查詢字段的最小值
count()總計所有記錄的條目總數
root@zytest 10:24>select count(*) from student;
sum字段值得總和
root@zytest 10:25>select sum(user_id) from student;
avg 取平均值
root@zytest 10:25>select avg(user_id) from student;
max()取字段值得最大值
root@zytest 10:27>select max(user_id) from student;
min()取字段值得最小值
root@zytest 10:28>select min(user_id) from student;
4》多表連接查詢:
1>內連接
具有相同意義的字段,才可以進行內連接:
root@zytest 15:56>select cust_name,cust_address,order_date from customers,orders
where customers.cust_id=orders.cust_id;
2>外連接
外連接包括左查詢和右查詢
select屬性名列表
from 表名1 left | right join 表名2 on 表名1.屬性名=表名2.屬性名;
左連接查詢:
可以查詢出表名1里面所有的數據,而表名2只能查出匹配的記錄。
以下例子:表名1=vendors(主表)表名2=products(匹配表)
root@zytest 17:42>select vendors.vend_id,prod_name,prod_price from vendors left join products on
vendors.vend_id=products.vend_id;
右連接查詢
可以查詢出表名2所有的記錄。而表名1只能查出匹配記錄。
以下例子:表名2=products(主表) 表名1=vendors(匹配表)
root@zytest 17:52>select products.vend_id,prod_name from vendors right join products on
vendors.vend_id=products.vend_id;
看不到1006?因為products里面沒有1006,所以在vendors表中不匹配。這里用用vendors ID去匹配products。有則匹配。
復合查詢:
在左連接或者右連接查詢出來之后如何進一步過濾?
root@zytest 18:18>select products.vend_id,prod_name,vend_name,vendors.vend_id from vendors right
join products on vendors.vend_id=products.vend_id where products.prod_name='Safe';
在后面直接加where就行了。
5》子查詢:
子查詢時將一個查詢語句內嵌到另個查詢語句當中。內層查詢的查詢結果,可以為外層查詢語句提供查詢條件;
1>帶IN關鍵字的子查詢
insert into student values('10005','aaaaa','','aaaaaa');
insert into student values('10006','aaaaa','','aaaaaa');
insert into student values('10003','aaaaa','','aaaaaa');
root@zytest 18:40>select * from orders where cust_id in (select user_id from student);
root@zytest 18:55>select * from orders where cust_id in (select user_id from student) and cust_id>'10003';進一步過濾
6》合並查詢:
有時候需要多個表進行合並數據。我們使用union和union all,使用union時系統會將合並的結果去掉重復。並且顯示。但是union all恰恰相反,不會去掉 重復,會把所有的內容全部顯示出來;
root@zytest 19:06>select vend_id from vendors union select vend_id from products;
root@zytest 19:07>select vend_id from vendors union all select vend_id from products;
7》為表和字段取別名:
為表取別名:
select * from student aa where aa.user_id='1';
為字段取別名:
select user_id as alvinzeng from student;
mysql> select * from yy1 aa where aa.user_id=1;
+---------+-----------+
| user_id | user_name |
+---------+-----------+
| 1 | zhangsan |
+---------+-----------+
1 row in set (0.00 sec)
8》使用正則查看:
在我們的mysql當中,照樣可以使用正則表達式來查詢結果;
正則我們使用關鍵字“regexp”來連接正則
select * from vendors where vend_name regexp '^An';以An開頭的
select * from vendors where vend_city regexp 's$';以s結尾的
select * from vendors where vend_city regexp '.d';如果字符后面包含d
select * from vendors where vend_city regexp 'd.'; d后面包含的任意字符
select * from vendors where vend_city regexp '[London]';只要包含中括號里面任意一個字符的都會被顯示出來
select * from vendors where vend_city regexp '[^Paris]';匹配除了Paris以外的所有字符,也就是說Paris將被過濾掉了。
select * from vendors where vend_state regexp 'MI|OH';匹配MI或者OH任意一個滿足都會被顯示出來。
select * from vendors where vend_state regexp 'M*';匹配以包含M后面的任何字符。
select * from vendors where vend_name regexp 'll+';代表多個字符前面或者后面的任何字符
select * from vendors where vend_city regexp 'd{1}';查詢d出現過1次或者N次
select * from vendors where vend_city regexp 'd{1,3}';查詢d出現過1次,最多出現3次,
=====================Mysql存儲過程與存儲函數=================
1》創建存儲過程:
語法:
MySQL中,創建存儲過程的基本形式如下:
1>CREATE PROCEDURE sp_name ([proc_parameter[,...]])
[characteristic ...] routine_body
create 是創建的的意思
procedure 是指的創建的類型是存儲過程。
sp_name參數是存儲過程的名稱;
proc_parameter表示存儲過程的參數列表;
characteristic參數指定存儲過程的特性;
routine_body參數是SQL代碼的內容,可以用BEGIN…END來標志SQL代碼的開始和結束。
proc_parameter中的每個參數由3部分組成。這3部分分別是輸入輸出類型、參數名稱和參數類型。其形式如下:
[ IN | OUT | INOUT ] param_name type
其中,IN表示輸入參數;OUT表示輸出參數; INOUT表示既可以是輸入,也可以是輸出; param_name參數是存儲過程的參數名稱;type參數指 定存儲過程的參數類型,該類型可以是MySQL數據庫的任意數據類型。
說明:MySQL中默認的語句結束符為分號(;)。存儲過程中的SQL語句需要分號來 結束。為了避免沖突,首先用"DELIMITER &&"將MySQL的結束符 設置為&&。最后再用"DELIMITER ;"來將結束符恢復成分號。這與創建觸發器時是一樣的。
2>存儲過程和存儲函數的區別:
存儲過程和函數目的是為了可重復地執行操作數據庫的SQL語句的集合,區別是寫法和調用上:
寫法上:存儲過程的參數列表可以有輸入參數,輸出參數,可以輸入輸出參數。函數的參數列表只有輸入參數,並且有return<返回值類型,無長度說 明>
在返回值上的區別:存儲過程的返回值,可以有多個值,函數返回值,只有一個值;
舉例1:
需求一、存儲過程一(功能返回Mysql的版本號、用戶、所在數據庫、用戶連接數、)
Delimiter &&
create procedure alvin1(
out getversion varchar(30),
out userversion varchar(30),
out userdatabase varchar(30),
out userconnection int)
reads sql data
begin
select version() into getversion;
select user() into userversion;
select database() into userdatabase;
select connection_id() into userconnection;
end &&
delimiter ;
call alvin1(@a,@b,@c,@d);
select @a,@b,@c,@d;
需求二、統計student id的數據量總共是多少?
create procedure alvin2(
out zycount int)
reads sql data
begin
select count(*) into zycount from student;
end&&
delimiter ;
call alvin2(@a);
select @a;
2》變量的使用:
在整個存儲和函數中,可以定義和使用變量,用戶可以使用declare關鍵字來定義變量,然后可以為變量賦值,這些變量的作用范圍是begin…end程序 中。
1>定義變量
declare aa_id int default 10;
2>為變量賦值
set aa_id=1001;
IN參數例子:
root@zytest 23:15>delimiter &&
root@zytest 23:16>create procedure alvin1( #創建一個名字為alvin1存儲過程
-> in p_in int) #設置傳入的參數類型和變量
-> begin
-> select p_in; #查詢第一次傳進來的參數
-> set p_in=2; #:重新給p_in 賦值后。覆蓋掉傳進來的參數值
-> select p_in; #:在查詢一次賦值
->end&&
root@zytest 23:19>delimiter ;
root@zytest 23:19>set @p_in=1;#開始傳入參數賦值
root@zytest 23:19>call alvin1(@p_in);#調用存儲過程
+------+
| p_in |
+------+
| 1| #傳入的值為1,
+------+
1 row in set (0.03 sec)
+------+
| p_in |
+------+
| 2 | #過程當中的二次賦值
+------+
1 row in set (0.03 sec)
Query OK 0 rows affected (0.03 sec)
root@zytest 23:20>select @p_in; #查詢外邊傳參賦值的結果
+-------+
| @p_in |
+-------+
| 1 |
+-------+
OUT參數例子:
root@zytest 23:41>delimiter &&
root@zytest 23:41>create procedure name_info(創建一個名稱為name_info的存儲過程
-> out p_out int) #定義輸出的變量和數據類型
-> begin
-> select p_out; #查看輸出參數
-> set p_out=2; #給參數賦值
-> select p_out; #查詢賦值結果
->end&&
Query OK, 0 rows affected (0.00 sec)
root@zytest 23:42>delimiter ;
root@zytest 23:42>set @p_out=1; #傳入一個參數。看看是否會在call調用的時候顯示出來?
Query OK, 0 rows affected (0.00 sec)
root@zytest 23:42>call name_info(@p_out);
+-------+
| p_out |
+-------+
| NULL | #傳入的參數為空
+-------+
1 row in set (0.01 sec)
+-------+
| p_out |
+-------+
| 2 | #存儲函數里面賦值的參數調用成功
+-------+
1 row in set (0.01 sec)
root@zytest 23:42>select @p_out;
+--------+
| @p_out |
+--------+
| 2 | #:只看到存儲函里面賦值的。傳入的參數無效。
+--------+
1 row in set (0.00 sec)
INOUT參數列子:
root@zytest 00:03>delimiter &&
root@zytest 00:03>create procedure alvin_name( #創建一個名為alvin_name的函數
-> inout p_inout int) #創建一個可以傳入和傳出的p_inout的變量和數據類型
-> begin
-> select p_inout; #:查詢傳入的數據
-> set p_inout=2; #:給p_inout的賦值
-> select p_inout; #:在此查詢p_inout的值
->end&&
root@zytest 00:04>delimiter ;
root@zytest 00:04>set @p_inout=1; #:開始傳入參數
Query OK, 0 rows affected (0.00 sec)
root@zytest 00:04>call alvin_name(@p_inout); #:開始調用
+---------+
| p_inout |
+---------+
| 1 | #使用inout既可以傳入可以傳出
+---------+
1 row in set (0.00 sec)
+---------+
| p_inout |
+---------+
| 2 | #使用inout既可以傳入可以傳出
+---------+
1 row in set (0.00 sec)
root@zytest 00:04>select @p_inout; #查詢最后結果
+----------+
| @p_inout |
+----------+
| 2 | #:可以傳出也可以傳入,最終返回結果為2,
+----------+
1 row in set (0.00 sec)
3》創建存儲函數:
語法:create function sp_name([func_parameter[,…….]])
Returns type
[characteristic…]routine_body。
其中,sp_name參數是存儲函數的名稱。
Func_parameter 表示存儲函數的參數列表。
Returns type 指定返回的參數類型。
characteristic參數指定存儲函數的特性。
routine_body參數是SQL代碼的內容。
可以用BEGIN…END來標志 SQL代碼開始和結束。
create function 函數名(參數1 數據類型[,參數2 數據類型,參數3 數據類型])returns 返回值類型
begin
任意系列的sql語句;
return 返回值;
end;
注:與儲存過程不同
1、參數只有輸入型
2、向調用方返回結果值
常見的錯誤:
This function has none of DETERMINISTIC, NO SQL解決辦法
創建存儲過程時
出錯信息:
ERROR 1418 (HY000): This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled (you *might* want to use the less safe log_bin_trust_function_creators variable)
其中在function里面,只有 DETERMINISTIC, NO SQL 和 READS SQL DATA 被支持。如果我們開啟了 bin-log, 我們就必須為我們的function指定一個參數。
解決方法:
SQL code
mysql> show variables like 'log_bin_trust_function_creators';
+---------------------------------+-------+
| Variable_name | Value |
+---------------------------------+-------+
| log_bin_trust_function_creators | OFF |
+---------------------------------+-------+
mysql> set global log_bin_trust_function_creators=1;
mysql> show variables like 'log_bin_trust_function_creators';
+---------------------------------+-------+w
| Variable_name | Value |
+---------------------------------+-------+
| log_bin_trust_function_creators | ON |
+---------------------------------+-------+
這樣添加了參數以后,如果mysqld重啟,那個參數又會消失,因此記得在my.cnf配置文件中添加:
log_bin_trust_function_creators=1
舉列:根據輸入的vend_id查詢到每個用戶的vend_name。
delimiter&&
create function alvin11( #創建一個函數名稱為alvin11
bb_id int)#定義一個參數類型和它的數據類型
returns varchar(20)#定義下面vend_name的返回數據類型
begin # 開始
return (select vend_name from vendors#返回 SQL語句查詢的結果,
where vend_id=bb_id);
end && #結束
delimiter ;#跳出總體段落。
select alvin11(1001);#調用存儲函數-查詢結果
4》流程控制:
1>存儲過程if語句使用方法:
delimiter&&
create procedure zy_if(in aa int,out bb int)
begin
if aa>20 then
set bb=30;
elseif aa=20
then
set bb=20;
else
set bb=15;
end if;
end&&
delimiter ;
開始調用1 aa=20
call zy_if(20,@bb);
select @bb;
開始調用2 aa=25
call zy_if(25,@bb);
select @bb;
開始調用3 aa=15
call zy_if(15,@bb);
select @bb;
2>存儲過程case用法
delimiter&&
create procedure zy_case(in aa int,inout bb int)
begin
case
when aa=20 then set bb=20;
when aa>20 and aa<=50 then set bb=30;
when aa>51 then set bb=60;
else set bb=15;
end case;
end&&
delimiter ;
開始調用驗證1
call zy_case(20,@bb);
select @bb;
開始調用驗證2
call zy_case(21,@bb);
select @bb;
開始調用驗證3
call zy_case(52,@bb);
select @bb;
開始調用驗證4
call zy_case(10,@bb);
select @bb;
3>存儲過程 while 循環使用,插入1萬條數據
delimiter&&
create procedure zy_while()
begin
declare count int default 0;
while count < 10000 do
insert into zybb (user_id,name)values(count,'aa1');
set count = count + 1;
end while;
end&&
delimiter ;
call zy_while();調用存儲過程
5》調用存儲過程和函數:
1>調用方式call +存儲過程名稱+參數
如:call alvin_name(@p_inout);
2>查詢結果
select @p_inout
6》查看存儲過程和函數:
1>查詢存儲過程
show procedure status;
查詢某具體存儲過程詳細
show create procedure alvin1\G;
2>查詢存儲函數
show function status;
查詢某個具體存儲函數詳細
show create function alvin10\G;
7》刪除存儲過程和函數:
1>刪除存儲過程
drop procedure alvin1;
2>刪除存儲函數
drop function alvin1;