mysql常用

##################mysql5.6配置#####################

#开启日志
general_log=ON
#错误日志
log-error=d:/Server/MySQL/log/mysql_log_err.txt
#查询日志
general_log_file=d:/Server/MySQL/log/mysql_log.txt
#慢日志
slow_query_log=on
slow-query-log-file=d:/Server/MySQL/log/mysql_log_slow.txt
long_query_time=0.03

##################mysql5.6配置end#####################

快速链接
mysql -uroot -p


地址链接
mysql -uroot -P3306 -h127.0.0.1

修改密码
mysqladmin -u用户名 -p旧密码 password 新密码


退出
exit;
quit;
\q;

提示符
mysql -uroot -p --prompt \h //表示后面的提示符用地址展示 localhost \D时间 \d数据库 \u用户名

显示当前服务器版本号
mysql -V
SELECT VERSION()

显示当前日期
SELECT NOW()

显示当前用户
SELECT USER()


创建数据库
create database IF NOT EXISTS study character set utf8


查看数据库
show create database study

查看当前使用的数据库
mysql> select database();

修改数据库编码
alter database mydb character set utf8;

删除数据库test
drop database test


查看修改最大连接数命令
show variables like '%max_con%';
set GLOBAL max_connections=200;

使用指定数据库
use study;

创建表
//直接创建表
CREATE TABLE IF NOT EXISTS `sp_test` (
`t_id` int(4) NOT NULL AUTO_INCREMENT,
`price` float(10,2) NOT NULL,
`title` varchar(20) NOT NULL,
PRIMARY KEY (`t_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;


//在存在表的时候删除再创建
DROP TABLE IF EXISTS `sp_test`;
CREATE TABLE IF NOT EXISTS `sp_test` (
`t_id` int(4) NOT NULL AUTO_INCREMENT,
`price` float(10,2) NOT NULL,
`title` varchar(20) NOT NULL,
`senddate` date NOT NULL DEFAULT '0000-00-00' COMMENT '发布时间', PRIMARY KEY (`t_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

增加列
alter table class add tel int(4) not null default 0;
增加主键
alter table class add id int(8) primary key auto_increment first;

末尾加 after 列名。加在某列之后。
末尾加 first. 加在第一行。

唯一性
ALTER TABLE `documents` ADD UNIQUE (
`title`
)

创建唯一性
`name` varchar(20) NOT NULL UNIQUE KEY,


修改列
alter table class change 被改变的列名 列声明 int(20) not null default 0;

如:改掉tel的结构长度。 alter table class change tel tel int(20) not null default 0;

删除列
alert table class drop id;

查看当前数据库表
show tables;

更改表名score表为newscore
rename table score to newscore

删除表
drop table newscore

表结构或表说明
desc class

设置gbk
set names gbk

表增加
insert into msg(id,title,name,content) values(1,'去学校了吗?','小明','我们今天没去哈哈!');

表更改
update msg set id = 2,content ='我要当老大' where name='小明';

表删除
delete from msg where id=2;


编辑表结构
ALTER TABLE `sp_test` CHANGE `title` `title` VARCHAR( 40 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL


添加列
ALTER TABLE `sp_test` ADD `ms` TEXT NOT NULL


批量添加列
alter table em_day_data add (f_day_house11 int(11),f_day_house12 int(11),f_day_house13 int(11));


删除列
ALTER TABLE `sp_test` DROP `ms`


清空表或删除表

truncate table `sp_test` //这个速度快,并且保留表的结构,相当于重新建立了一张同样的新表
delete from `sp_test` //内容的ID仍然从删除点的ID继续建立,而不是从1开始


insert select语句 列数据类型要对应
insert test(name) select username from student where age>15;

建议

SQL语句+procedure analyse();


数据库导入导出
从数据库导出数据库文件
使用“mysqldump”命令
首先进入 DOS 界面,然后进行下面操作。
1)导出所有数据库
格式:mysqldump -u [数据库用户名] -p -A>[备份文件的保存路径]

2)导出数据和数据结构
格式:mysqldump -u [数据库用户名] -p [要备份的数据库名称]>[备份文件的保存路径]
举例:
例 1:将数据库 mydb 导出到 e:\MySQL\mydb.sql 文件中。
打开开始->运行->输入“cmd”,进入命令行模式。
c:\> mysqldump -h localhost -u root -p mydb >e:\MySQL\mydb.sql
然后输入密码,等待一会导出就成功了,可以到目标文件中检查是否成功。

例 2:将数据库 mydb 中的 mytable 导出到 e:\MySQL\mytable.sql 文件中。
c:\> mysqldump -h localhost -u root -p mydb mytable>e:\MySQL\mytable.sql

例 3:将数据库 mydb 的结构导出到 e:\MySQL\mydb_stru.sql 文件中。
c:\> mysqldump -h localhost -u root -p mydb --add-drop-table >e:\MySQL\mydb_stru.sql
备注:-h localhost 可以省略,其一般在虚拟主机上用。

3)只导出数据不导出数据结构
格式:
mysqldump -u [数据库用户名] -p -t [要备份的数据库名称]>[备份文件的保存路径]

4)导出数据库中的Events
格式:mysqldump -u [数据库用户名] -p -E [数据库用户名]>[备份文件的保存路径]

5)导出数据库中的存储过程和函数
格式:mysqldump -u [数据库用户名] -p -R [数据库用户名]>[备份文件的保存路径]

从外部文件导入数据库中
1)使用“source”命令
首先进入“mysql”命令控制台,然后创建数据库,然后使用该数据库。最后执行下面操作。
mysql>source [备份文件的保存路径]

2)使用“<”符号
首先进入“mysql”命令控制台,然后创建数据库,然后退出 MySQL,进入 DOS 界面。最后执行下面操作。
mysql -u root –p < [备份文件的保存路径]


mysql 存储过程
存储过程是SQL语句和控制语句的预编译集合,以一个名称存储并作为一个单元处理

存储过程参数
in该参数的值必须在调用存储过程时指定,不能被存储过程改变
out该参数可以被存储过程改变,并且可以返回
inout该参数在调用时指定,并且可以被改变和返回

存储过程语法
变量定义 DECLARE variable_name [,variable_name...] datatype [DEFAULT value];
DECLARE l_int int unsigned default 4000000;
DECLARE l_numeric number(8,2) DEFAULT 9.95;
DECLARE l_date date DEFAULT '1999-12-31';
DECLARE l_datetime datetime DEFAULT '1999-12-31 23:59:59';
DECLARE l_varchar varchar(255) DEFAULT 'This will not be padded';

$sql = "
DELIMITER $$
create procedure myproce3(out score int)
begin
set score=100;
END $$
DELIMITER ;
";
mysql_query($sql);//创建一个myproce3的存储过程
$sql = "call test.myproce3(@score);";
mysql_query($sql);//调用myproce3的存储过程
$result = mysql_query('select @score;');
$array = mysql_fetch_array($result);

echo '<pre>';print_r($array);


Ⅱ. 变量赋值

SET 变量名 = 表达式值 [,variable_name = expression ...]

条件语句
if-then -else语句

DELIMITER $$
CREATE PROCEDURE `removeUserByIdUseIf` (IN p_id INT)
BEGIN
declare i int;
set i = p_id + 1;
if p_id > 0 then
delete from student where id = i;
end if;
END $$

DELIMITER ;


Ⅱ. case语句:

DELIMITER $$
CREATE PROCEDURE proc3 (in parameter int)
begin
declare var int;
set var=parameter+1;
case var
when 0 then
insert into t values(17);
when 1 then
insert into t values(18);
else
insert into t values(19);
end case;
end;
$$
DELIMITER ;

//使用显式类型 cast 连接字符串和数值类型
CONCAT(CAST(int_col AS CHAR), char_col)

(3). 循环语句

Ⅰ. while ···· end while:

DELIMITER $$
CREATE PROCEDURE `addUserUseWhile` (IN p_id INT)
BEGIN
declare i int;
declare name varchar;
set i = 1;
set name = '张山';
while i < p_id do
insert into student(`name`) valuse(CONCAT(CAST(i AS CHAR), name));
set i = i + 1;
end while;
END $$

DELIMITER ;

Ⅱ. repeat···· end repeat:

它在执行操作后检查结果,而while则是执行前进行检查。

mysql > DELIMITER //
mysql > CREATE PROCEDURE proc5 ()
-> begin
-> declare v int;
-> set v=0;
-> repeat
-> insert into t values(v);
-> set v=v+1;
-> until v>=5
-> end repeat;
-> end;
-> //
mysql > DELIMITER ;

 

Ⅲ. loop ·····end loop:

loop循环不需要初始条件,这点和while 循环相似,同时和repeat循环一样不需要结束条件, leave语句的意义是离开循环。

DELIMITER $$
CREATE PROCEDURE `addUserUseLoop` (IN p_id INT)
BEGIN
declare i int;
declare name varchar(20);
set i = 1;
set name = '王五';
LOOP_LABLE:loop
insert into student(`name`) values(CONCAT(CAST(i AS CHAR), name));
set i = i + 1;
if i >=10 then
leave LOOP_LABLE;
end if;
end loop;
END $$

DELIMITER ;

 


(4). ITERATE迭代

Ⅰ. ITERATE:

通过引用复合语句的标号,来从新开始复合语句

DELIMITER $$
CREATE PROCEDURE `addUserUseIterate` (IN p_id INT)
BEGIN
declare i int;
declare name varchar(20);
set i = 1;
set name = '李四';
LOOP_LABLE:loop
if i=3 then
set i=i+1;
ITERATE LOOP_LABLE;
end if;
insert into student(`name`) values(CONCAT(CAST(i AS CHAR), name));
set i = i + 1;
if i >=10 then
leave LOOP_LABLE;
end if;
end loop;
END $$

DELIMITER ;
那么这个存储程序是怎么运行的的?首先i的值为0,条件判断语句if i=3 then判断为假,跳过if语段,向数据库中插入0,然后i+1,同样后面的if i>=10 then判断也为假,也跳过;继续循环,同样插入1和2;在i=3的时候条件判断语句if i=3 then判断为真,执行i=i+1,i值为4,然后执行迭代iterate loop_label;,即语句执行到iterate loop_label;后直接跳到if i=3 then判断语句,执行判断,这个时候由于i=4,if i=3 then判断为假,跳过IF语段,将4添加到表中,继续循环,当i变为10,条件判断if i>=10 then判断为真,执行leave loop_label;跳出loop循环,然后执行end;//,结束整个存储过程。
PS:可以这样理解ITERATE就是我们程序中常用的contiune,而leave就是break.当然在MySQL存储过程,需要循环结构有个名称,其他都是一样的.

 

案例:简单银行转账业务存储过程
DELIMITER $$
CREATE PROCEDURE `userPay` ( IN `p_id` INT, IN `o_id` INT, IN `p_price` FLOAT )
BEGIN
DECLARE g_price INT DEFAULT 0;
DECLARE t_error INTEGER DEFAULT 0;
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET t_error=1;
start transaction;
select price into g_price from zhanghao where id = p_id;
if g_price < p_price then
SET t_error=1;
select "该用户余额不足";
end if;
update zhanghao set price=price-p_price where id=p_id;
update zhanghao set price=price+p_price where id=o_id;
IF t_error = 1 THEN
ROLLBACK;
ELSE
COMMIT;
END IF;
END $$
DELIMITER ;


9.MySQL存储过程的基本函数

(1).字符串类

CHARSET(str) //返回字串字符集
CONCAT (string2 [,... ]) //连接字串
INSTR (string ,substring ) //返回substring首次在string中出现的位置,不存在返回0
LCASE (string2 ) //转换成小写
LEFT (string2 ,length ) //从string2中的左边起取length个字符
LENGTH (string ) //string长度
LOAD_FILE (file_name ) //从文件读取内容
LOCATE (substring , string [,start_position ] ) 同INSTR,但可指定开始位置
LPAD (string2 ,length ,pad ) //重复用pad加在string开头,直到字串长度为length
LTRIM (string2 ) //去除前端空格
REPEAT (string2 ,count ) //重复count次
REPLACE (str ,search_str ,replace_str ) //在str中用replace_str替换search_str
RPAD (string2 ,length ,pad) //在str后用pad补充,直到长度为length
RTRIM (string2 ) //去除后端空格
STRCMP (string1 ,string2 ) //逐字符比较两字串大小,
SUBSTRING (str , position [,length ]) //从str的position开始,取length个字符,
注:mysql中处理字符串时,默认第一个字符下标为1,即参数position必须大于等于1

mysql> select substring('abcd',0,2);
+-----------------------+
| substring('abcd',0,2) |
+-----------------------+

+-----------------------+
1 row in set (0.00 sec)

mysql> select substring('abcd',1,2);
+-----------------------+
| substring('abcd',1,2) |
+-----------------------+
| ab |
+-----------------------+
1 row in set (0.02 sec)
TRIM([[BOTH|LEADING|TRAILING] [padding] FROM]string2) //去除指定位置的指定字符
UCASE (string2 ) //转换成大写
RIGHT(string2,length) //取string2最后length个字符
SPACE(count) //生成count个空格

(2).数学类

ABS (number2 ) //绝对值
BIN (decimal_number ) //十进制转二进制
CEILING (number2 ) //向上取整
CONV(number2,from_base,to_base) //进制转换
FLOOR (number2 ) //向下取整
FORMAT (number,decimal_places ) //保留小数位数
HEX (DecimalNumber ) //转十六进制
注:HEX()中可传入字符串,则返回其ASC-11码,如HEX('DEF')返回4142143
也可以传入十进制整数,返回其十六进制编码,如HEX(25)返回19
LEAST (number , number2 [,..]) //求最小值
MOD (numerator ,denominator ) //求余
POWER (number ,power ) //求指数
RAND([seed]) //随机数
ROUND (number [,decimals ]) //四舍五入,decimals为小数位数]

注:返回类型并非均为整数,如:
(1)默认变为整形值

mysql> select round(1.23);
+-------------+
| round(1.23) |
+-------------+
| 1 |
+-------------+
1 row in set (0.00 sec)

mysql> select round(1.56);
+-------------+
| round(1.56) |
+-------------+
| 2 |
+-------------+
1 row in set (0.00 sec)

(2)可以设定小数位数,返回浮点型数据

mysql> select round(1.567,2);
+----------------+
| round(1.567,2) |
+----------------+
| 1.57 |
+----------------+
1 row in set (0.00 sec)
SIGN (number2 ) //

(3).日期时间类

ADDTIME (date2 ,time_interval ) //将time_interval加到date2
CONVERT_TZ (datetime2 ,fromTZ ,toTZ ) //转换时区
CURRENT_DATE ( ) //当前日期
CURRENT_TIME ( ) //当前时间
CURRENT_TIMESTAMP ( ) //当前时间戳
DATE (datetime ) //返回datetime的日期部分
DATE_ADD (date2 , INTERVAL d_value d_type ) //在date2中加上日期或时间
DATE_FORMAT (datetime ,FormatCodes ) //使用formatcodes格式显示datetime
DATE_SUB (date2 , INTERVAL d_value d_type ) //在date2上减去一个时间
DATEDIFF (date1 ,date2 ) //两个日期差
DAY (date ) //返回日期的天
DAYNAME (date ) //英文星期
DAYOFWEEK (date ) //星期(1-7) ,1为星期天
DAYOFYEAR (date ) //一年中的第几天
EXTRACT (interval_name FROM date ) //从date中提取日期的指定部分
MAKEDATE (year ,day ) //给出年及年中的第几天,生成日期串
MAKETIME (hour ,minute ,second ) //生成时间串
MONTHNAME (date ) //英文月份名
NOW ( ) //当前时间
SEC_TO_TIME (seconds ) //秒数转成时间
STR_TO_DATE (string ,format ) //字串转成时间,以format格式显示
TIMEDIFF (datetime1 ,datetime2 ) //两个时间差
TIME_TO_SEC (time ) //时间转秒数]
WEEK (date_time [,start_of_week ]) //第几周
YEAR (datetime ) //年份
DAYOFMONTH(datetime) //月的第几天
HOUR(datetime) //小时

 

创建不带参数的储存过程
CREATE PROCEDURE sp1() select 语句;


调用存储过程
CALL sp1;


创建带参数的存储过程
DELIMITER $$ 1.先修改定界符
CREATE PROCEDURE `removeUserById` (IN p_id INT) /2.添加带参数存储过程,删除指定ID的用户,参数名不能和字段名同名
BEGIN

delete from student where id = p_id;

END $$

DELIMITER ; 3.复原定界符


CALL removeUserById(3); 4.调用指定参数的存储过程


创建in和out的存储过程

DELIMITER $$
CREATE PROCEDURE `removeUserByIdAndReturnUserNums` (IN p_id INT,out d_count,out userNums INT) //out返回参数
BEGIN

delete from student where id = p_id;
select ROW_COUNT into d_count; //查看改变的数量。
select count(id) from student into userNums; //into 查询剩余的记录赋给参数

END $$

DELIMITER ;

//调用
CALL removeUserByIdAndReturnUserNums(7,@dnums,@nums);

select @dnums,@nums;

select @dnums; //查看改变的数量,即为删除的数量。
select @nums; //查看输出的值


//删除储存过程
DROP PROCEDURE `removeUserById`;

//查看存储过程
SHOW PROCEDURE STATUS


//查看存储过程内容
show create procedure proc_name;


mysql事务特性 //事物处理,保证数据库的完整性

原子性Atomicity
一致性Consistency
隔离性Isolation
持久性Durability


修改数据引擎
ALTER TABLE tab1 engine=innodb;


表结构或表说明
desc class

mysql属性:字段属性,针对数值型数据和日期类型数据的设置。
UNSIGNED:该字段不会有非负数出现,比如 int 设置为该属性,那么这列的数值都是从0开始。
ZEROFILL:默认补充的空格用零代替,设置为这个属性的时候,该列就是非负数列。例如,对于声明为INT(5) ZEROFILL的列,值4检索为00004
ON UPDATE CURRENT_TIMESTAMP:该列列为默认值使用当前的时间戳,并且自动更新。

group by 分组(多个分组 ‘,’号连接)

having 筛选 (多个筛选 and 连接)

例子:

******建立一张临时表*******
create table ecs_goods2 like ecs_goods;

insert into ecs_goods2 select * from ecs_goods order by cat_id asc,shop_price desc;

*****查询每组中最贵的商品*****

良好的理解模型

思路:where 表达式,把表达式放在行中,看表达式是否为真。把列当变量来理解。把查询出的结果当表来理解。

第一种方法
存到临时表 再分组
(from 型子查询)
select * from (select * from ecs_goods order by cat_id asc,shop_price desc) as a group by cat_id

第二种方法
子查询
(where 型子查询)
SELECT * FROM ecs_goods WHERE shop_price IN (SELECT max( shop_price ) FROM ecs_goods GROUP BY cat_id)


*******查询挂科2门以上的同学的平均分*****

第一种方法

select name,sum(score < 60) as s,avg(score) from stu group by name having s>=2

第二种方法

1.先把挂科2门以及2门以上的同学找出来
select name,count(*) from stu where score < 60 group by name;

2.再把查询结果存到临时表

3.SELECT name, avg( fen ) FROM newscore WHERE name IN (SELECT name FROM ( SELECT name, count( * ) AS gk FROM newscore WHERE fen <60 GROUP BY name HAVING gk >=2 ) AS a
)GROUP BY namei


exists 子查询 把外层的查询结果带到内层,看内层的结果是否成立,返回TRUE或FALSE

select cat_id,cat_name from category where exists(select * from goods where goods.cat_id=category.cat_id)


union 合并查询:把2次或多次查询联合起来
要求:两次查询的列数一致。

推荐:查询的每一列,相对应的列类型也一样。

注意:如果不同的语句中取出行,有完全相同(每个列的值都相同),那么相同的行将会合并(去重复)。

如果不去重复,可以加all来指定。

如果字句中有order by ,limit 需加小括号把语句包起来

(select * .....order by id) union (select * .....order by id) order by id desc

(select * .....order by id limit0,3) union (select * .....order by id limit0,4)

可以来自于多张表。

INNER JOIN 在表中存在至少一个匹配时,INNER JOIN 关键字返回行。

LEFT JOIN 关键字会从左表 (table_name1) 那里返回所有的行,即使在右表 (table_name2) 中没有匹配的行。

RIGHT JOIN 关键字会右表 (table_name2) 那里返回所有的行,即使在左表 (table_name1) 中没有匹配的行。

FULL JOIN 只要其中某个表存在匹配,FULL JOIN 关键字就会返回行。


创建视图

create view 视图名 as select 。。。。。。

修改视图

alter view .. as slect.....

set和enum类型创建
`cl` set('x','w','r') NOT NULL,
`c2` enum('f','d') NOT NULL,

set类型
select * from table where find_in_set('c',flag)
SELECT * FROM `student` WHERE `flag`='a,b'
SELECT * FROM `student` WHERE find_in_set( 'a', flag ) AND find_in_set( 'a', flag ) LIMIT 0 , 30


mysql查看日志
1,查看所有日志状态: show variables like '%log'
2,查看慢查询状态:show variables like 'show%'
3,开启慢查询日志:set global slow_query_log=on
4,查看是否开启了慢查询日志:show variables like 'slow_query_log'
5,记录未使用索引的查询:set global log_queries_not_using_indexes=on

count语句优化
查询2006和2007年电影的数量

select count(year='2006' or NULL) as '2006movie_count', count(year='2007' or NULL) as '2007movie_count' from film //count(id)表示不会被记数,count(*)null会被记数


mysql中using的用法
示例:
select a.*, b.* from a left join b using(colA);
等同于:
select a.*, b.* from a left join b on a.colA = b.colA;

group by 优化

group by可能会出现临时表(Using temporary),文件排序(Using filesort)等,影响效率。
可以通过关联的子查询,来避免产生临时表和文件排序,可以节省io
改写前
select actor.first_name,actor.last_name,count(*)
from sakila.film_actor
inner join sakila.actor using(actor_id)
group by film_actor.actor_id;
改写后
select actor.first_name,actor.last_name,c.cnt
from sakila.actor inner join(
select actor_id,count(*) as cnt from sakila.film_actor group by
actor_id
)as c using(actor_id);


取列的唯一性distinct

select count(distinct customer_id), count(distinct staff_id) from payment; //看离散度,看哪个列高
离散度高的可以放在组合索引前面

pt-duplicate-key-check工具检查重复及冗余索引。

pt-工具集地址:http://www.percona.com/software/percona-toolkit

mysql第三方配置工具
https://tools.percona.com/wizard
http://www.imooc.com/video/4165

mysql创建索引

EXPLAIN + sql语句 //使用 EXPLAIN 关键字可以让你知道MySQL是如何处理你的SQL语句的。这可以帮你分析你的查询语句或是表结构的性能瓶颈。

//EXPLAIN 的查询结果还会告诉你你的索引主键被如何利用的,你的数据表是如何被搜索和排序的……等等,等等。

(1)普通索引,这是最基本的索引,它没有任何限制。它有以下几种创建方式:
CREATE INDEX indexName ON mytable(username(10)); -- 单列索引
-- CREATE INDEX indexName ON mytable(username(10),city(10)); -- 组合索引
-- indexName为索引名,mytable表名,username和city为列名,10为前缀长度,即索引在该列从最左字符开始存储的信息长度,单位字节
-- 如果是CHAR,VARCHAR类型,前缀长度可以小于字段实际长度;如果是BLOB和TEXT类型,必须指定 前缀长度,下同

-- 修改表结构来创建索引
ALTER TABLE `sp_test` ADD INDEX ( `title` ) //简写

ALTER TABLE mytable ADD INDEX indexName (username(10));
-- ALTER TABLE mytable ADD INDEX indexName (username(10),city(10));
-- 此处 indexName 索引名可不写,系统自动赋名 username ,username_2 ,username_3,...

-- 创建表的时候直接指定
CREATE TABLE mytable(

id INT,

username VARCHAR(16),

city VARCHAR(16),

age INT,

INDEX indexName (username(10))-- INDEX indexName (username(10),city(10))

);
-- 此处 indexName 索引名同样可以省略

(2)唯一索引,它与前面的普通索引类似,不同的就是:索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。它有以下几种创建方式(仅仅在创建普通索引时关键字 INDEX 前加 UNIQUE):
*/
-- 创建索引
CREATE UNIQUE INDEX indexName ON mytable(username(10));
-- 修改表结构来创建索引
ALTER TABLE mytable ADD UNIQUE INDEX indexName (username(10));-- 也可简写成 ALTER TABLE mytable ADD UNIQUE indexName (username(10));
-- 创建表的时候直接指定
CREATE TABLE mytable(

id INT,

username VARCHAR(16),

city VARCHAR(16),

age INT,

UNIQUE INDEX indexName (username(10)) -- 也可简写成 UNIQUE indexName (username(10))

);

(3)主键索引,它是一种特殊的唯一索引,不允许有空值。在建表的时候同时创建的主键即为主键索引
主键索引无需命名,一个表只能有一个主键。主键索引同时可是唯一索引或者全文索引,但唯一索引或全文索引不能共存在同一索引
*/
-- 修改表结构来创建索引
ALTER TABLE mytable ADD PRIMARY KEY (id);
-- 创建表的时候直接指定
CREATE TABLE mytable(

id INT,

username VARCHAR(16),

city VARCHAR(16),

age INT,

PRIMARY KEY(id)

);

/*
(4)全文索引,InnoDB存储引擎不支持全文索引
*/
-- 创建索引
CREATE FULLTEXT INDEX indexName ON mytable(username(10));
-- 修改表结构来创建索引
ALTER TABLE mytable ADD FULLTEXT INDEX indexName (username(10));-- 也可简写成 ALTER TABLE mytable ADD FULLTEXT indexName (username(10));
-- 创建表的时候直接指定
CREATE TABLE mytable(

id INT,

username VARCHAR(16),

city VARCHAR(16),

age INT,

FULLTEXT INDEX indexName (username(10)) -- 也可简写成 FULLTEXT indexName (username(10))

)ENGINE=MYISAM;
-- 建表时创建全文索引,要设置该表的存储引擎为MYISAM,新版mysql默认InnoDB存储引擎不支持全文索引


-- 删除索引
DROP INDEX indexName ON mytable;

/*
Mysql自动使用索引规则:
btree索引
当使用 <,<=,=,>=,>,BETWEEN,IN,!=或者<>,以及某些时候的LIKE才会使用btree索引,因为在以通配符%和_开头作查询时,MySQL不会使用索引。btree索引能用于加速ORDER BY操作
hash索引
当使用=,<=>,IN,IS NULL或者IS NOT NULL操作符时才会使用hash索引,并且不能用于加速ORDER BY操作,并且条件值必须是索引列查找某行该列的整个值

对where后边条件为字符串的一定要加引号,字符串如果为数字mysql会自动转为字符串,但是不使用索引。
mysql目前不支持函数索引,只能对列的前一部分(指定长度前缀)进行索引,对于char和varchar列,使用前缀索引(该列从起始字符到指定长度字符位置建立索引)将大大节省空间。
mysql列建议列是非null的。说是如果是允许null的列,对索引会有影响(索引不会包括有NULL值)。因为它们使得索引、索引的统计信息以及比较运算更加复杂。应该用0、一个特殊的值或者一个空串代替空值。
尽量不使用NOT IN和<>操作

username,city,age建立这三列的组合索引,其实是相当于分别建立了下面三组组合索引:

username,city,age

username,city

username

使用组合索引,比如where等条件,列名必须从组合索引最左列至右连续的列名做条件才可以,组合索引类似单一索引前缀

*/
-- 调用组合索引
SELECT * FROM mytable WHERE username = 'admin' AND city = 'DaLian';
-- 多表联查中的条件也可运用索引

 

-- 全文索引的使用
SELECT * , MATCH (username,city) AGAINST ('name100 name200 city500 thisisname') FROM mytable WHERE MATCH (username,city) AGAINST ('name100 name200 city500 thisisname');
-- 返回 mytable 表在 MATCH 的参数中的任意列中包含 AGAINST 字符串参数中被 "空格" "," 和 "." 分割的任意单词的行(断字的字符: "空格" "," 和 "." 但是不用这些符号断字的语言,如中文,就得自行手动断字。)
-- 表列中的单词也是以空格分割来区分
-- 这里指定 MATCH...AGAINST 两次。这不会引起附加的开销,因为 MySQL 优化器会注意到两次是同样的 MATCH...AGAINST 调用,并只调用一次全文搜索代码。
/*
函数 MATCH() 对照一个列名集(一个 FULLTEXT 索引中的一个或多个列的列名)。搜索字符串做为 AGAINST() 的参数给定。搜索以忽略字母大小写的方式执行,预设搜寻是不分大小写,若要分大小写,列的字符集设置要从utf8改成utf8_bin。
虽然同一个表格可以有不同字符集的字段,但是同一个FULLTEXT 索引里的字段必须是同一个字符集与collation。
任何在 stopword 列表上出现的,或太短的(3 个字符或更少的)的单词将被忽略。(可以覆写内建的 stopword 列表。可以修改最少四个字符的设定。 )
搜索的词有一个权重性,如果搜索的词在表中包含它的行太多,则这个搜索词将有较低的权重(可能甚至有一个零权重),否则,它将得到一个较高的权重。然后,权重将被结合用于计算行的相似性。
如果搜索词在表中超过一半的行中出现。则它被有效地处理为一个 stopword (即,一个零语义值的词),不搜索该词。

MATCH...AGAINST可以跟所有MySQL语法搭配使用,像是JOIN或是加上其他过滤条件。

对于表中的每行记录,MATCH...AGAINST 返回一个相关性值。即,返回的每行与搜索条件之间的相似性尺度。

当 MATCH() 被使用在一个 WHERE 子句中时,返回的结果被自动地以相关性从高到底的次序排序。如果即没有 WHERE 也没有 ORDER BY 子句,返回行是不排序的。
相关性值是正值的浮点数字。零相关性意味着不相似。
相关性的计算是基于:查找单词在表行中的数目、在行中唯一词的数目、在集中词的全部数目和包含一个特殊词的行的数目。

到 4.0.1 时,MySQL 也可以使用 IN BOOLEAN MODE 修饰语来执行一个逻辑全文搜索。
IN BOOLEAN MODE的特色:
不剔除50%以上符合的row。
不自动以相关性反向排序。
可以对没有FULLTEXT 索引的字段进行搜寻,但会非常慢。
限制最长与最短的字符串。
套用stopwords。

逻辑全文搜索支持下面的操作符:
+ 一个领头的加号表示,返回的结果的每行都必须包含有该单词。
- 一个领头的减号表示,包含该单词的行不能出现在返回的结果中。
> 操作符增加包含该单词返回行相似性值的基值。
< 操作符减少包含该单词返回行相似性值的基值。
() 被括号包含的多个词只相当一个词,即在查询时括号里只有一个词可代表该括号与括号外的词相结合做查询,但括号中每个词都会依次被轮到代表该括号,所以与括号外单词会产生多种结合形式,依次做查询条件。
~ 将其相关性由正转负,表示拥有该字会降低相关性,但不像 - 将之排除,只是排在较后面。
* 一个星号是截断操作符,它应该被追加到一个词后,不加在前面。作用类似 LIKE 语句中的 %
"" 把被双引号包含的多个词作为一个词

这里是一些示例,在返回结果中:
1.+apple +juice ... 两个词均在被包含
2.+apple macintosh ... 包含词 “apple”,但是如果同时包含 “macintosh”,它的排列将更高一些
3.+apple -macintosh ... 包含 “apple” 但不包含 “macintosh”
4.+apple +(>pie <strudel) ... 包含 “apple” 和 “pie”,或者包含的是 “apple” 和 “strudel” (以任何次序),但是“apple pie” 排列得比 “apple strudel” 要高一点
5.apple* ... 包含 “apple”,“apples”,“applesauce” 和 “applet”
6."some words" ... 可以包含 “some words of wisdom”,但不是 “some noise words”
*/
SELECT *,MATCH (username,city) AGAINST ('>>name300 +thisisname -city100' IN BOOLEAN MODE) FROM mytable WHERE MATCH (username,city) AGAINST ('>>name300 +thisisname -city100' IN BOOLEAN MODE);
/*
全文索引的限制
MATCH() 函数的所有参数必须是从来自于同一张表的列,同时必须是同一个FULLTEXT 索引中的一部分,除非 MATCH() 是 IN BOOLEAN MODE 的。

MATCH() 列必须确切地匹配表的某一 FULLTEXT 索引中定义的列,除非 MATCH() 是 IN BOOLEAN MODE 的。

AGAINST() 的参数必须是一个常量字符串。

 

MySQL全文搜寻设定:
大部分的参数都是启动参数,也就是修改后必须重新启动MySQL。
有些参数修改必须重新产生索引文件。
mysql> SHOW VARIABLES LIKE 'ft%';

ft_boolean_syntax + -><()~*:""&|
ft_min_word_len 4
ft_max_word_len 84
ft_query_expansion_limit 20 ft_stopword_file (built-in)

ft_min_word_len:最短的索引字符串,默认值为4,修改后必须重建索引文件。
ft_max_word_len:最长的索引字符串,默认值因版本而不同,余同上一点。
[mysqld]
ft_min_word_len=1
ft_stopword_file:stopword档案路径,若留空白不设定表示要停用stopword过滤,修改后必须重新启动MySQL和重建索引;stopword档案内容可以用分行空白与逗号区隔stopword,但底线和单引号视为合法的字符串字符。
50%的门坎限制:配置文件在storage/myisam/ftdefs.h,将 #define GWS_IN_USE GWS_PROB 改为 #define GWS_IN_USE GWS_FREQ,然后重新编译MySQL,因为近低门坎会影响数据的精准度,所以不建议如此,可用IN BOOLEAN MODE即可以避开50%的限制。
ft_boolean_syntax:改变IN BOOLEAN MODE的查询字符,不用重新启动MySQL也不用重建索引。
修改字符串字符的认定,譬如说将「-」认定为字符串的合法字符:
方法一:修改storage/myisam/ftdefs.h的true_word_char()与misc_word_char(),然后重新编译MySQL,最后重建索引。
方法二:修改字符集档,然后在FULLTEXT index的字段使用该字符集,最后重建索引。
重建索引:
每个有FULLTEXT index的表格都要这么做。
mysql> REPAIR TABLE tbl_name QUICK;
要注意如果用过myisamchk,会导致上述的设定值回复成默认值,因为myisamchk不是用MySQL的设定值。
解法一:将修改过得设定值加到myisamchk的参数里。
shell> myisamchk --recover --ft_min_word_len=1 tbl_name.MYI
解法二:两边都要设定。
[mysqld]
ft_min_word_len=1
[myisamchk]
ft_min_word_len=1
解法三:用REPAIR TABLE、ANALYZE TABLE、OPTIMIZE TABLE与ALTER TABLE取代myisamchk语法,因为这些语法是由MySQL执行的。

中文全文索引可以建两个表,一个表字段里存中文,一个表对应字段存汉语拼音,两表行必须对应,数据一致,插入时中文转化下汉语拼音,两表都插入
查询时也转化下,全文索引查汉语拼音,然后找到中文表对应行
或者使用mysqlcft中文全文索引插件

 

查看索引使用情况
如果索引正在工作,Handler_read_key的值将很高,这个值代表了一个行被索引值读的次数,很低的值表明增加索引得到的性能改善不高,因为索引并不经常使用。
Handler_read_rnd_next的值高则意味着查询运行低效,并且应该建立索引补救。这个值的含义是在数据文件中读下一行的请求数。如果你正进行大量的表扫描,该值较高。通常说明表索引不正确或写入的查询没有利用索引。

语法:SHOW STATUS LIKE 'Handler_read%';


MyISAM表的数据文件和索引文件是自动分开的
InnoDB的数据和索引是存储在同一个表空间里面,但可以有多个文件组成

虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT、UPDATE和DELETE。因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件。

建立索引会占用磁盘空间的索引文件。一般情况这个问题不太严重,但如果你在一个大表上创建了多种组合索引,索引文件的会膨胀很快。
*/


如何判定是否需要创建索引?

1、较频繁地作为查询条件的字段

这个都知道。什么是教频繁呢?分析你执行的所有SQL语句。最好将他们一个个都列出来。然后分析,发现其中有些字段在大部分的SQL语句查询时候都会用到,那么就果断为他建立索引。

2、唯一性太差的字段不适合建立索引

什么是唯一性太差的字段。如状态字段、类型字段。那些只存储固定几个值的字段,例如用户登录状态、消息的status等。这个涉及到了索引扫描的特性。例如:通过索引查找键值为A和B的某些数据,通过A找到某条相符合的数据,这条数据在X页上面,然后继续扫描,又发现符合A的数据出现在了Y页上面,那么存储引擎就会丢弃X页面的数据,然后存储Y页面上的数据,一直到查找完所有对应A的数据,然后查找B字段,发现X页面上面又有对应B字段的数据,那么他就会再次扫描X页面,等于X页面就会被扫描2次甚至多次。以此类推,所以同一个数据页可能会被多次重复的读取,丢弃,在读取,这无疑给存储引擎极大地增加了IO的负担。

3、更新太频繁地字段不适合创建索引

当你为这个字段创建索引时候,当你再次更新这个字段数据时,数据库会自动更新他的索引,所以当这个字段更新太频繁地时候那么就是不断的更新索引,性能的影响可想而知。大概被检索几十次会更新一次的字段才比较符合建立索引的规范。而如果一个字段同一个时间段内被更新多次,那么果断不能为他建立索引。

4、不会出现在where条件中的字段不该建立索引

这个相信大家都知道。

 

mysql事件

创建一个每隔30秒往test表中插入一条数据的事件,代码如下:

CREATE EVENT IF NOT EXISTS testEvent ON SCHEDULE EVERY 30 SECOND

ON COMPLETION PRESERVE

DO INSERT INTO sp_test(title,price) VALUES('jjj',2222.356);

 

事件设置2012-08-22 00:00:00时刻开始运行,每隔1天调用一次存储过程,40天后结束,代码如下:

CREATE EVENT test ON SCHEDULE EVERY 1 DAY

STARTS '2012-08-22 00:00:00'

ENDS '2012-08-22 00:00:00'+INTERVAL 40 DAY

ON COMPLETION PRESERVE DO

CALL test_add();


mysql 触发器
CREATE TRIGGER 触发器名 BEFORE|AFTER 触发事件
ON 表名 FOR EACH ROW 执行语句

DELIMITER ||
CREATE TRIGGER testTrig BEFORE DELETE
ON sp_test FOR EACH ROW
BEGIN
INSERT INTO sp_test1(`title`,`price`) VALUES('yyyyy',6578.92);
END ||
DELIMITER ;

上面的语句中,开头将结束符号定义为||,中间定义一个触发器,一旦有满足条件的删除操作

就会执行BEGIN和END中的语句,接着使用||结束

最后使用DELIMITER ; 将结束符号还原

 

MyISAM 和InnoDB 讲解

  InnoDB和MyISAM是许多人在使用MySQL时最常用的两个表类型,这两个表类型各有优劣,视具体应用而定。基本的差别为:MyISAM类型不支持事务处理等高级处理,而InnoDB类型支持。MyISAM类型的表强调的是性能,其执行数度比InnoDB类型更快,但是不提供事务支持,而InnoDB提供事务支持以及外部键等高级数据库功能。

  以下是一些细节和具体实现的差别:

  ◆1.InnoDB不支持FULLTEXT类型的索引。

  ◆2.InnoDB 中不保存表的具体行数,也就是说,执行select count(*) from table时,InnoDB要扫描一遍整个表来计算有多少行,但是MyISAM只要简单的读出保存好的行数即可。注意的是,当count(*)语句包含 where条件时,两种表的操作是一样的。

  ◆3.对于AUTO_INCREMENT类型的字段,InnoDB中必须包含只有该字段的索引,但是在MyISAM表中,可以和其他字段一起建立联合索引。

  ◆4.DELETE FROM table时,InnoDB不会重新建立表,而是一行一行的删除。

  ◆5.LOAD TABLE FROM MASTER操作对InnoDB是不起作用的,解决方法是首先把InnoDB表改成MyISAM表,导入数据后再改成InnoDB表,但是对于使用的额外的InnoDB特性(例如外键)的表不适用。

  另外,InnoDB表的行锁也不是绝对的,假如在执行一个SQL语句时MySQL不能确定要扫描的范围,InnoDB表同样会锁全表,例如update table set num=1 where name like “%aaa%”

  两种类型最主要的差别就是Innodb 支持事务处理与外键和行级锁。而MyISAM不支持.所以MyISAM往往就容易被人认为只适合在小项目中使用。

  作为使用MySQL的用户角度出发,Innodb和MyISAM都是比较喜欢的,如果数据库平台要达到需求:99.9%的稳定性,方便的扩展性和高可用性来说的话,MyISAM绝对是首选。

  原因如下:

  1、平台上承载的大部分项目是读多写少的项目,而MyISAM的读性能是比Innodb强不少的。

  2、MyISAM的索引和数据是分开的,并且索引是有压缩的,内存使用率就对应提高了不少。能加载更多索引,而Innodb是索引和数据是紧密捆绑的,没有使用压缩从而会造成Innodb比MyISAM体积庞大不小。

  3、经常隔1,2个月就会发生应用开发人员不小心update一个表where写的范围不对,导致这个表没法正常用了,这个时候MyISAM的优越性就体现出来了,随便从当天拷贝的压缩包取出对应表的文件,随便放到一个数据库目录下,然后dump成sql再导回到主库,并把对应的binlog补上。如果是Innodb,恐怕不可能有这么快速度,别和我说让Innodb定期用导出xxx.sql机制备份,因为最小的一个数据库实例的数据量基本都是几十G大小。

  4、从接触的应用逻辑来说,select count(*) 和order by 是最频繁的,大概能占了整个sql总语句的60%以上的操作,而这种操作Innodb其实也是会锁表的,很多人以为Innodb是行级锁,那个只是where对它主键是有效,非主键的都会锁全表的。

  5、还有就是经常有很多应用部门需要我给他们定期某些表的数据,MyISAM的话很方便,只要发给他们对应那表的frm.MYD,MYI的文件,让他们自己在对应版本的数据库启动就行,而Innodb就需要导出xxx.sql了,因为光给别人文件,受字典数据文件的影响,对方是无法使用的。

  6、如果和MyISAM比insert写操作的话,Innodb还达不到MyISAM的写性能,如果是针对基于索引的update操作,虽然MyISAM可能会逊色Innodb,但是那么高并发的写,从库能否追的上也是一个问题,还不如通过多实例分库分表架构来解决。

  7、如果是用MyISAM的话,merge引擎可以大大加快应用部门的开发速度,他们只要对这个merge表做一些select count(*)操作,非常适合大项目总量约几亿的rows某一类型(如日志,调查统计)的业务表。

  当然Innodb也不是绝对不用,用事务的项目就用Innodb的。另外,可能有人会说你MyISAM无法抗太多写操作,但是可以通过架构来弥补。

你可能感兴趣的:(mysql常用)