先介紹下MySQL自帶的一些函數:
結構:sql --> 結果 #作用
以下都是運行結果:
字符串相關函數
select concat('zhou','yi'); --> zhouyi #字符串拼接,可多參數
select concat_ws('&',zhou'','yi'); --> zhou&yi #指定分割符號進行字符串鏈接
# FOMRAT(N,D,locale); N對象,D小數位數,locale可選
select format(2019.011,1); --> 2019.0 #數字格式化
select lower('ZY'); --> zy # 轉小寫;upper 轉大寫
select replace('zhouyibaba','zhouyi',''); --> baba# 替換
SELECT left('chinese', 4); --> chin # 左截取; right(str, len)右截取;substring指定截取
select length('zhouyi'); --> 6 # 返回長度
select char_length("周毅"); --> 2 # 如果是length返回6
select ltrim(' space A'); --> space A #刪除前空格; rtrim刪除後空格;trim 刪除前後空格
select trim(both '?'from '??zY?zy??'); --> zY?zy
select trim(leading '?'from '??zY?zy??'); --> zY?zy??
select trim(trailing '?'from '??zY?zy??'); --> ??zY?zy
判斷子串:
select locate('ho','zhouyi');---> 2 #從字符串zhouyi中獲取ho的開始位置,0代表無
日期時間函數
select now(); --> 2019-12-03 09:11:53 #當前日期和時間
select curdate(); --> 2019-12-03 # 當前日期; curtime()當前時間
SELECT DATE_ADD(now(),INTERVAL 2 DAY); --> 2019-12-05 09:19:48 #向日期添加指定的時間間隔 時間間隔有很多
select DATE_FORMAT(NOW(),'%b %d %Y %h:%i %p'); --> Dec 03 2019 09:15 AM # 時間格式化
數值運算(用的叫少帶過)
div() 整數除法 mod() 取餘數 power() 冪運算 truncate() 數字截取 ceil() 進一取整 floor 舍1取整
以及基本的聚合函數:avg() count() max() min() sum()
1,自定義函數:
創建自定義函數語法格式如下:
CREATE FUNCTION <函數名> ( [ <參數1> <類型1> [ , <參數2> <類型2>] ] … )
RETURNS <類型>
<函數主體>
語法說明如下:
<函數名>:指定自定義函數的名稱。注意,自定義函數不能與存儲過程具有相同的名稱。
<參數><類型>:用於指定自定義函數的參數。這裏的參數只有名稱和類型,不能指定關鍵字 IN、OUT 和 INOUT。
RETURNS<類型>:用於聲明自定義函數返回值的數據類型。其中,<類型>用於指定返回值的數據類型。
<函數主體>:自定義函數的主體部分,也稱函數體。所有在存儲過程中使用的 SQL 語句在自定義函數中同樣適用,包括前面所介紹的局部變量、SET 語句、流程控制語句、遊標等。除此之外,自定義函數體還必須包含一個 RETURN<值> 語句,其中<值>用於指定自定義函數的返回值。
即是:
CREATE FUNCTION function_name
RETURNS
{STRING | INTEGER | REAL | DECIMAL}
Routine_body
刪除自定義函數語法如下:
DROP FUNCTION [ IF EXISTS ] <自定義函數名>
實際舉例:
1,無參數舉例:
mysql> create function getName()
-> returns varchar(45)
-> return
-> (select 'zhouyi');
Query OK, 0 rows affected (0.34 sec)
mysql> select getname();
+-----------+
| getname() |
+-----------+
| zhouyi |
+-----------+
1 row in set (0.11 sec)
mysql>
2,有參數舉例:
mysql> CREATE FUNCTION twoAvg(num1 int,num2 int)
-> RETURNS FLOAT(10,2)
-> RETURN (num1+num2)/2;
Query OK, 0 rows affected (0.00 sec)
mysql> select twoAvg(2,3);
+-------------+
| twoAvg(2,3) |
+-------------+
| 2.50 |
+-------------+
1 row in set (0.12 sec)
mysql>
這裏遺留問題。字符串的操作,嘗試了好幾遍都失敗了。有空看到這一定要裏,一定要補充完整。
更進一步,帶複合結構的函數體。
注意:當使用 DELIMITER 命令時,應該避免使用反斜槓“\”字符,因爲反斜槓是 MySQL 的轉義字符。
定義語法:
DELIMITER //
CREATE FUNCTION function_name(parameter_nametype,[parameter_name type,...])
RETURNS {STRING|INTEGER|REAL}
BEGIN
//body
END
// /* 此處的”//“爲告訴系統函數定義結束 */
當函數體內需要執行的是多條語句時,要使用BEGIN…END語句,複合結構可以包括聲明、循環、控制結構(包括IF語句、CASE語句、LOOP語句、LEAVE語句、ITERATE語句、REPEAT語句和WHILE);且當編寫函數體內容的時候,需要使用DELIMITER關鍵字將分隔符先修改爲別的,否則編寫語句的時候寫到’;’的時候會直接執行,導致函數編寫失敗。
另外還需要了解自定函數內常量和變量定義:
用戶變量:以”@”開始,形式爲”@變量名”。用戶變量跟mysql客戶端是綁定的,設置的變量,只對當前用戶使用的客戶端生效
語法:
set @name = 值;
全局變量:定義時,以如下兩種形式出現,set GLOBAL 變量名 或者 set @@global.變量名,對所有客戶端生效。只有具有super權限纔可以設置全局變量
語法:
set GLOBAL name = 值;
會話變量:只對連接的客戶端有效。
局部變量:作用範圍在begin到end語句塊之間。在該語句塊裏設置的變量。declare語句專門用於定義局部變量。set語句是設置不同類型的變量,包括會話變量和全局變量
局部變量:
變量定義的語法:
DECLARE var_name[,varname]...date_type [DEFAULT VALUE];
爲變量賦值的語法:
SET parameter_name = value[,parameter_name = value...]
SELECT INTO parameter_name
3,複雜一點的自定義函數。
- 自定義隨機生成姓名的自定義函數。
mysql> #自定義開始結束符
mysql> DELIMITER $$
mysql> drop function if exists createRandomName$$
Query OK, 0 rows affected (0.00 sec)
mysql> create function createRandomName()
-> returns varchar(3)
-> begin
-> # 用來存可隨機姓 名 形如LMN
-> declare ln varchar(500);
-> declare mn varchar(500);
-> declare nn varchar(500);
-> # 用來存隨機ln mn nn的長度。char_length
-> declare ln_le int;
-> declare mn_le int;
-> declare nn_le int;
-> # 變量賦值
-> set ln='ABCDEFGH';
-> set mn='IJKLMN';
-> set nn='OPQRYZST';
-> set ln_le=char_length(ln);
-> set mn_le=char_length(mn);
-> set nn_le=char_length(nn);
-> return (concat(substring(ln,ceil(rand()*ln_le),1),
-> substring(mn,ceil(rand()*mn_le),1),substring(nn,ceil(rand()*nn_le),1)));
-> end $$
Query OK, 0 rows affected (0.01 sec)
mysql> DELIMITER ;
mysql> select createRandomName();
+--------------------+
| createRandomName() |
+--------------------+
| EMR |
+--------------------+
1 row in set (0.00 sec)
mysql>
解釋:
#自定義開始結束符
DELIMITER $$
drop function if exists createRandomName$$
create function createRandomName()
returns varchar(3)
begin
# 申明局部變量,用來存可隨機姓 名 形如LMN
declare ln varchar(500);
declare mn varchar(500);
declare nn varchar(500);
# 用來存隨機ln mn nn的長度。char_length
declare ln_le int;
declare mn_le int;
declare nn_le int;
# 變量賦值 ,這裏由於本人創建數據庫時,未指定UTF-8,不能使用。
set ln='ABCDEFGH';
set mn='IJKLMN';
set nn='OPQRYZST';
set ln_le=char_length(ln);
set mn_le=char_length(mn);
set nn_le=char_length(nn);
return (concat(substring(ln,ceil(rand()*ln_le),1),
substring(mn,ceil(rand()*mn_le),1),substring(nn,ceil(rand()*nn_le),1)));
end $$
DELIMITER ;
進一步深入就必須瞭解控制結構,因爲這是學一個東西能實際運用的基礎。
IF語句語法:
IF…END IF爲一組
IF search_condition THEN statement_list
[ELSEIF search_condition THEN statement_list] ...
[ELSE statement_list]
END IF
search_condition表示條件判斷語句;statement_list表示條件成立執行的語句。
CASE語句語法:
CASE...END CASE爲一組
CASE case_value
WHEN when_value THEN statement_list
[WHEN when_value THEN statement_list] ...
[ELSE statement_list]
END CASE
case_value表示條件判斷的變量;when_value表示變量的取值;
statement_list表示不同when_value值執行的語句。
loop語句語法:
[begin_label:] LOOP
statement_list
#LEAVE語句 主要用於跳出整個循環控制
LEAVE begin_label
END LOOP [end_label]
ITERATE語句語法:
ITERATE語句是跳出本次循環,然後直接進入下一次循環。
ITERATE語句只可以出現在LOOP、REPEAT、WHILE語句內
ITERATE label
begin_label和end_label分別表示循環開始和結束的標誌,兩個標誌必須相同,而且都可以省略;
statement_list表示需要循環執行的語句。
while語句語法:
[begin_label:] WHILE search_condition DO
statement_list
END WHILE [end_label]
WHILE循環需要使用END WHILE來結束。
其中,search_condition參數表示循環執行的條件,滿足該條件時循環執行;
repeat語句語法:
[begin_label:] REPEAT
statement_list
UNTIL search_condition
END REPEAT [end_label]
簡單舉個栗子:
判斷員工優秀?
#自定義開始結束符
DELIMITER $$
drop function if exists getGreade$$
create function getGreade(grade int)
returns varchar(10)
begin
declare ret varchar(10);
CASE
WHEN grade=1 THEN SET ret='優秀';
ELSE SET ret='非常優秀';
END CASE ;
return ret;
end $$
DELIMITER ;
# 以;結束
單從邏輯而言,作爲程序員的你理解不難。以上你瞭解,但是這種東西實際中會需要很多問題,主要時sql報錯需要經驗。沒有相關經驗你基本看不出來,而且百度也沒有什麼效果,網上學習課程教的又很淺,我學習這部分花了很大的時間去調通各種代碼問題。且行且珍惜。
2,存儲過程
爲什麼我寫了自定義函數。其實我們可以發現這兩者有很多相似之處。他就是一種爲了方便快捷的一組具有特定功能的SQL語句集組成的可編程的、經編譯創建並保存在數據庫的函數。(**注:**不同的數據庫,語法上存在的差異)。
上面自定函數都可以用到這裏來。
存儲過程的語法:
CREATE
#指定當前用戶
[DEFINER = { user | CURRENT_USER }]
PROCEDURE sp_name ([proc_parameter[,...]])
[characteristic ...] routine_body
( #上面的參數細化
proc_parameter:
[ IN | OUT | INOUT ] param_name type
#上面指定數據庫引擎細化
characteristic:
COMMENT 'string'
| LANGUAGE SQL
| [NOT] DETERMINISTIC
| { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
| SQL SECURITY { DEFINER | INVOKER }
#上面主體細化
routine_body:
Valid SQL routine statement )
[begin_label:] BEGIN
[statement_list]
END [end_label]
IN/OUT/INOUT 字面意思in只做輸入不可改變,out只做輸出可變,inout兩者都可萬能。
刪除及查看存儲過程:
#刪除
drop procedure sp_name;
#查看
show procedure status;/create procedure sp_name;
前期數據表準備:
mysql> create table `grade`(
-> `id` int(11) not null auto_increment primary key,
-> `stu_number` varchar(11) not null,
-> `math` int(4) not null,
-> `chinese` int(4) not null,
-> `english` int(4) not null
-> )engine=innodb default charset=utf8 comment='學生成績表';
Query OK, 0 rows affected (0.76 sec)
mysql> drop table if exists student;
Query OK, 0 rows affected, 1 warning (0.13 sec)
mysql> create table `student`(
-> `id` int(11) not null auto_increment primary key,
-> `stu_number` varchar(11) not null,
-> `stu_name` varchar(12) not null,
-> `class` int(4) not null
-> )engine=innodb default charset=utf8 comment='學生信息表';
Query OK, 0 rows affected (0.15 sec)
mysql> show tables; +-----------------------------+
| Tables_in_activiti_database |
+-----------------------------+
| grade |
| student |
+-----------------------------+
2 rows in set (0.00 sec)
// sql+數據預置
#學生信息表
drop table if exists student;
create table `student`(
`id` int(11) not null auto_increment primary key,
`stu_number` varchar(11) not null,
`stu_name` varchar(12) not null,
`class` int(4) not null
)engine=innodb default charset=utf8 comment='學生信息表';
#學生成績表
drop table if exists grade;
create table `grade`(
`id` int(11) not null auto_increment primary key,
`stu_number` varchar(11) not null,
`math` int(4) not null,
`chinese` int(4) not null,
`english` int(4) not null,
`total` int(5) not null
)engine=innodb default charset=utf8 comment='學生成績表';
insert into student(stu_number,stu_name,class) values
('10000','張一',101),
('10001','張二',101),
('10002','張三',101),
('10003','張四',101),
('10004','張二',102),
('10005','張三',102),
('10006','張四',102);
insert into grade(stu_number,math,chinese,english,total) values
('10000',80,90,101,271),
('10001',82,70,101,253),
('10002',80,60,101,241),
('10003',85,10,101,196),
('10004',80,88,101,269),
('10005',87,77,101,265),
('10006',83,90,101,274);
1,創建一個存儲過程找到前全年級總分最高前三名。
drop procedure if exists getavgthree;
#不帶參數
create procedure getavgthree()
begin
select s.stu_name,s.class from student s left join grade g on s.stu_number=g.stu_number order by total desc limit 3;
end;
2,找到學號最大的學生,將學號存儲到輸出參數。
create procedure getMaxSIDByClass(IN classname int, out maxid varchar(11))
BEGIN
select MAX(stu_number) into maxid from student where class=classname;
END;
當然除了上述查詢,存儲過程更刪改查都是可以的,此外也可以使用存儲過程備份還原數據(簡單來說就是將一張表的數據複製到另一張表)