MySQL學習

.數據庫

數據庫的發展: 文件系統(使用磁盤文件來存儲數據)=>第一代數據庫(出現了網狀模型,層次模型的數據庫)=>第二代數據庫(關系型數據庫和結構化查詢語言)=>新一代數據庫("關系-對象"型數據庫);

層次模型是一種導航結構,
優點:分類管理,如果查詢同一類的數據是很方便的。
缺點:如果查詢很多不是同一類的數據,效率就很低了
層次結構可以造成數據無效,比如張經理管理了一個員工叫張三,李經理也管理了一個叫張三,我們無法區分張三是一個人還是兩個人。

網狀模型解決了層次模型數據無效的問題,但是沒有解決導航問題,深層率查詢,效率很低.

關系模型中,每個表都是獨立的,通過公共字段來建立關系。優點:表是獨立的,需要什么數據就到那個表中查詢。
缺點:多表查詢的時候效率低下。

關系:兩個表的公共字段叫關系

  • SQL語句

Structured Query Language 結構化查詢語言,是用來操作關系型數據庫的.常用的關系型數據有:

Access,MySQL,Sql Server,Oracls.

標準的SQL是所有關系型數據庫都支持的操作語句,標準的SQL也叫作SQL-92.但是每個數據庫在標準的基礎上又擴展了自己的東西.所有,一個數據庫的拓展語句在在其他數據庫不能運行.

  • 連接數據庫

需要的參數: Host (-h),username (-u), password (-p),port(默認3306) (-P)

mysql -u root -h localhost -p
  • 退出數據庫:exit,quit,\q

  • 數據庫操作:數據庫的本質是一個文件.操作數據庫的軟件叫做數據庫管理系統.

/**
*   創建數據庫
*   如果創建的數據庫已經存在,會報錯.所以一般要進行判   斷.
*  同時,如果數據庫名是關鍵字或者純數字,需要加上反引    號,最好的辦法是任何時候都加反引號
*/
Create database db_name [charset=字符編碼]
Create database if not exists db_name [charset=字符編碼]


/** 
*/
2.  查詢數據庫
show database;

3.顯示數據庫的創建語句
show create database create db_name;

4. 更改數據庫
alter database db_name [option];

//eg:alter database haha charset=gbk;

5. 刪除數據庫:如果數據庫不存在會報錯
drop database if exists db_name;

6. 選擇數據庫
    use db_name;
  • 數據庫表的操作

幾個概念:

行row:也叫記錄,一行就是一條記錄

列(column) : 一列就是一個字段,字段也叫屬性,一個表中包含多個字段

1.創建表:(primary key)主鍵不能重復,不能為空,一個表只能有一個主鍵,主鍵可以由多個字段組成.

create table table_name(
    field1 data_type [null | not null][default][auto_increment][primary key],
    field2 data_type,
    ...,
);

2. 查看所有表
show tables;

3.顯示創建表的SQL語句
show create table table_name [\G];

4.顯示表結構
describe [desc] table_name;

5.刪除表
drop tabel table_name1,table_name2,...;

數據類型:

int,decimal(總位數,小數位數) 存小數 decimal(10,3), char(1):定長, varchar(10):可變長度, text:大段文字

  • 數據操作
1.插入數據:插入字段可以和數據庫中字段順序不一致,但是值和插入的字段順序必須一致. 如果插入字段省略掉,插入的值和數據庫表的字段的順序和個數都要一致.

insert into table_name (field1,field2) values (value1,value2);

//自動增長的插入
insert into student values (null,"name","female","shenzhen",22);

//默認值的插入
insert into student values (null,"name","female",default,33);


2.數據的修改
update table_name set field1=value1,field2=value2 [where 條件];

//eg:
update student set gender="male" where name="xiaoming";

update student set gender = "female";

3.刪除數據
delete from table_name [whre 條件];

delete from student where name = "haha";

delete from student;    //所有的數據都刪除了

4 .查詢數據
select 列名 from 表 [where 條件] [order by 排序字段 asc|desc] [limit [起始位置默認0],或者的記錄數量];
升序:asc
降序:desc
默認升序

select name,gender from student;
select * from;  //獲取所有
select * from student order by score desc;
select * from student limit 3;
select * from student limit 2,10;
select * from student order by score desc limit 3;

//取出第一位
select * from stu order by score desc limit 0,1
  • 運算符

比較運算符: > , >=, <, <=, = , <>(不等于)
邏輯運算符: and, or, not

聚合運算:

Sum(), Avg(), Min(), Count(), Max().

select max(score) from student;
select min(score) from student;
select sum(score) from student;
select avg(score) from student;
select count(*) from student;
select count(*) from student where gender="male";

4.PHP與MySQL

  • php開啟MySQL拓展,PHP本身是一個框架,它的功能是由PHP拓展而來的,要通過PHP連接數據庫,必須開啟PHP連接MySQL的功能,就是PHP的MySQL拓展. 在php.ini中,把extension=php_mysql.dll 開啟,重啟服務器.
1.php連接數據庫
$connect = mysql_connect("localhost",'root','password') or die("數據庫連接失敗");
/**
    通過@符號屏蔽信息
    $connect = @mysql_connect("localhost",'root','password') or die("數據庫連接失敗");
*/

2. 終止執行:exit(),和die();
die()停止執行,把生成的代碼發送到客戶端.

3. 選擇數據庫
方法1: 執行 use db_name
mysql_query("use database_name") or die("數據選擇失敗");

方法二:
mysql_select_db("database_name") or die ("數據庫選擇失敗");

4. 設置字符編碼
mysql_query("set names utf8");

5.查詢數據庫 : 返回一個資源類型的數據

$results = mysql_query("select * from products");       //resource type

mysql_fetch_row: 取出結果集中數據
開始匹配,指針指向第一個記錄.取出資源中的當前記錄,匹配成索引數組,指針指向下一條記錄.

5.1.
while($rows = mysql_fetch_row($results)){
    echo $rows[0];
    echo "<br>";
    echo $rows[1];
    echo "<br>";
    echo $rows[2];
    echo "<br>";
    echo $rows[3];
    echo "<br>";
}

這種方法讀取數據缺點:數據庫字段發生變化,會影響數組的索引編碼.


5.2: mysql_fetch_assoc : 形成關聯數組
數組的鍵和數據表的字段名相關聯
while($rows = mysql_fetch_assoc($results)){
    echo $rows["name"];
    echo "<br>";
    echo $rows["gender"];
    echo "<br>";
    echo $rows["age"];
    echo "<br>";
    echo $rows["id"];
    echo "<br>";    
}

5.3: mysql_fetch_object: 匹配成對象,通過->訪問

while($obj=mysql_fetch_object($results)){
    echo $rows->name;
    echo "<br>";
    echo $rows->gender;
    echo "<br>";
    echo $rows->age;
    echo "<br>";
    echo $rows->id;
    echo "<br>";
}


6. 釋放資源 mysql_free_result($results);
7. 關閉連接 mysql_close($connect);

頁面執行完畢后,所有變量全部銷毀,可以不用手動釋放資源.

數據的導入與導出,用phpMyAdmin工具


1月 5日

MySQL 學習

  • 簡介
  1. 數據庫系統: DataBase System = 數據庫管理系統(DBMS,DataBase Management System) + 數據庫 (DataBase) + 管理員(Manager)
    DBS = DBMS + DB;
    對大量信息進行管理的高效解決方案,按照數據結構來組織,存儲和管理數據的庫.

關系型數據庫系統:建立在關系模型上的數據庫系統

關系模型: 日常生活的實體和實體的屬性保存到數據庫時,處理實體結構的方式:
數據結構可以規定,同類數據,結構一致.數據之間的關系可以設置實體之間的聯系.

Nosql: Not only sql,非關系型數據庫
mongoD,MemBase

對象型數據庫.

關系型數據庫的幾個重要概念:

數據庫database:數據的倉庫

表table:數據是保存在表內,保存在一個表內的數據,應該具有相同的數據格式.

行和列:行用于記錄數據,列用于規定數據的格式

MySQL是基于C/S架構的.

  • MySQL常用的操作
(1)數據庫操作

//創建數據庫
create database `db_name` [數據庫選項];

//查詢當前存在的數據庫
show databases;

//查詢數據庫的創建語句
show create database db_name;

//刪除數據庫
drop database db_name;

//修改數據庫信息
alter database db_name [修改指令];
alter database db_class character set utf8;

//修改數據庫的名字
1.直接修改文件夾的目錄名
2.將數據全部導出,新建一個數據庫,再導入數據,刪除舊數據庫
3.新建數據庫,把就數據庫的表移到新數據庫,刪除就數據庫

(2)表操作

可以通過.(點)語法,指明數據表所屬的數據庫
create table `db_name`.`table_name`(
    field1 type,
    field2 type
);

use db_name 只是設定了默認數據庫,不影響操作其它數據庫.選擇了默認數據庫,只會影響默認行為.可以操作任意的數據庫

//創建表
create table info_student(
    `name` varchar(20),
    `stu_no` varchar(20)
);

//查看表
show tables [like 'pattern'];like pattern部分表示獲得規定規則的表名. % 為通配符,表示任意字符的任意組合.同樣適用于數據庫查詢:
show databses like 'pattern';

//查看表的結構
describe(desc) table_name;

//刪除表
drop table [if exists] table_name;
drop database [if exists] database_name;

//修改表名
rename table old_table_name to new_table_name;

//同時修改多個
rename table tb1 to new_tb1,tb2 to new_tb2;

//支持跨數據庫重命名
//可以利用這個操作為數據庫重命名: 創建一個新的數據庫,舊數據內的表,都rename到新的數據庫.刪除舊的數據庫.

rename table exam_user to `db_name`.table_name;

//修改列的定義
alter table tb_name [add | drop | change | modify]

//增加一個新列
alter table table_name add filed_name type;

//刪除一個列
alter table tb_name drop field;

//修改一個列的定義
alter table tb_name modify field varchar(90);

//重命名一個列
alter table table_name change old_field new_field type;

//修改表選項
alter table table_name character set utf8;

(3)數據操作
//創建數據(插入數據)
insert into table_name (fields) values (value1,...);

insert into student (name,id) values (`name`,`09332`);

//獲取數據(查詢數據)
select fields(*) from table_name condition;

select * from students;
select name,id from students where 1;
select * from students where score>=80;

//刪除數據
delete from table_name condition;

delete from students where score<=20;

//修改數據
update table_name set field1 = value1,... condition;

update students set score = 90 where id = 0922;

  • SQL

Structured Query Language:結構化查詢語言;

針對操作對象不同,分成不同語言:

1.數據操作(管理)語言.DML;
查詢,獲得數據.DQL;
管理,增加,刪除,修改數據.DML

2.數據定義語言(對保存的數據的格式進行定義) DDL;

3.數據庫控制語言 (針對數據庫軟件服務進行操作) DCL;

  • 字符集

字符的集合;構成分兩部分:1.字符的集合,展示用,2.字符的編碼,保存和處理.

MySQL支持常見的字符集,查看: show character set;

字符集決定的是字段的數據以何種形式保存.
如果通過客戶端操作服務器,那么客戶端和服務器端之間進行數據通信,要保證編碼一致.可以將互相發送的數據,轉換成目標可以接收的編碼數據.

通過MySQL配置:

character_ser_client 客戶端發送數據編碼

character_ser_results 客戶端接收數據的編碼

通過指令 show variables like 'character_set_%';查看當前的字符編碼集

設置變量: set 變量名=值;

set character_set_client = utf8;告知服務器,客戶端發送的數據是utf8編碼;

如果需要從服務器返回數據,還需要設置服務器發送給客戶端的編碼:set character_set_results = utf8;服務器在發送數據時,才能轉成客戶端認識的編碼;
對于普通的簡單項目統一的操作可以使用 set names utf8;完成設置

連接層編碼: set character_set_connection = utf8;

set names 操作可以同時設置客戶端接收的數據格式,客戶端發送的數據格式,連接層編碼三個.

數據編碼轉換過程: client->connection->[服務器內部編碼]->results

  • MySQL數據類型

1.整型

類型 字節 最小值(有符號/無符號) 最大值(有符號/無符號)
tinyint 1 -128 / 0 127/255
smallint 2 -32768 / 0 32767/65535
mediumint 3 -838808 / 0 83888607/1777215
int/integer 4 -2147483648 / 0 2147483647/4294967295
bigint 8 -922337203685477580/ 0 922337203685477580/8446744073709551615

在定義字段時,可以使用unsigned標示無符號,默認為有符號.

create table tbl_int(
    a tinyint unsigned,
    b tinyint
);

定義顯示寬度:通過規定數據的顯示寬度,達到統一顯示的目的. 類型(M) ,M表示顯示的最小寬度是多少. 如果需要用前導零值填充,使用 zerofill;不會影響數的范圍,寬度大的不影響,不會截取;

alter table tbl_int add c tinyint(2) zerofill;
insert into tbl_int values (0,123,2);

2.浮點數

float 單精度,默認精度位數為6位;

double 雙精度,默認16位

控制數值的范圍 Type(M,D),D表示所有的數值的位數(不包括小數點和符號);
D表示小數位數;

支持科學計數法: 1.322*10^3;

3.定點數

decimal(M,D);M總位數,D小數位數,M默認10,D默認0

小數也支持zerofill和unsigned


create table number1(
    send_money decimal(10,2) zerofill;
);
insert into number1 values (123.43);
insert into number1 values (122332.564);

  1. 日期和時間

DateTime 年月日時分秒

Timestamp 時間戳,存儲時整型,表示時,日期時間

Date 年月日

支持0值:表示當前沒有規定 2015-04-0 表示4月整個月.

insert into dt_1 values (0,0);

Time 類型: 1,表示一天中的時間 2,時間間隔,在表示時間間隔時,可以用天表示 格式: DHH:MM:SS

create table tb_1(
    ago time
);

insert into tb_1 values ('4 21:22:11');
insert into tb_1 values ('23:22:11');
insert into tb_1 values ('232211');

Year:此時表示日期的范圍,不是1000-9999
而是 1901-2155 一個字節(256間隔)

在實際項目中,通常保存的都是Unix時間戳,直接用整型保存在數據庫,不是MySQL提供的timestamp類型;

  • 字符串類型

char(M): 固定長度

varchar(M): 可變長度

M在varchar中表示允許的最大長度,char內表示嚴格限定的長度

char(5) varchar(5)
'' 5個字符 一個字節 varchar需要一個字節保存字符串總長度
'abc' 5 4
'abcdf' 5 6
'abcdefg'

M表示的是字節,而不是字節數,但是總的長度的使用時按照字節計算的

create table tb_2(
    a varchar(65535)        //會報錯,最大長度是21845, 三個字節21845 * 3 = 65535
);

create table tb_3(
    a varchar(65535)
) character set gbk;  //報錯,最大長度是32767,2個字節 2 * 32767 = 65535

字段的最大長度除了類型本身之外,記錄的總長度也是有限制的.

真實的varchar長度:

記錄存在總長度65535限制

特點:當類型數據超過255個字符時,采用2個字節表示長度 65535-2 = 65533

整條記錄,需要一個額外的字節,用于保存當前字段的null值.除非所有的字段都不是null,這個字節才可以忽略.一個記錄,不論有多少個字段存在null,都是使用統一的一個字節表示.而不是每個字段一個字節

Text類型: 2 ^ 16,文本類型,tinytext,longtext;

枚舉 enum

值是否能為空: null || notnull,如果為not null,在插入時,缺少值,會插入失敗;

默認值屬性: default value來聲明. 在沒有為該字段設置值時啟用,而且默認值的設置,需要使用固定值;

常見的是一個字段不能為空,而且存在默認值;

create table tb_3(
    a int not null default 10,
    b int not null default 2
);

insert into tb_3 (a) values (1);
insert into tb_3 (b) values (22);

主鍵pk,primary key:

可以唯一標示,某條記錄的字段或者是字段的集合,就是主鍵.主鍵可以是真實實體的屬性.常用的是使用一個與實體信息不相關的屬性作為唯一標識.主鍵與業務邏輯不發生關系,只是用來標識記錄.

1.字段上設置:主鍵字段在插入時不能為空,或者沖突

create table reacher(
    t_id int primary key,
    t_name varchar(5);
    class_name varchar (6);
    days tinyint unsigned
);

2.在定義完字段后,可以定義多列主鍵(組合主鍵):一個主鍵內包含多個字段,而不是多個字段的主鍵.只需要一個唯一標識即可,MySQL規定只能存在一個主鍵;
常見的主鍵設計,每個表都應該存在一個可以唯一標識的主鍵字段,最好與實體沒有關系,不是實體屬性字段.

create table teacher(
    t_name varchar(5),
    class_name varchar(6),
    days tinyint unsigned,
    primary key(t_name,class_name);
);


字段增長:auto_increment,自動增長的默認值是1,可以設置
如果插入的值小于已經存在的主鍵的值,是可以的,如果是主鍵,不能重復;

實體之間的關系:

1vs1:
兩個實體表內,存在相同的主鍵字段.如果記錄的主鍵值等于另一個關系表內的主鍵值,則兩條記錄一一對應;

1 vs n
:一個實體對應多個其它實體;例如,一個班級對應多個學生

在多的那端,增加一個字段,用于指向改實體所屬的另外實體的標識

M:N 多對多

典型的,利用一個中間表,標識實體之間的對應關系.中間表的每個記錄,標識一個關系

一個M:N,
1:M,1:N來實現

講師主鍵 名字 班級
1 joe
2 jack
班級主鍵 班級名 講師主鍵
29 0234
30 0907
講師主鍵 班級主鍵
1 29
3 29
  • 外鍵 foreign key

:如果一個實體(student)的某個字段(class_id)指向(引用)另外一個實體(class)的主鍵(class_id),就稱student實體的class_id是外鍵.被指向的實體,稱之為主實體(主表,父實體),對應的另外一個實體稱之為從實體(從表,子實體,子表)

外鍵的作用: 保證數據的完整性,用于約束處于關系的內的實體.增加子表記錄的時候,是否有與之對應的父表記錄.在刪除或者更新的主表記錄時,從表應該如何處理相關的記錄.

//定義一個外鍵
在從表上在,增加一個外鍵字段,指向主表的主鍵.使用關鍵字foreign key;
foreign key (外鍵字段) references 主表名 (關聯字段)[主表記錄刪除時的動作][主表記錄更新時的動作];

drop table if eixsts class;
create table class (
    class_id int primary key auto_increment,
    class_name varchar(10) not null default `php` comment `班級名稱`
)character set utf8;

drop table if exists student;
create table student(
    stu_id int primary key auto_increment,
    stu_name varchar(10) not null default ``,
    class_id int,
    foreign key (class_id) references class (class_id)
) character set utf8;

設置級聯操作:
在主表數據發生改變時,與之關聯的從表數據應該如何處理:
主表更新:on update,主表刪除 on delete

允許的聯級操作,cascade:關聯操作,如果主表被更新或者刪除,那么從表也會執行相應的操作.set null:設置為null,表示從表不指向任何主表記錄,restrict:拒絕主表的相關操作

修改外鍵:先刪除,再新建.通過修改表完成
alter table_name drop foreign key field;
刪除外鍵需要通過指定外鍵名稱達到目的,可以在創建外鍵時,指定名稱或者使用MySQL默認生成的名稱;

alter table student drop foreign key class_id;

//增加外鍵
alter table student add foreign key (class_id) references class (class_id) on delete set null; //刪除時,將從表外鍵,設置為null;

alter table student add foreign key (class_id) references class (class_id) on delete cascade; //刪除時,將從表外鍵刪除; 

alter table student add foreign key (class_id) references class (class_id) on delete cascade on update restrict; //刪除時,將從表外鍵上刪除,更新時拒絕更新;

  • 數據庫存儲引擎

默認的服務器表類型,通過mu.ini可以配置:default-storeage-engine=INNODB

在創建表時,或者編輯表時,可以指定表的存儲引擎

alter table class engine myisam;

create table room(
    room_id int primary key auto_increment,
    room_no char(3)
)engine myisam character set utf8;

innodb和myisam區別

保存的文件的方式不同:
myisam,一個表,三個文件
Tbl_name.frm 結構 (frame)
Tbl_name.myd 數據 (data)
Tbl_name.myi 索引 (index)

innodb:
一個表一個文件:
Tbl_name.frm 結構

所有的innodb表,都使用相同的innodb存儲空間在保存數據和索引;

選擇存儲引擎的依據: 1 功能, 2 性能

特點 Myisam InnoDB BDB Memory Archive
事務安全 支持 支持
全文索引 支持 5.5版本支持
鎖機制 表鎖 行鎖 頁鎖 表鎖 行鎖
存儲限制 沒有 64TB 沒有 沒有
B樹索引 支持 支持 支持 支持
哈希索引 支持 支持
集群索引 支持
數據緩存 支持 支持
索引緩存 支持 支持 支持
數據可壓縮 支持 支持
空間使用 N/A 非常低
內存使用 中等
支持外鍵 支持

innoDB&Myisam:

數據和索引的保存的文件不同: Myisam是分開保存的,innoDB是保存到表空間

Myisam支持索引壓縮,而innoDB索引和數據是綁定保存不壓縮,體積大;

innoDB很多時候是行級鎖,而myisam是表級鎖,innodb的并發高;

innodb不支持fulltext類型的索引(新的版本的innodb支持);

innodb支持事務,外鍵,數據的完整性約束要強,二myisam不支持.

innodb中不保存表的具體行數,所以在執行 select count(*) from table_name 時,innodb要掃描一遍整個表來計算有多少行,但myisam只需要簡單的讀取保存好的行數即可.注意的是,當count(*)語句包含where時,兩種表的操作是一樣的;
對于auto_increment類型的字段,innodb中必須包含只有該字段的索引,但是在myisam中,可以和其它字段一起建立聯合.

  • 范式 (Normal Form)

用于規范表的設計的一套原則體系.

規范表的結構:

體系:1NF,2NF,3NF,4NF...

1NF:

要求: 表,所有的列(屬性),不能再分,具有原子性.通常認為,不符合第一范式的表,不具有關系模型的定義;

2NF:

滿足第一個范式的基礎上.
要求:每一行(記錄)必須能夠唯一標識.同時要求:不存在非主鍵字段,不能對主鍵有部分函數依賴.(在組合鍵前提下,表中非主鍵字段,有依賴于組合主鍵內的個別字段依賴的情況). 比如:非主鍵關鍵字(教室號碼),依賴主鍵內的部分字段(班級id),非主鍵關鍵字(教師性別),依賴于主關鍵字內部分字段(教師)

解決方案:常用方案是增加一個單子段主鍵即可,可以保證唯一標識,而且也不能形成部分函數依賴(一個獨立的字段)

3NF:

不錯出現傳遞依賴:不能出現 A->B->C
這樣的結構,如果出現,就說C傳遞依賴A

實體上表示,一個關系(二維表),只能保持一個實體的信息,不能保存多個信息

通用原則:
1,每個實體一個表(可以采取常用信息和詳細信息分開保存的思路)
2,為一個關系(二維表)增加,一個邏輯主鍵(不屬于真實實體屬性的字段),用于做標識。
3,出現二維表對應的關系,采用1:1, 1:N, M:n的形式
將關聯關系設計。
注意:
實際的開發中,常常會為了操作方便,編碼容易,做一些逆規范化的事情。
例如,每次得到授課信息時,都需要得到教室號。如果不做逆規范話,每次都
需要2個表內獲得數據。可以考慮,將教室號,放入到 代課信息內。查詢容易,編碼簡單。

  • 校對規則

每一套編碼字符集都有與之相關的校對規則.即,在當前編碼規則下,字符間的比較規則,順序;

每個字符集都支持不定數量的校對規則,可以通過指令:show collation 查看字符集地區名比較規則(ci,cs,bin)(不區分大小寫,區分大小寫,字節比較)

show collation like `gbk%`;

在設置字符集的時候,可以設置當前字符集所采用的校對規則,如果不設置校對規則,那么每個字符集都有一個默認的校對規則;

以gbk為例子,比較chinese_ci bin 之間的區別,一個chinese_ci,一個chinese_bin,插入相同的數據:

當使用order by 進行排序時,數據會按照某個字段進行排序.由于排序規則不同,排序會不一致

character set gbk collate gbk_chinese_ci;
character set gbk collate gbk_bin;

select * from tb_3 order by name;
select * from tb_4 order by name;

  • 查詢語句 select

select語法: select [查詢選項][查詢表達式(字段)] [from 子句][where 子句][having 子句][order by 子句][limit 子句];

要求子句可以不出現.如果出現,要求必須按照順序書寫;

表達式:字段,值,返回值的語句,函數的返回值

列子句

select id+10,concat(t_name,'-',gender),c_name from teacher_class;
//concat字符串拼接函數,字段可以作為參數,也可以進行加法運算

別名: 通常一個表達式,形式不夠好,不容易讀取,起一個可以容易讀取的別名即可:

使用關鍵字 as: 標識符 [as] 別名;as可以省略,建議保留

from子句:表示查詢的目標數據源,通常情況下是表名,表名也支持別名

select * from teacher_class,num_2;

表名也是一個列表:如果沒有任何條件的兩個表名,會得到表1乘表2的所有數據.交叉連接,笛卡爾積;

from可以省略,但是有些數據庫不支持,MySQL支持;使用dual作為虛擬表存在

select now() from dual;

where 子句:

用于通過條件過濾數據,得到真實的結果;

MySQL支持的操作符:邏輯運算符和關系運算符
=,>,<,>=,<=.!= (<>)

字符串匹配運算符:like 可以利用通配符,完成模糊匹配

通配符: _ 匹配一個字符,%匹配多個任意字符,%匹配%,_匹配_

判斷某個值是否為null: is null, is not null;
isnull()結構可以判斷null值;

<=>功能與 = 一致,特別的功能在于可以比較null值

select null is not null,null is null;
select null<=>null, 10 <=> null;

between and:

between valueA and valueB:范圍取值

范圍比較,閉區間: valuesA<=expr<=valueB;

select * from teacher_class where id between 3 and 5; //3,4,5三個id的值

select * from teacher_class where id in (3,5)  //兩個值,3,5

in| not in:集合之內(外);
in| not in(集合元素);

.interval:

獲得一個集合元素的集合:interval(值A,元素1,元素2....);
一次判斷值與元素之間的大小,如果值A小于元素1,則返回0;如果值A小于元素2,則返回1,依次類推;

select t_name ,days,interval(days,10,20,30) from teacher_class where interval(days,10,20,30) = 1;

邏輯運算符: And && ,Or ||, Not ! ;

null值的特殊性: not null,! null 為null

異或:xor ,有null就是null

. group by:分組聚合查詢語句:通過列內,不同的值,完成數據統計;

分組的目錄,通常是組內統計:統計是通過MySQL的統計函數完成的;

sum()計算所有表達式的和

select t_name,sum(days) from teacher_class where 1 group by t_name; //所有老師的上課天數

select c_name, sum(days) as sum_days from teacher_class where 1 group by c_name; //所有班級的上課天數

如果合計函數的使用,沒有與group by配合,統計所有的數據,將所有的數據當作一組.

select sum(days) from teacher_class where 1;

排序group by:會通過排序字段,為數據進行重新排序,默認升序(asc)

select t_name,sum(days) from teacher_class where 1 group by t_name [asc | desc];

group by 多字段分組:

select t_name,c_name,sum(days) from teacher_class where 1 group by t_name,c_name; 類似多字段主鍵,使用組合的字段進行標識;

. rollup:在使用多字段分組時,通常需要做上級統計:

select t_name,c_name,sum(days) from teacher_class where 1 group by t_name,c_name with rollup;

使用 with rollup ,可以相當于利用組合條進行統計后,
再使用上一條件再次統計一次。
注意,會統計到 沒有分組的情況,整個都是一組的情況

是否可以得到 大于某些代課天數的講師信息?
select t_name, sum(days) from teacher_class where sum(days)>50 group by t_name;

分析發現:
where先執行,group by 后執行。
Sum()在計算的時候,沒有分組的呢

無法在在where內使用合計函數:
需要一個,可以在結果內,再次過濾的功能:
having

slect t_name,sum(days) from teacher_class where days > 10 group by t_name; //where會影響group的統計,說明where執行在前;

. having :負責在結果(where查詢到的)中進行再次過濾,可以像使用where一樣,having進行處理;

select t_name,sum(days) from teacher_class where 1 group by t_name having sum(days) > 50;
  • 聚合函數

Sum(),Avg(),Max(),Min(),Count()

Count():統計總的記錄數,統計的是非null的記錄數,通常用count(*)來統計.

group_concat(): 組內字符串連接,做了分組,只能顯示組內信息.如果需要對其它列進行顯示,可以把結果連起來;

  • order by

校對規則,決定排序關系;按照字段值進行排序,order by 字段 asc | desc;
默認升序asc;

允許多字段排序:先按照第一個字段排序,如果說,不能區分,才使用第二個字段,依次類推

select * from teacher_class order by days;
select * from teacher_class order by days ddesc;
select * from teacher_class order by days desc,begin_date desc,edn_date asc;

如果是分組,應該用對應字段group by,進行排序的group by語法.

. limit

限制獲得的記錄數量;
limit offset,row_count;
;offset偏移量,默認從零開始,0可省略,row_count要取的記錄數,不足,全部取了;

select * from teacher_class limit 3,5;
select * from teacher_class limit 5;

. distinct: 去除重復記錄

重復的記錄指的是字段值,都相同的記錄,而不是部分字段相同的記錄

相對的是all,表示所有.默認就是all行為.

select days from teacher_class;
select distinct days from teacher_class;
selct days,begin_date from teacher_class;
select distinct days,begin_date from teacher_class;

聯合查詢:

將多條select語句的結果,合并到以前,稱為聯合操作.

使用的場景: 獲得數據的條件,出現邏輯沖突,或者很難在一個邏輯內表示,可以拆分多個邏輯,分別實現,最后吧結果合并到一起.

//獲取兩個不同班級上課天數最多的老師
(select t_name,days,from teacher_class where c_name='1234' order by days desc limit 1) union (select t_name,days,from teacher_class where c_name='2221' order by days desc limit 1)

union all:環境

如果union的結果存在重復的記錄,會自動消除重復.如果不想消除重復,使用union all達到目的.

(select t_name,days,from teacher_class where c_name='1234' order by days limit 10) union all
(select t_name,days,from teacher_class where c_name='2221' order by days desc limit 10)

排序:子語句結果的排序,1 . 將子句包裹在括號內, 2. 子語句的order by 只有在order by配合limit時才生效.union在做子語句時,會對沒有limit的子語句優化(忽略)

(select t_name,days,from teacher_class where c_name='1234' order by days) union all   //沒有limit,結果無序的
(select t_name,days,from teacher_class where c_name='2221' order by days desc limit 10)

如果要對所有結果進行排序,只需要在最后一個select語句后進行排序.

(select t_name,days,from teacher_class where c_name='1234') union all
(select t_name,days,from teacher_class where c_name='2221') order by days desc;  //括號不是必須的,但提高了可讀性

多個select語句的檢索到的字段數,必須一致.更加嚴格的是,數據類型上也要一致.MySQL內部會做類型轉換,前提是能夠轉換成功. 檢索結果中列的名稱是根據第一條select語句決定的.

  • 子查詢:語句內部的查詢語句,就是子語句查詢

如果一個表內,有多個相同的結果時取數據的思路: 比如并列第一的情況

select t_name,gender from teacher_class order by days limit 1;

//方案:先獲取條件數,作為判斷依據變量,這是SQL支持的
var1 = select max(days) from teacher_class;
select t_name,gender from teacher_class where days=var1;


//select t_name,gender from teacher_class where days=(select max(days) from teacher_class);

子查詢分類: 分類的依據: 出現的位置和返回值的形式

返回值分類:
單一值,一列,多列,表(多行,多列)

出現的位置:
where 型,where 后

from型:from 后

exists 型

集合運算符:in,not in, any, all , !=all(not in)

返回一行:

在參與比較時,使用括號可以構建一行:

(filed1, field2) 
select t_name, gender, c_name from teacher_class where (gender, c_name) = (select distinct gender, c_name from teacher_class where t_name='李白' and c_name='0115' limit 1); 

返回一個表:

如果用于在from子句內,from子句內,要求使用一個表,是一個結果.
應該給這個結果起個名稱,別名.

select * from (select t_name,c_name,days from teacher_class where days > 15) as temp_name where t_name like '李%';

exists(subquery):如果子查詢的可以返回數據,則認為exists表達式返回真. 否則返回假;

//這兩個語句完成的是同樣的語句
select * from teacher_class where exists(select * from teacher where teacher_class.id=t_id);

select * from teacher_class where id in (select t_id from teacher);

//兩個語句的思路

exists:先獲得每一條teacher_class的數據,然后獲得ID字段,去teacher 表內查詢對應值,找到.

in:先找到所有的ID 的可能性.再在檢索teacher_class數據時,判斷當前的id是否在id集合內.

  • join

每一個實體,每一個表,一個業務邏輯,使用多個實體的數據,多張表應該在一起使用,將多個表的記錄連接起來.

總體的思路:將所有的數據,按照某種條件,連接起來,在進行篩選處理.

連接的分類: 內連接,外連接,自然連接

//內連接:數據內部的連接,要求連接的多個數據必須存在才能進行連接
select join_teacher.t_name,join_teacher_class.begin_date,join_teacher_class.days from join_teacher inner join join_teacher_class on join_teacher.id=join_teacher_class.t_id;


//外連接:如果負責連接的一個或者多個數據不真實存在,則稱之為外鏈接.
select join_teacher.t_name,join_teacher_class.begin_date,join_teacher_class.days from join_teacher left outer join join_teacher_class on join_teacher.id=join_teacher_class.t_id;

內連接的處理:
內連接,在連接時,是可以省略連接條件的.意味著所有的左表的數據都要與右表的記錄做一個連接,共存M*N個連接.這種連接稱為交叉連接或者笛卡爾積;

select join_teacher.t_name,join_teacher_class.begin_date,join_teacher_class.days from join_teacher inner join join_teacher_class;

join_teacher.t_name,join_teacher_class.begin_date,join_teacher_class.days from join_teacher cross join join_teacher_class;

join_teacher.t_name,join_teacher_class.begin_date,join_teacher_class.days from join_teacher join join_teacher_class;

此時,可以用cross join 代替inner join.可以通過多表查詢,不使用where做到笛卡爾積.

在MySQL中cross join和inner join相同,但在數據庫的定義上,交叉連接就是笛卡爾積.是沒有條件的inner join.MySQL inner join是默認的連接方案,可以省略join

. 有條件的內連接: 會在連接時過濾掉非法的連接.

where的寫法:在數據過濾上,數據交叉連接完成后,再做數據過濾.

on的寫法:在連接時,就對數據進行判斷;

using的寫法:using要求,負責連接的兩個實體之間的字段名稱一致.

建議在有同名字段時用using,而在通用的條件時,用on.在數據過濾時(不是指連接過濾)使用where.

查詢條件,與外鏈接通用(外鏈接,不能使用where作為連接條件)

//后面再補充


  • select

將檢索到的數據,保存到服務器的文件內.可以自動創建文件,但是不能重寫已經存在的文件,否則報錯;

生成的文件格式:
默認的,采用行來區分記錄,而采用制表符,來區分字

為了滿足某種特別的需求,會采用不同的分割方式。
支持,在導出數據時,設置記錄,與字段的分割符。

通過如下的選項:

fields:設置字段選項
Lines: 設置行選項(記錄選項)

先看默認值:

字段:fields terminated by '\t' enclosed by '' escaped by '\‘

記錄:lines terminated by '\n' starting by ''

可以自己設定

select * into outfile 'e:/amp/three'

fields terminated by ','

lines terminated by '\n' starting by 'start:'
from teacher_class where t_name = '韓信';

select * into outfile 'e:/amp/four'
fields terminated by '\t' enclosed by 'x'
lines terminated by '\n' starting by 'start:'
from teacher_class where t_name = 'jjj';

注意:
常規的,所有的記錄,應該通過行來顯示
例外是保存二進制數據:

//
select * into outfile '/usr/application/www' from table_name where name = "jjj";

Blob binary

使用 into dumpfile

select * into dumpfile 'e:/amp/six' from teacher_class where t_name = 'jjj' limit 1;
  • 新增數據Insert&replace&loaddata

Insert into tbl_name (字段列表)values (值列表)

可以不將所有的字段都插入數據。
如果說需要完成部分字段的插入,需要必須存在 字段列表

沒有插入的字段,使用默認值:
insert into teacher_class (t_name) values ('張三豐');

如果是插入部分字段, 可以使用下面的set語句:
insert into teacher_class set t_name='張無忌';
insert into teacher_class set t_name='趙敏', c_name='武術';

值列表的語法,可以一次性插入多條數據:
每條數據采用記錄構造符 括號完成即可:
insert into teacher_class (t_name, c_name) values
('張君寶', '太極'),
('楊過', '黯然銷魂掌');

插入數據時,如果主鍵沖突會如何?

默認有 主鍵約束,不會插入成功
但是可以在insert語法內,控制
在主鍵沖突時,改成執行更新操作。

Update 后 不跟 set。

insert into teacher_class (id, t_name, c_name) values
(13, '楊露嬋', '太極')
on duplicate key update
t_name='楊露嬋', c_name='太極'
;

插入的數據源:

除了使用自定義數據外,
還可以是使用 select 語句
查詢到數據,作為插入的數據源。

insert into teacher_class (t_name, c_name) select t_name, c_name from teacher_class;

數據可以來源于其他數據表,要求,字段數量和類型一致即可:

insert into teacher_class (t_name, c_name) select t_name, class_name from teacher;

通過強制使用 default關鍵字,或者default()函數,使用默認值;
insert into teacher values
(13, 'xxx', 'yyy', default),
(14, 'xxx', 'yyy', default(days))
;

Replace

主鍵或唯一索引沖突,則替換
否則插入。
replace into teacher values
(1, '韓非', '法家', 30);

replace into teacher values
(15, '韓非', '法家', 30);

Load data infile "file" into table tbl_name;

導入 select * into outfile 'file' 命令
導出的內容;
上面兩個命令 互補。

注意:
導入時,涉及到數據增加,需要考慮,
是否沖突的情況。

通常,可以在導出時,將主鍵導出成null。
利用自動增長的特性。可以形成新的主鍵:

同樣:
在導入數據時,需要同樣指定數據的分割,
起止符號等。
保證 導出數據的格式與導入數據需要的格式
是一致的即可

刪除數據:Delete

允許使用條件(刪除符合條件的數據)

允許使用 limit :
限制刪除的記錄數。
Limit N;

常見的是
Limit 配合 order by來使用:
先將結果排序,再刪除固定數量的記錄:
delete from teacher order by days limit 10;
只有 order by 是沒有意義的
;

允許連接刪除:允許使用類似join的語法,同時刪除多個表內的記錄;需要先提供表名,再提供連接條件;可以拆分成 delete one,deletetwo...

delete from one,two using one join two on one.public_field=two.public_field where one_id=2;

清空表:truncate

類似delete from table;

truncate teacher;

truncate:不會返回刪除的記錄數. 會重建自動增長的主鍵

delete逐行刪除
,truncate刪除表,新建表

  • 更新數據

replace,insert onduplicate key update

update where order by limit;

多表更新:

update one join two on one.public_field=two.public_field set one_data='x',two_data='y' where one_id = 3;

  • 備份還原

方案1:
適用于 mysiam表:

直接將 tbl_name.frm
Tbl_name.myd
Tbl_name.myi
三個文件,保存,備份即可。

需要的時候,直接解壓到移動
到相應的數據庫目錄內即可

注意,如果是同樣的方法,處理的
innodb表結構的文件。
則使用showtables時,也可以看到
但是不能使用的;

方案2:
通用的方案:
思路是:將建表結構,與插入數據的sql語句生成并保存,下次如果需要該結構和數據
直接將數據語句 執行即可。

利用 mysql提供的工具完成的:
不是sql語言的一部分。

不需要在 mysql命令行客戶端執行,
直接運行即可。

將備份的數據庫還原:
就是將剛剛生成的sql語句,執行即可;

將備份的數據庫還原:

就是將剛剛生成的sql語句,執行即可。

在mysql客戶端,直接執行即可:
如何執行 保存在文件內的sql語句:
使用 source 指令,可以指定需要執行sql語句的源代碼文件:

常用的備份操作:
1,備份整個數據內的表:
Mysqldump -uroot -p db_name > bak.sql

2,備份數據庫內的某張表:
mysqldump -uroot -p php_one teacher_class > e:/php_one_teacher_class.sql
mysqldump -uroot -p php_one teacher_class tbl_name1 tbl_name2 tbl_name3 > e:/php_one_teacher_class.sql

  • 視圖

創建視圖:

Create view view_name
AS select_statement;

create view v_teacher as select id,t_name from info_teacher;

視圖就是一個存在與數據庫中的虛擬表了;視圖,本身沒有數據,只是通過執行相應的select語句完成獲得相應的數據。

視圖管理

刪除視圖:
Drop view [if exists] view_name;

修改視圖:
Alter view view_name

修改視圖內,所使用的字段的名稱:
視圖名稱后,使用 (字段列表即可)

縮減業務邏輯:
通過視圖還可以,使復雜的業務邏輯,簡單的完成,先使用視圖完成一定的邏輯,在在視圖的基礎上,完成另外的邏輯。
通常,視圖完成的邏輯,都是相對來說比較基礎的邏輯。

create view join_info as select tc.id as tc_id, t_name, c_name, days from join_teacher_class as tc left join join_teacher as t on tc.t_id=t.id left join join_class as c on tc.c_id=c.id;
 
select * from join_info;

視圖的執行過程:
視圖的執行算法:

存在兩種執行算法:
1,merge
2,temptable

指的是一個視圖是在什么
時候執行,依據哪些方式執行:

merge:合并的執行方式,每當執行的時候,現將我們視圖的sql語句
與外部查詢視圖的sql語句,混合在一起。最終執行:

Temptable:臨時表,模式,每當查詢的時候,將視圖所使用select語句
生成一個結果的臨時表。再在當前的臨時表內進行查詢。

當用戶創建視圖時,mysql默認使用一種 undefine的處理算法:就是會自動在
合并和臨時表內進行選擇。

  • 事務

一組sql語句操作單元。
組內所有sql語句完成一個業務。
如果整組成功:意味著全部sql都實現
如果其中任何一個失敗。意味著整個操作都失敗。
失敗,意味著整個過程都是沒有意義的。應該
是數據庫回到 操作前的初始狀態。

上面的特性,就是事務。

如何處理?

1,失敗后,可以回到開始位置
2,沒都成功之前,別的用戶(進程,會話)是不能看到
操作內的數據修改的。

思路:就是在 一組操作之間,設計一個記號,備份點。

實現:
利用 innodb存儲引擎的,事務日志功能:

SQL執行分成2個階段:1,執行階段 2,將執行結果,提交的數據庫的階段;

其中,我們的事務日志,就是保存執行階段的結果.如果用于選擇提交,則才將執行的結果提交到數據庫;默認的執行方式叫自動提交,執行完畢,自動完成提交,因此.
需要關閉自動提交功能.

自動提交
存在一個系統的變量,
Autocommit 可以對自動提交進行配置

show variables like autocommit;

關閉后,再次執行相應的更新語句:
發現,在其他連接中,查看數據,
沒有發生變化,因為結果沒有提交.

提交或回滾。

在此基礎上,執行完所有的sql語句。

判斷是否都成功(出現錯誤,包括語法錯誤,和邏輯錯誤
服務器錯誤)。

成:將結果提交
利用 commit

敗:回到開始位置。
Rollback

常見的事務的指令:
開啟事務
Start transaction; 可以使用begin。
關閉自動提交。如果事務結束了,
成或敗,都會將自動提交機制,回到start時的狀態。

成功:commit;
失敗:rollback;

限定:
在innodb下生效(DBD)

事務的特點:
1,原子性。
2,一致性。
3,隔離性。
4,持久性。
ACID。

  • 觸發器

監聽數據進行操作:在當前的表上,設置一個對每行數據的一個監聽器,監聽相關事件,每當事件發生時.會執行一段有SQL完成的一段功能代碼;

觸發器的元素:事件,執行代碼

創建觸發器: create trigger 名字 事件 執行代碼;

事件:insert,delete,update

事件的時機:執行之前和執行之后,after/before

由時機和事件在一起形成了6種事件:before insert,before delete...

事件規定在哪個表上的什么時機的什么動作上;

觸發程序:特定事件發生,即觸發:

update addMoney set stu_money = stu_money + 20 where id = 1;

觸發器不能同名,目前MySQL只支持一類事件設置一個觸發器

create trigger my_trigger after update on addMoney for each row update class set cz_money=cz_money+20;

管理觸發器:

刪除:
Drop trigger trigger_name;
查看:
Show create trigger trigger_name;

在觸發器內,獲得觸發該觸發程序時的數據:
Old new

利用 觸發程序內的 new 和 old來完成;

create trigger my_trigger after update on addMoney for each row update class set cz_money=cz_money+(old.stu_money-new.stu_money);

Old:
監聽事件所在表上的數據,在事件發生之前時的數據。舊的數據。
New:
監聽表上,事件發生之后,新處理完畢的數據。

數據,就是觸發該事件的記錄。

事件是insert呢? 不能使用old
事件是 delete呢?不能使用new

如果一個觸發程序,由多條SQL語句組成;

應該:1.語句組成語句塊(begin end)來標示語句塊.
2.語句塊的語句需要獨立的語句結束符,分號;

命令行:由于觸發器程序內使用分號作為語句結束符,那么當命令行客戶端碰到分號時,就應該理解成觸發程序內子語句結束,而不是整個觸發器的語句結束.

應該通過修改命令行的語句結束符達到目的.delimiter語句可以完成設置語句結束符;

drop trigger ruxue;
delimiter $$
create trigger ruxue after insert on czbk_student for eache row 
begin
update class set student_count = stu_count  +1;
update class set cz_money=cz_money+20;
end
$$

delimiter;
SQL編程

SQL:結構化查詢語言。
是一門編程語言。是由于管理數據的編程語言。

元素:
數據,
數據類型,
變量,
函數,
控制流程,
運算符 ,
注釋;

注釋:
行:

--[空格]
塊:
/* */

結束符:
命令行:\g \G

可以使用 delimiter 來修改語句結束符
Delimiter $$

變量:
字段名就是變量。
php有許多系統默認變量例如:
show variables like 'char%';

用戶自定義變量:

定義一個變量:set
Set 變量名 = 變量值。

注意,為了區分 系統變量和字段與用戶自定義變量,需要在用戶變量前,增加@標識符。
set @who = "haha";

通過 select 語句可以獲得當前的變量的值:
select @who;

Set是專門的為變量賦值的形式,甚至可以子查詢

set @total = (select count(*) from join_teacher);

定義一個變量 select info:

Select 字段列表 表達式 。。。 Into 變量列表。

select 10,14,20 into @a,@b,@c;
select c_name from join_class where id = 2 into @c_name;

注意,select into @var 要求,只能返回一行。如果返回多行,會語法錯誤,或者只將最后一行的數據,注入到變量內。

//會報錯
select c_name from join_class where 1 into @c_name;

利用 select語句的部分表達式達到為變量賦值的目的:

select @who = 'xiaoming'; //=是關系判斷

使用 := 的形式;

select @who := 'xiaoming';

注意,=應該賦值,但是在 select語句內,就成了 關系等于。使用專門的賦值運算符 :=。
同樣適用于 set。

set @i := '111';
select * from teacher where @who:='xiaoming';

使用變量是在表達式,或者使用select查詢到即可。

1,作用域。用戶定義的函數,是全局的(函數內可用)。存在局部作用域變量,函數內定義的變量。
2,有效期。會話結束(連接結束)。

運算符:

  • 函數

內置函數
數值:
Rand()得到1-0之間的隨機數

select rand();

如何得到5到10?
5+(0-5)
5+rand()*5;
取整:

select floor(rand()*5+5);

格式化:
format

select format(2132432.12323,2); //2位小數顯示

時間日期:
Now();
Unix_timestamp();

select unix_timestamp();
select from_unixtime(123456);
select from_unixtime(unix_timestamp());

字符串:

Concat()字符串連接
Substring(原字符串,開始位置,截取長度);
開始位置 從1開始

Char_length();
Length();

Lpad(需要補足的字符串,補足后的長度,補字符串);
左邊補足:

其他:
Md5()

select substring("hahahaha",2,2);
select length('你好');  //4
select char_length("你好"); //2

select lpad("1",3,"0"); //001

select md5("2");
select password("2");
select sha1("332");

數值函數
Abs(X),絕對值 abs(-10.9) = 10
Format(X,D),格式化千分位數值 format(1234567.456, 2) = 1,234,567.46
Ceil(X),向上取整 ceil(10.1) = 11

Floor(X),向下取整 floor (10.1) = 10
Round(X),四舍五入去整
Mod(M,N) M%N M MOD N 求余 10%3=1
Pi(),獲得圓周率
Pow(M,N) M^N
Sqrt(X),算術平方根
Rand(),隨機數
TRUNCATE(X,D) 截取D位小數
時間日期函數
Now(),current_timestamp(); 當前日期時間
Current_date();當前日期
current_time();當前時間
Date(‘yyyy-mm-dd HH;ii:ss’);獲取日期部分
Time(‘yyyy-mm-dd HH;ii:ss’);獲取時間部分
Date_format(‘yyyy-mm-dd HH;ii:ss’,’ %D %y %a %d %m %b %j');
Unix_timestamp();獲得unix時間戳
From_unixtime();//從時間戳獲得時間
字符串函數
LENGTH (string )   //string長度,字節
CHAR_LENGTH(string)    //string的字符個數
SUBSTRING (str , position [,length ])   //從str的position開始,取length個字符
REPLACE (str ,search_str ,replace_str )   //在str中用replace_str替換search_str



INSTR (string ,substring )   //返回substring首次在string中出現的位置
CONCAT (string [,... ])   //連接字串
CHARSET(str)  //返回字串字符集
LCASE (string )  //轉換成小寫
LEFT (string ,length )   //從string2中的左邊起取length個字符
LOAD_FILE (file_name )   //從文件讀取內容
LOCATE (substring , string [,start_position ] )   //同INSTR,但可指定開始位置
LPAD (string ,length ,pad )   //重復用pad加在string開頭,直到字串長度為length
LTRIM (string )  //去除前端空格
REPEAT (string ,count )   //重復count次
RPAD (string ,length ,pad)   //在str后用pad補充,直到長度為length
RTRIM (string )   //去除后端空格
STRCMP (string1 ,string2 )   //逐字符比較兩字串大小



流程函數:

CASE WHEN [condition] THEN result [WHEN [condition] THEN result ...] [ELSE result] END   多分支
IF(expr1,expr2,expr3)  雙分支。
聚合函數
Count()
Sum();
Max();
Min();
Avg();
Group_concat()
其他常用函數
Md5();
Default();

  • 自定義函數

要素:
函數名,
參數列表,
函數體,
返回值;

語法:
定義:
Create function 函數名 (參數列表) 返回值類型
函數體

delimiter $$
create function sayHi() returns varchar(20);
begin
return 'Hi';
end
$$
delimiter;

//調用
select sayHi();

注意:函數是與當前的數據庫綁定的,可以使用庫名.函數名的形式調用;

select one.sayHi();

sql中的流程控制:


分支
If 條件1 then
條件1滿足執行的語句
Elseif 條件2 then
條件2滿足執行的語句
….
Else 
上面的條件全都不滿足,執行的語句
End if;
 
Elseif 和 else 都是可以省略的。

循環
While 條件 do
循環體
End while


循環的提前終止
Leave       break 終止循環
Iterate     continue 終止當前循環
 
注意,不是根據leave和iterate所在的位置來決定終止哪個循環,而是由循環的標簽來決定的。
 
循環的標簽,給循環起名字。
標簽 : while
End while 標簽;


函數內使用的變量
@var的形式,相當于 全局變量,函數內和函數外通用。
 
函數的參數:
參數,同樣需要確定類型。
參數名 類型

一個函數,可以有多個參數,使用 逗號分割。
 
 
函數聲明的局部變量:
使用 declare聲明局部變量。 需要指定類型,可以指定默認值 default。
delimiter $$
create function func1() returns varchar(20)
begin

if hour(now(()) > 18 then
    return 'night';
else
    return 'day';
end if;

end
$$
delimiter;

delimiter $$
create function func2() returns int
begin
-- 1-10的和
set @i = 1;
set @sum = 0;

while @i<=10 do
    set @sum = @sum + @i;
    set @i = @i + 1;
end while;
return @sum;
end
$$
delimiter

delimiter $$
create function func2() returns int
begin
-- iterate
set @i = 1;
set @sum = 0;

w:while @i<10 do
    set @i = @i + 1;
    if @i = 5 then
        -- iterate w;
        iterate w;
    end if;
    set @sum = @sum + @i;
    
end while w;
return @sum;
end
$$
delimiter

delimiter $$
drop function if exists sayHi;
create function sayHi(user_name varchar(10)) returns varchar(20)
begin
return concat("Hi ",user_name);
end
$$
delimiter;
delimiter $$
drop function if exists func2;
create function func2() returns int
begin
-- 1-10的和
declare i int default 0;
declare total int default 0 ;
while i<=10 do
    set total = total + i;
    set i = i+ 1;
end while;
return total;
end
$$
delimiter;

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,363評論 6 532
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,497評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,305評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,962評論 1 311
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,727評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,193評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,257評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,411評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,945評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,777評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,978評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,519評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,216評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,642評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,878評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,657評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,960評論 2 373

推薦閱讀更多精彩內容