总结一下最近学到的MySQL的tips,做个备忘:
INSERT IGNORE 与 INSERT INTO的区别
INSERT IGNORE 与 INSERT INTO的区别就是:INSERT IGNORE会忽略数据库中已经存在 的数据,如果数据库没有数据,就插入新的数据,如果有数据的话就跳过这条数据。INSERT INTO有无数据都插入,如果主键则不插入(而且报错)
insert语句一次可以插入多组值,每组值用一对圆括号括起来,用逗号分隔,如下:
insert into `news`(title, body, time) values('helloworld', 'body 1', now()), ('title 2', 'body 2', now());
下面通过代码说明之间的区别,如下:
create table testtb( id int not null primary key, name varchar(50), age int ); insert into testtb(id, name, age) values(1, "helloworld", 13); //报错“ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'” select * from testtb; insert into testtb(id, name, age) values(1, "helloworld", 13); select * from testtb; insert ignore into testtb(id, name, age) values(1, "aa", 13); select * from testtb; //仍是 1 helloworld 13,因为id是主键,出现主键重复但使用了ignore则错误被忽略 replace into testtb(id, name, age) values(1, "aa", 12); select * from testtb; //数据变为1 aa 12
MySQL多表查询
SELECT * FROM table1,table2 WHERE table1.id=table2.id; SELECT * FROM table1 LEFT JOIN table2 ON table1.id=table2.id; SELECT * FROM table1 LEFT JOIN table2 ON table1.id=table2.id LEFT JOIN table3 ON table2.id=table3.id; 笛卡尔积(交叉连接) 在MySQL中可以为CROSS JOIN或者省略CROSS即JOIN,或者使用',' 如: SELECT * FROM table1 CROSS JOIN table2 SELECT * FROM table1 JOIN table2 SELECT * FROM table1,table2 由于其返回的结果为被连接的两个数据表的乘积,因此当有WHERE, ON或USING条件的时候一般不建议使用,因为当数据表项目太多的时候,会非常慢。一般使用LEFT [OUTER] JOIN或者RIGHT [OUTER] JOIN
IP地址在MySQL数据库中的存储
echo ip2long('192.168.1.38'); C:>php -r "echo ip2long('219.143.8.242');" -611383054 C:>php -r "echo ip2long('192.168.1.38');" -1062731482 C:>php -r "echo ip2long('127.0.0.1');" 2130706433 ========== 在32位的机子上,echo ip2long('192.168.1.38');由于超过32位的最大数,导致输出负数-1062731482。 有两种方法更新为正数: $ip_long = bindec(decbin(ip2long($ip))); #验证OK! 或 $ip_long = = sprintf("%u", ip2long($ip));
mysql> select inet_aton('219.143.8.242'); +----------------------------+ | inet_aton('219.143.8.242') | +----------------------------+ | 3683584242 | +----------------------------+ 1 row in set (0.00 sec) mysql> select inet_ntoa('3683584242'); +-------------------------+ | inet_ntoa('3683584242') | +-------------------------+ | 219.143.8.242 | +-------------------------+ 1 row in set (0.00 sec) mysql> select inet_ntoa(3683584242); +-----------------------+ | inet_ntoa(3683584242) | +-----------------------+ | 219.143.8.242 | +-----------------------+ 1 row in set (0.00 sec) mysql> select inet_aton('192.168.1.38'); +---------------------------+ | inet_aton('192.168.1.38') | +---------------------------+ | 3232235814 | +---------------------------+ 1 row in set (0.00 sec) select inet_aton('219.143.8.242'); select inet_ntoa('3683584242'); select inet_ntoa(3683584242);
两个函数都是根据:A*256*256*256+B*256*256+C*256+D的算法
192*256*256*256+168*256*256+1*256+38 = 3 232 235 814
反过来,从int转换为IP地址分别是php的long2ip()和mysql的INET_NTOA()。
mysql存储这个值是字段需要用int UNSIGNED。不用UNSIGNED的话,128以上的IP段就存储不了了。
传统的方法,创建varchar(15),需要占用15个字节,而改时使用int只需要4字节,可以省一些字节。
PHP存入时:$ip = ip2long($ip);
MySQL取出时:SELECT INET_NTOA(ip) FROM table …
PHP取出时,多一步:$ip = long2ip($ip);
转换以前的数据:
1.把以前的varchar()数据转换为int型的SQL语句:
UPDATE `hx_table` SET ip = INET_ATON(ip) WHERE INET_ATON(ip) is NOT NULL
2.把字段更改为int型:
ALTER TABLE `hx_table` CHANGE `ip` `ip` INT UNSIGNED NOT NULL
程序做相应修改上传,完成。
因此一种是修改PHP程序,使其肯定存入正数。
另一种是将mysql的这个字段使用int,非UNSIGNED,使其可以存入负数。
参考链接:
待续……
《 “MySQL的一些tips总结” 》 有 8 条评论
在MySQL中查询某一个时间区间内的记录(between…and)
`
select * from hockey_stats where game_date between ‘2016-09-11 00:00:00’ and ‘2016-10-11 23:59:00’ order by game_date desc;
select * from hockey_stats where game_date < '2016-01-01 00:00:00';
`
MySQL工具汇总
http://cenalulu.github.io/mysql/mysql-tools-list/
MySQL字段如何设置为「当前/当天」的时间?
https://stackoverflow.com/questions/19246309/how-to-get-current-date-time-in-mysql
`
— 创建时自己填充当前时间 DEFAULT CURRENT_TIMESTAMP
CREATE TABLE `servers`
(
id int(11) NOT NULL PRIMARY KEY auto_increment,
…,
date_time datetime NOT NULL DEFAULT CURRENT_TIMESTAMP
);
— 插入时用当前时间 NOW()
INSERT INTO servers (server_name, online_status, exchange, disk_space, network_shares)
VALUES(‘m1′,’ONLINE’,’exchange’,’disk_space’,’network_shares’, NOW())
`
https://stackoverflow.com/questions/20461030/current-date-curdate-not-working-as-default-date-value
MySQL中如何删除「特定时间之前」的数据?
https://stackoverflow.com/questions/8359457/deleting-records-before-a-certain-date
`
— 固定时间之前
DELETE FROM table_name WHERE column_name < '2011-09-21 08:21:22';
— 删除 1 天之前的数据
delete from table_name where column_name < DATE_SUB(NOW() , INTERVAL 1 DAY)
— 删除 6 月之前的数据
delete from table_name where column_name < DATE_SUB(NOW() , INTERVAL 6 MONTH)
`
https://dba.stackexchange.com/questions/42892/drop-tables-where-the-last-update-is-over-1-week-ago
MySQL中将多列的组合设置为主键的语法
https://dba.stackexchange.com/questions/57548/how-to-set-up-multiple-fields-as-primary-key-in-mysql
https://stackoverflow.com/questions/2642778/multi-column-primary-key-in-mysql-5
https://dev.mysql.com/doc/refman/5.6/en/create-table.html
`
CREATE TABLE yourtable
(
employeeid INT,
blahblah VARCHAR(255),
blahblah2 VARCHAR(255),
recordmonth DATE,
recodrdyear DATE,
PRIMARY KEY (employeeid, recordmonth, recodrdyear)
)
`
[慢查优化]联表查询注意谁是驱动表 & 你搞不清楚谁join谁更好时请放手让mysql自行判定
https://www.cnblogs.com/zhengyun_ustc/p/slowquery1.html
mysql驱动表与被驱动表及join优化
https://blog.csdn.net/qq_20891495/article/details/93744495
`
# 驱动表与被驱动表
先了解在join连接时哪个表是驱动表,哪个表是被驱动表:
1.当使用left join时,左表是驱动表,右表是被驱动表
2.当使用right join时,右表时驱动表,左表是驱动表
3.当使用join时,mysql会选择数据量比较小的表作为驱动表,大表作为被驱动表
在sql优化中,永远是以小表驱动大表。
在以小表驱动大表的情况下,再给大表建立索引会大大提高执行速度。
`
MySql小表驱动大表
https://blog.csdn.net/codejas/article/details/78632883
`
in后面应该跟小表,exists后面应该跟大表。
`
MySQL小表驱动大表
https://blog.csdn.net/lizc_lizc/article/details/86571758
13.MySQL联表查询中的驱动表,优化查询,以小表驱动大表
https://www.jianshu.com/p/6c3020e33d42
项目中常用的19条MySQL优化
https://segmentfault.com/a/1190000012155267
https://juejin.im/entry/5a1bbb386fb9a044fc4475aa
mysql常见的几个SQL性能考虑
https://yuerblog.cc/2016/08/12/consideration-about-mysql-sql-performance/