./security.md
./mysql_grant.md
../database/start启动与停止.md
docker run -e MYSQL_ALLOW_EMPTY_PASSWORD=yes -ti mysql
初始化数据库
sudo mariadb-install-db --user=mysql --basedir=/usr --datadir=/var/lib/mysql
表的名称绝对不能有引号
最后一行千万不要有逗号
- 示例
CREATE DATABASE menagerie character set utf8mb4;
CREATE TABLE <tablename> (column, column);
create table user (
id SMALLINT unsigned not null auto_increment primary key,
name VARCHAR(50) comment '用户名', -- comment来写注释
)
CREATE TABLE shop (
article INT(4) UNSIGNED ZEROFILL DEFAULT '0000' NOT NULL,
dealer CHAR(20) DEFAULT '' NOT NULL,
price DOUBLE(16,2) DEFAULT '0.00' NOT NULL,
`title` varchar(31) COLLATE utf8mb4_unicode_ci NOT NULL
)- 参考
- DEFAULT: 默认值
- NOT NULL: 不能为空
- COLLATE: 编码
顺序不能错
col_name data_type [NOT NULL|NULL] [DEFAULT {literal|expr}] [AUTO_INCREMENT] [[PRIMARY] KEY]
id int not null auto_increment primary key
drop table <table>; --表整个删除
delete from table; -- 保留表的结构
DESCRIBE <table>;
- INSERT 官方参考
INSERT INTO pet VALUES ('Puffball', 'Diane', 'hamster', 'f', '1999-03-30', NULL);
INSERT INTO pet VALUES ('Puffball', 'Diane'), ('Puffball', 'Diane') # 一次新插入多个数据* insert最后一个数据后面不能加逗号
- mysql --help
mysql -h host -u user -p[passwoed] [<databasename>]
- A条件 AND B条件 OR C条件, AND的优先级比较高,但是为了不弄混,还是加括号()比较好
- DISTINCT是针对结果的。结果数据一致就算是一致
- ORDER BY birth [DESC]; 对某个列进行排序
- ORDER BY name 按照名字排序(不分大小写)
- ORDER BY BINARY name 按照名字排序(区分大小写)
- ORDER BY name, birth DESC; 按照几个字段排序
- NULL 的查询
- SELECT name FROM pet WHERE death is null;
正则查询, 默认不区分大小写
SELECT name FROM pet WHERE name like 'b%': b开头SELECT name FROM pet WHERE name like '_____': 5个字母SELECT name FROM pet WHERE name REGEXP/RLIKE '^b': b开头- '%fy': fy结尾
- '%w%': 包含w
- '_': 一个任意字符
- 区分大小写:
SELECT name FROM pet WHERE name like binary '%w'; .: 匹配任意单个字符串[abc]: abc中任意一个*: 任意数量{5}: 指定5个- ...to be continued
COUNT(*) 求和。 COUNT(field) 会排除field为null的数据
如果 SET sql_mode = 'ONLY_FULL_GROUP_BY' 那COUNT后面必须有group by, 如果 SET sql_mode = '' 那COUNT后面可以没有group by
SELECT [DISTINCT] field FROM table WHERE conditions_to_satisfy ORDER BY column [DESC];
select @min_price:=MIN(price) from shop;
select @min_price;
select * FROM shop WHERE price=@min_price;
CREATE TABLE shirt (
id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
style ENUM('t-shirt', 'polo', 'dress') NOT NULL,
color ENUM('red', 'blue', 'orange', 'white', 'black') NOT NULL,
owner SMALLINT UNSIGNED NOT NULL REFERENCES person(id),
PRIMARY KEY (id)
);
- SHOW DATABASES;
- SHOW TABLES;
- SHOW CREATE TABLE pet;
- SHOW INDEX FROM pet;
- SHOW CREATE TABLE pet\G; # \G 可以让代码变整洁,具体意思以后再看
show full columns from group_group; 查看所有的信息
UPDATE pet SET birth = '1989-08-31' WHERE name = 'Bowser';mysql < batch-file > outfile
-
普通函数
CURDATE: 当前日期CURRENT_DATE: 当前日期CURRENT_TIME: 当前时间(不带日期)DATABASE(): 当前数据库DATE_ADD(CURDATE(), INTERVAL 1 MONTH): 返回下个月的今天。1月29, 30, 31的结果都一样DAYOFMONTH: 返回日期LAST_INSERT_ID: 最后一次插入的数据MAX(column): 最大值MOD(MONTH(CURDATE()), 12) + 1: MOD去模,用来返回下个月的月份MONTH: 返回月份NOW(): 当前时间TIMESTAMPDIFF(YEAR, birth, CURDATE()): 年份。直接比较时间戳去尾,如果跨过了闰年的2月29号,就要和366天比,否则和365天比USER(): 当前用户VERSION(): 查看版本
-
不常用函数
BIT_OR:
-
数学函数
PI(): 3.141592SIN: sin三角函数
- Securing the Initial MySQL Account
mysql> ALTER USER 'root@localhost' IDENTIFIED BY 'new_password';
- Loading Data into a Table 见SQL Statements - Data Manipulation Statements - LOAD DATA Statement
MySQL Programs::Client Programs::mysql Client Commands
mysql> help
\c 取消当前的输入
- 示例
CREATE TABLE child (
id INT,
parent_id INT,
INDEX par_ind (parent_id),
FOREIGN KEY (parent_id)
REFERENCES parent(id)
ON DELETE CASCADE
)- reference的字段,必须需要index
- 如果外键的字段有重复。只要里面一条数据被删除了,那么整个表里面的关联数据都会被删除。
[CONSTRAINT [symbol]] CHECK (expr) [[NOT] ENFORCED]
CREATE TABLE t1
(
CHECK (c1 <> c2),
c1 INT CHECK (c1 > 10),
c2 INT CONSTRAINT c2_positive CHECK (c2 > 0),
c3 INT CHECK (c3 < 100),
CONSTRAINT c1_nonzero CHECK (c1 <> 0),
CHECK (c1 > c3)
);
CREATE TABLE people (
id int,
birth date,
death date,
CONSTRAINT mycheck CHECK(death > birth)
);
DELETE FROM tbl_name
WHERE where_condition
ORDER BY ...
LIMIT row_count
- LOAD DATA Statement
-
例子
LOAD DATA INFILE 'file_name' INTO TABLE tbl_name FIELDS TERMINATED BY ',' ENCLOSED BY """ IGNORE number {LINES | ROWS}
-
\N代表了空置NULL -
example:
LOAD DATA LOCAL INFILE '/path/pet.txt' INTO TABLE pet; LOAD DATA LOCAL INFILE '/path/pet.txt' INTO TABLE pet LINES TERMINATED BY '\r\n';
-
-
-
LEFT JOIN
SELECT * from pet LEFT JOIN event ON pet.name = event.name; 找出每个动物。存在事件就插进去。最多可能pet的行数 x event的行数 -
RIGHT JOIN
SELECT * FROM pet RIGHT JOIN event ON pet.name = event.name; 找出所有的事件,如果有对应的动物,就插进去。如果对应多个,就插入多个。所以最多的行数等于pet的行数 x event的行数 -
INNER JOIN
SELECT * FROM pet INNER JOIN event ON pet.name = event.name; 找出所有的匹配,然后只看里面pet.name == event.name. 如果没匹配上,就不显示。所以最多显示的数量是 pet的数量 × event的数量 -
案例
SELECT pet.name TIMESTAMPDIFF(YEAR, birth, date) AS age, remark FROM pet INNER JOIN event ON pet.name = event.name WHERE event.type = 'litter'; -
INNER JOIN: 把两个表格里面合并起来,只有on的条件满足了才会一起出现,否则就不显示
-
-
UNION Clause
./access_control.md
* 基础: INT(2)
* 可用参数: `UNSIGNED, ZEROFILL, AUTO_INCREMENT`
* `ALTER TABLE tb1 AUTO_INCREMENT = 100;` # 不是自动加1,而是自动加100
* YEAR(4)
-
TIMESTAMP 时间戳类型 插入的时候,会把时间变成时间戳保存,取出的时候,会自动根据链接的时区变成datetime
CREATE TABLE
test7(nint DEFAULT NULL,updateattimestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP )
CREATE TABLE shirts (
name VARCHAR(40),
size ENUM("x-small", "small", "medium", "large", "x-largs")
)
ALTER TABLE shirts MODIFY size ENUM("small", "big");
ERROR 1265 (01000): Data truncated for column 'size' at row 2; /* 如果enum不存在就报错了 */- 实际上数据库用1个字节来保存这个数据,所以速度会快很多
- 注意排序,会根据ENUM的顺序来排序
CREATE TABLE geom (g GEOMETRY); SELECT ST_AsText(g) from geom;
> | POINT(1 1) |
SELECT ST_AsBinary(g) from geom;
> | 010010000 |- 插入数据
insert into testjson values (JSON_ARRAY(1,2,3));
select *, JSON_EXTRACT(json, '$.key1') b from testjson where JSON_EXTRACT(json, '$.key1') is not null;
通用的函数和操作
时间操作相关
- CURTIME
- DATE
从datetime里面或者他的日期
select DATE('2003-12-31 01:02:03'); -> '2003-12-31' -
DATE_ADD
- 基础:
WHERE species = 'dog' IN:SELECT * FROM pet WHERE species IN ('dog', 'cat');
SELECT a,b,a+b INTO OUTFILE '/tmp/result.text'
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
LINES TERMINATED BY '\n'
FROM test_table;- 示例代码
mysqldump -u root -p test --extended-insert=FALSE > test.sql # windows下不正确,因为windows用了UTF-16
mysqldump -u root -p test --extended-insert=FALSE --result-file=test.sql
## 我的习惯
mysqldump \
-u <username> \
--set-gtid-purged=OFF \
--column-statistics=0 \
--result-file result.sql \
--lock-tables=False \
--skip-add-locks \
--net-buffer-length=32k \
<database> <table>
- 选项
--add-locks, --skip-add-locks: dump出来的sql语句, 是否有LOCK TABLES<table>WRITE;--result-file: 保存路径--extended-insert: 是否把所有数据的insert写成一句,默认True--complete-insert: insert语句里面是否带上columns的参数,默认False--net-buffer-length: 32K比较不错.既不会太慢,也不会卡顿
- Performance and Scalability Considerations 性能和企业数据要考虑
It's recommended to use mysqlbackup command of MySQL Enterprise Backup product,
因为mysqldump要考虑索引,io,处理大型数据会很慢
mysql -h localhost -u root -p < ./test.sql # 处理dump出来的
mysql> LOAD DATA LOCAL INFILE 'dump.txt' INTO TABLE mytbl # 处理outfile的结果
-> FIELDS TERMINATED BY ':'
-> LINES TERMINATED BY '\r\n';- How MySQL Uses Indexes
- If there is a choice between multiple indexes, MySQL normally uses the index that find the smallest number of rows(most selective index)
- multiple-column index can be used by the leftmost prefix of the index, (col1, col2, col3) 的联合索引可以用于 (col1), (col1, col2), (col1, col2, col3)
- If a query uses from a table only columns that are included in some index, the selected values can be retrieved from the index tree for greater speed.
- Primary Key Optimization 主键优化
- set primary key not null 设置成非null
- With the InnoDB storage engine, the table data is physically organized to do ultra-fast lookups 主键非常快
- if it does not have an obvious column or set of columns to use as a primary key, create a separate column with auto-increment 必要要有主键
- SPATIAL Index Optimization
- Foreign Key Optimization
- Column Indexes
- Multiple-Column Indexes
- Verifying Index Usage
- InnoDB and MyISAM Index Statistics Collection
- Comparison of B-Tree and Hash Indexes
- Use of Index Extensions
- Optimizer Use of Generated Column Indexes
- Invisible Indexes
- Descending Indexes
- Optimization Overview
- Optimizing SQL Statements
- Database Structure
- Optimizing for InnoDB Tables
- Optimizing for MyISAM Tables
- Optimizing for MEMORY Tables
- Understand the Query Execution Plan
- Controlling the Query Optimizer
- Buffering and Caching
- Optimizing Locking Operations
- Optimizing the MySQL Server
- Measuring Performance
- Examining Thread Information
- ALTER TABLE Syntax
ALTER TABLE score smallint unsigned not null; this will set the default value 0
alter table <table> add <column> <data-type> [after <column>] wer123 ALTER TABLE t1 RENAME t2; ALTER TABLE t2 MODIFY a TYNYINT NOT NULL, CHANGE b c CHAR(20); ALTER TABLE t1 RENAME COLUMN hometown_match TO hometown_match2; /* 重命名 */ ALTER TABLE t2 ADD d TIMESTAMP; ALTER TABLE t2 ADD INDEX (d), ADD UNIQUE (a); ALTER TABLE t2 DROP COLUMN c; 删除列 ALTER TABLE t2 ADD c INT UNSIGNED NOT NULL AUTO_INCREMENT, ADD PRIMARY KEY (c);- Performance and Space Requirements ALTER TABLE use one the the following algorithms (COPY, INPLACE(before 8.0), INSTANT(new in 8.0.12 default)) ALTER 的时候,会复制原先的数据表,此时数据库处于只读状态,不能改写或插入(除非是把一个table移动到另外一个文件夹的RENAME TO操作)
- CREATE INDEX Syntax
- 不能够加双引号,加了会导致报错
CREATE INDEX t1_hometown_match_28b57695 ON t1 (hometown_match); SELECT INDEX_NAME FROM INFORMATION_SCHEMA.STATISTICS WHERE TABLE_SCHEMA = 'test' AND TABLE_NAME="t1"; DROP INDEX index_name on tbl_name
- utf8与utf8mb4的问题
- ALTER DATABASE database_name CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
- ALTER TABLE table_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
- ALTER TABLE table_name CHANGE column_name column_name VARCHAR(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
- SHOW VARIABLES WHERE Variable_name LIKE 'character_set_%' OR Variable_name LIKE 'collation%';
utf8mb4_unicode_ci和utf8mb4_general_ci尽量用前面的
`id` varchar(31) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL;
alter table group_groupapply convert to character set utf8mb4 collate utf8mb4_unicode_ci;
- 参考链接
- mysql使用B+树,是因为磁盘上一次读取的信息很多,只存一个节点有点亏。多以干脆多存几个,减少层级数
- mysql的innodb是直接在叶子节点存了数据(聚集索引),如果对其他的key做索引,会有回表再次查询的问题(为了节约空间)。所以每个表必须要有主键。但是mysql的叶子节点数据也有物理地址啊。给其他的字段创建索引时为什么不直接用物理地址呢?这个物理地址会变化吗
- 主键不要太长,因为其他的索引数据就太大了
- myisam则是保存了物理地址。索引查到数据后直接能读取数据
- 查看占用空间比较大的表
SELECT table_schema, table_name, ROUND((data_length+index_length)/POWER(1024,2),2)
AS tablesize_mb
FROM information_schema.tables
ORDER BY tablesize_mb
DESC LIMIT 20;