介绍几个数据库的概念
SQL语言分类
DBMS可分为两类
MySQL版本
MySQL工具
mysql -u 登录名 -p 端口号 -h 主机名 -P 密码 # 默认的可以省略
选择数据库
USE 数据库名称
了解数据库和表
SHOW DATABASES # 返回可用数据库的一个列表
SHOW TABLES # 返回当前选择的数据库内可用表的列表
SHOW COLUMNS FROM 表名 # 显示指定表的所有列信息
SQL语句不区分大小写,可以对关键字使用大写,对表名和列使用小写
SELECT * FROM admin_user LIMIT 2 OFFSET 1
ORDER BY :A 被视为与 a 相同
-- LIMIT 与 ORDER BY 语句顺序不能改变
SELECT * FROM admin_user ORDER BY username LIMIT 1
比较 NULL < ' '(空格) 总是在 '' (空字符串)前 < 数字 < 中文
SELECT * FROM admin_user ORDER BY email asc
1简单使用
SELECT * FROM admin_user WHERE username = 'ADMIN' ORDER BY username LIMIT 2
2 使用以下语句期望可以将为 NULL 的值查出来,但实际不可以
SELECT * FROM admin_user WHERE gender != 0
3 使用 NULL 时需要注意,它只能使用 IS / IS NOT 来过滤
SELECT * FROM admin_user WHERE IFNULL(gender,0) = 0
SELECT * FROM admin_user WHERE IFNULL(gender,0) != 1
4 注意空格,= ‘’ 或者 = ‘ ’ 可以匹配带空格或不带空格的非 NULL 值
1 AND 比 OR 的优先级高
SELECT * FROM admin_user WHERE username = 'admin' or username = 'string' and gender = 0
以上语句实际为
SELECT * FROM admin_user WHERE username = 'admin' or ( username = 'string' and gender = 0 )
2 IN操作符一般比OR操作符清单执行更快
LIKE ,LIKE 'admin' 可以匹配到等于 ‘admin’ 的记录
1 不区分大小写
SELECT * FROM admin_user WHERE username LIKE 'ad%'
2 注意尾空格 LIKE ‘%min’ 不能匹配末尾有空格的 `admin `
3 注意 NULL,LIKE '%' 不能匹配 NULL
SELECT * FROM admin_user WHERE email LIKE '%'
注意:
REGEXP 与 LIKE '%内容%' 一样。不区分大小写,可以使用 REGEXP BINARY 'JetPack .000' 区别大小写
1 与 LIKE '%内容%' 一样
SELECT * FROM admin_user WHERE username REGEXP 'adm'
2 字符类
3 匹配多个实例
SELECT * FROM admin_user WHERE username REGEXP '[[:alnum:]]{7}' -- 可以匹配不少于 7 个的字符串
4 定位符
^ 的双重用途:在集合中(用[和]定义),用它来否定该集合,否则,用来指串的开始处。
SELECT * FROM admin_user WHERE username REGEXP '^string' -- 匹配 string 开头的
5 使用如下语句返回 0 或 1 验证是否匹配
SELECT 'hello' REGEXP 'hello'
函数没有SQL的可移植性强,不赞成使用特殊实现的功能
TRIM() 去掉空格
SELECT TRIM(' abc ') -- abc
LEFT() 返回串左边的几个字符串,小于 0.5 时为空,进行四舍五入
SELECT LEFT("abc",2) -- ab
SELECT LEFT(1234,-1) -- 返回空字符串
SELECT LEFT(1234,1.5) -- 12
SELECT LEFT(1234,1.4) -- 1
RIGHT() 返回串右边的几个字符,小于 0.5 时为空,进行四舍五入
SELECT RIGHT('123',1) -- 3
SELECT RIGHT('123',0) -- 空字符串
LOCATE() 是否匹配
SELECT LOCATE(username,'admin'),username FROM admin_user
LOWER() 转为小写
SELECT LOWER('ACd') -- acd
UPPER() 转为大写
SELECT UPPER('abc') -- ABC
SOUNDEX() 返回 SOUNDEX 值,一种语音算法
SELECT SOUNDEX("abc") -- A120
SUBSTR() 返回子字符串,从 1 开始
SELECT SUBSTR(123 FROM 1 FOR 4) -- 123
SELECT SUBSTR(123 FROM 0 FOR 4) -- 空
SELECT NOW(); -- 2020-03-23 08:28:05
SELECT CURRENT_DATE; -- 2020-03-23
SELECT CURRENT_TIME; -- 08:26:54
SELECT DATE(NOW()); -- 2020-03-23
SELECT YEAR(NOW()); -- 2020
SELECT MONTH(NOW()); -- 3 当前是 2020-03-23
SELECT DAY(NOW()); -- 23
SELECT HOUR('2020-01-05 00:00:01'); -- 0
SELECT MINUTE('2020-01-05 00:0:01'); -- 0
SELECT SECOND('2020-01-05 00:00:01'); -- 1
SELECT DAYOFWEEK(NOW()) -- 2 当前是周一,周日是 1
-- 日期运算,两者可接受参数较多:SECOND MINUTE HOUR DAY WEEK MONTH YEAR 等
SELECT ADDDATE(NOW(),INTERVAL 1 YEAR);
SELECT DATE_ADD(NOW(),INTERVAL 1 YEAR);
-- 当前时间加几秒
SELECT ADDTIME('2020-01-05 00:00:01',6) -- 2020-01-05 00:00:07
-- 日期差
SELECT DATEDIFF('2020-01-05','2020-01-06'); -- -1 前面减后面的
SELECT COUNT(gender) FROM admin_user -- 只计算不为 null 的行数
WITH ROLLUP 计算汇总和
SELECT username,COUNT(*) FROM admin_user GROUP BY username WITH ROLLUP
ORDER BY 可以对分组后的别名进行排序
SELECT gender,AVG(gender) FROM admin_user GROUP BY gender ORDER BY gender DESC
select 子句顺序
SELECT * FROM admin_user, admin_role
SELECT user_id , username FROM admin_user
UNION
SELECT user_id , username FROM admin_user
ORDER BY user_id
如果以上语句的列顺序或列名不一致,将出现一个笛卡尔乘积的结果;
只能使用一条ORDER BY子句,它必须出现在最后一条SELECT语句之后。对于结果集,不存在用一种方式排序一部分,而又用另一种方式排序另一部分的情况,因此不允许使用多条ORDER BY子句。
并( UNION) 或复合查询(compound query),使用场景
注意事项:
UNION ALL 不会对结果进行去重,它完成 WHERE 子句完成不了的工作,比如查询两条一样的数据?
并非所有引擎都支持全文本搜索。两个最常使用的引擎为MyISAM和InnoDB,前者支持全文本搜索,而后者不支持。
启用全文本搜索支持 FULLTEXT、ENGINE = MYISAM ,FULLTEXT可以索引多个列
CREATE TABLE productnotes (
note_id INT NOT NULL AUTO_INCREMENT,
prod_id CHAR ( 10 ) NOT NULL,
note_date datetime NOT NULL,
note_text text NULL,
PRIMARY KEY ( note_id ),
FULLTEXT ( note_text )
) ENGINE = MYISAM
进行全文本搜索,Match() 指定被搜索的列, Against() 指定要使用的搜索表达式
SELECT note_text FROM productnotes
WHERE match ( note_text ) against ( 'food' )
-- 与 like '%food%' 作用相同
什么是等级?
Match()和Against()的结果是具有等级的,等级由MySQL根据行中词的数目、唯一词的数目、整个索引中词的总数以及包含该词的行的数目计算出来
SELECT note_text, match ( note_text ) against ( 'food' ) as rank
FROM productnotes
使用查询扩展
SELECT note_text FROM productnotes
WHERE MATCH ( note_text ) AGAINST ( 'anvils' WITH QUERY EXPANSION)
布尔文本搜索
SELECT note_text FROM productnotes
WHERE MATCH ( note_text ) AGAINST ( 'food -ROP*' IN BOOLEAN MODE)
不安全的插入,高度依赖于表中列的定义次序
INSERT INTO productnotes VALUES ( NULL, 'a1', NOW( ), 'hello ' )
安全但是繁琐,给出了列名,并且省略了不需要的列
INSERT INTO productnotes(note_id,prod_id,note_date)
VALUES ( NULL, 'a1', NOW( ) )
使用 LOW_PRIORITY 指示 MySQL 降低 INSERT 语句的优先级,先执行 SELECT,提高性能。同样适用于 UPDATE/DELETE
INSERT LOW_PRIORITY INTO productnotes(prod_id,note_date,note_text)
VALUES ('a2', NOW( ), 'hello ' )
多个 insert 语句使用封号隔开
INSERT LOW_PRIORITY INTO productnotes(prod_id,note_date,note_text)
VALUES ('a2', NOW( ), 'hello' );
INSERT LOW_PRIORITY INTO productnotes(prod_id,note_date,note_text)
VALUES ('a3', NOW( ), 'home' );
VALUES 后边多个括号的值用逗号隔开。效率高。
INSERT INTO productnotes ( prod_id, note_date, note_text )
VALUE
( 'a1', NOW( ), 'year' ),
( 'b1', NOW( ), 'month' )
注意:VALUE 是 VALUES 的 synonym 没有区别。
INSERT SELECT
INSERT INTO productnotes ( prod_id, note_date, note_text )
SELECT prod_id,note_date,note_text FROM productnotes
更新表中的特定行,添加 WHERE 子句
UPDATE productnotes SET note_text = 'update hello', prod_id = 520
WHERE note_id = '3'
更新表中的所有行,不加 WHERE 子句
IGNORE 关键字,发生错误仍然继续更新
UPDATE IGNORE tablename ..
从表中删除特定的行
DELETE FROM productnotes WHERE note_id = 1
从表中删除所有行
使用 TRUNCATE TABLE 提高效率,实际是直接删除原来的表再新建一个。不能有 where 子句
TRUNCATE TABLE productnotes
注意事项:
CREATE TABLE user
(
id INT NOT NULL AUTO_INCREMENT comment '用户id',
name CHAR ( 50 ) NOT NULL,
sex int DEFAULT 0,
PRIMARY KEY ( id )
) ENGINE = INNODB;
使用ALTER TABLE要极为小心,应该在进行改动前做一个完整的备份
ALTER TABLE `user` ADD address VARCHAR ( 255 );
ALTER TABLE `user` DROP address;
ALTER TABLE `user` CHANGE name username VARCHAR ( 100 ); -- 修改列名与类型
ALTER TABLE `user` MODIFY username VARCHAR(255) comment '用户名称'; -- 修改列属性
永久删除表,小心点啊
DROP TABLE test
可以同时修改多个
RENAME TABLE `user` TO my_user ,tablename to newtablename;
CREATE VIEW vw_user AS
SELECT * FROM `user`
使用存储过程比使用多条SQL语句要快
不带参数的存储过程
CREATE PROCEDURE `pro_user`()
BEGIN
SELECT * FROM `user`;
END;
CALL pro_user -- 使用
使用命令行需注意:
如果命令行实用程序要解释存储过程自身内的;字符,则它们最终不会成为存储过程的成分,这会使存储过程中的SQL出现句法错误。解决办法是临时更改命令行实用程序的语句分隔符,如下所示:
DELIMITER // 告诉命令行实用程序使用//作为新的语句结束分隔符,可以看到标志存储过程结束的END定义为END// 而不是END;。 除\符号外,任何字符都可以用作语句分隔符
DELIMITER //
CREATE PROCEDURE `pro_user`()
BEGIN
SELECT * FROM `user`;
END //
DELIMITER;
列出了查询结果
CALL pro_user
DROP PROCEDURE pro_user
DROP PROCEDURE IF EXISTS pro_user -- 仅存在时删除,防止报错
OUT 获取返回结果,只能是单列,想要获取结果集就不要使用 OUT参数。
注意:参数使用 id 时无法使用呢??不要和字段名一样
CREATE PROCEDURE pro_user ( OUT outid INT)
BEGIN
SELECT MAX( id ) INTO outid FROM `user`;
END;
CALL pro_user ( @outid);
SELECT @outid as id;
如果没有返回值 OUT ,但是有多个查询,会输出第一个的查询结果
DROP PROCEDURE IF EXISTS pro_user;
CREATE PROCEDURE pro_user ( in inname VARCHAR ( 255 ) )
BEGIN
SELECT * FROM `user`;
SELECT * FROM `user` WHERE `name` = inname;
END;
-- 使用
CALL pro_user ( 'ewjlf' );
IN 向存储过程中传入参数,
注意:传入参数也不能使用 id,不要和字段名一样
DROP PROCEDURE IF EXISTS pro_user;
CREATE PROCEDURE pro_user ( OUT outname VARCHAR ( 255 ), IN inid INT )
BEGIN
SELECT `name` INTO outname FROM `user` WHERE id = inid;
END;
DROP PROCEDURE IF EXISTS pro_user;
CREATE PROCEDURE pro_user ( IN inid INT ) COMMENT '用户的存储过程'
BEGIN
-- 声明变量
DECLARE username VARCHAR(255);
DECLARE test int;
-- INTO 的位置可以是末尾
SELECT `name` FROM `user` WHERE id = inid INTO username;
-- if 语句
IF LENGTH( username ) > 0 THEN
SELECT '存在';
ELSE
SELECT '不存在';
END IF;
END;
-- 显示所有存储过程,也可以在后面加 like '存储过程名称' 这个查询条件
SHOW procedure STATUS
SHOW CREATE PROCEDURE pro_user
参考:https://www.jb51.net/article/55019.htm##1
查看是否允许自定义函数,OFF 不允许
show variables like '%func%';
set global log_bin_trust_function_creators=1 -- 临时开启自定义函数功能
CREATE FUNCTION <函数名> ( [ <参数1> <类型1> [ , <参数2> <类型2>] ] … )
RETURNS <类型>
<函数主体>
DROP FUNCTION IF EXISTS fun_user; -- 删除
CREATE FUNCTION fun_user(userid int) -- 创建
RETURNS varchar(255) -- 注意返回值是 RETURNS,有个 S
BEGIN
DECLARE username VARCHAR(255);
DECLARE result VARCHAR(255);
SELECT `name` FROM `user` WHERE id = userid INTO username;
-- if 语句
IF LENGTH( username ) > 0 THEN
SELECT '存在' into result;
ELSE
SELECT '不存在' INTO result;
END IF;
RETURN result;
END;
SELECT fun_user(22);
检查,与存储过程的使用方式一样
SHOW CREATE FUNCTION fun_user;
SHOW FUNCTION STATUS;
MySQL游标只能用于存储过程(和函数)
游标主要用于交互式应用,其中用户需要滚动屏幕上的数据,并对数据进行浏览或做出更改
http://c.biancheng.net/view/2600.html
只支持 6 中触发器语句
begin |
insert |
update |
delete |
end |
insert |
update |
delete |
创建触发器
CREATE <触发器名> < BEFORE | AFTER >
ON <表名> FOR EACH Row <触发器主体>
可以引用 NEW 和 OLD 指代被操作前后的记录
CREATE TRIGGER before_insert BEFORE INSERT on user
FOR EACH ROW SET New.sex = 5;
事务用来管理 INSERT、UPDATE、DELETE。
不能回退 SELECT、CREATE、DROP ,它们可以存在事务块中,但不可以撤销
隐含事务关闭 当COMMIT或ROLLBACK语句执行后,事务会自动关闭(将来的更改会隐含提交)。
保留点越多越好 可以灵活回退
释放保留点:ROLLBACK 或 COMMIT 后自动释放。MySQL 5 后可以使用 RELEASE SAVEPOINT 释放。
更改默认提交行为 SET autocommit = 0 设置为不自动提交,只在当前连接生效
START TRANSACTION;
SELECT * FROM `user`;
DELETE FROM `user` WHERE ID = 19
SAVEPOINT U20;
DELETE FROM `user` WHERE ID= 20
ROLLBACK TO U20;
COMMIT/ROLLBACK;
字符集和校对可以在系统管理安装、创建数据库、表、列的时候指定。
也可以在 select 语句中指定校对,实现想要的排序方式,或者是针对 GROUP BY、HAVING、聚集函数、别名
字符串可以使用 Cast() Convert() 转换字符集
SHOW CHARACTER SET; -- 显示可用的字符集、描述和默认校对
SHOW COLLATION; -- 显示所有可用校对,以及适用的字符集
SHOW VARIABLES LIKE 'character%'; -- 查看字符集
SHOW VARIABLES LIKE 'collation%'; -- 查看校对
root 拥有对整个 MySQL 服务器的完全控制,只有在绝对需要时使用 root 用户
查看所有用户 存放在 mysql 这数据库的 user 表中
SELECT * from mysql.`user`
创建用户 最好使用 CREATE USER,不推荐使用 INSERT 直接操作 USER 表 ,也可以使用 GRANT
CREATE USER test IDENTIFIED BY '123' -- 创建用户,口令自动被加密
RENAME USER test TO test1; -- 重命名,仅 MySQL 5 后支持
删除用户 MySQL 5 之后会删除用户账号及相关权限。之前只删除用户账号,所以需要先用 REVOKE 删除相关权限
DROP USER test1;
设置权限
SHOW GRANTS FOR test; -- 显示拥有的权限
GRANT SELECT ON cloud.* TO test; -- 授予 cloud 数据库所有表上的只读权限
REVOKE SELECT ON cloud.* FROM test; -- 撤销权限
授权范围包括
注意:在使用 GRANT 和 REVOKE 时,用户账号必须存在,但对所涉及的对象没有这个要求。这允许管理员在创建数据库和表之前设计和实现安全措施。
这样做的副作用是,当某个数据库或表被删除时(用DROP语句),相关的访问权限仍然存在。而且,如果将来重新创建该数据库或表,这些权限仍然起作用。
更改口令
SET PASSWORD FOR test = PASSWORD('443'); -- 修改指定用户的密码,必须使用 PASSWORD() 函数加密
SET PASSWORD = PASSWORD('443'); -- 修改当前登录用户的口令
参考《MySQL 必知必会》