#附上本脚本参照的菜鸟教程原地址 #通用sql教程 https://www.runoob.com/sql/sql-tutorial.html #mysql教程 https://www.runoob.com/mysql/mysql-tutorial.html #SQL干什么用的? Structured query language, 结构化数据库查询语言, 用来操作数据库的.
use sql27; select * from websites; select name,country from websites; select distinct country from websites; select * from websites where country = 'cn'; #cn居然不分大小写 select * from websites where id = 1;#数值字段不用引号 select * from websites where country = 'cn' and alexa > 50; select * from websites where country = 'cn' or country = 'usa'; select * from websites order by alexa desc; select * from websites order by country,alexa desc;#每个country组按alexa排序 insert into websites (name, url, alexa, country) values('百度', 'https://www.baidu.com/', '4', 'CN'); insert into websites (name, url, country) values('stackoverflow', 'https://stackoverflow.com/', 'IND'); #alexa默认值是0 update websites set alexa='5000', country='usa' where name='菜鸟教程'; update websites set alexa='5000', country='5000'; #没有加where就全部改了 delete from websites where name='facebook' and country='usa'; delete * from websites; #删不掉报错了. 去掉星号idea会提示没有where是不安全的操作. select * from websites limit 2; select top 50 percent * from websites; #不支持顶部百分比查询, Microsoftmysql才支持 select * from websites where name like 'g%'; #小写也能查到啊 select * from websites where name like '%w'; #w结尾的 select * from websites where name like '%oo%'; select * from websites where name like '_oogle%'; select * from websites where name like 'G_o_le'; select * from websites where name regexp '^[gfs]'; #g也不区分大小写的 select * from websites where name regexp '^[a-h]'; select * from websites where name not regexp '^[a-h]'; select * from websites where name regexp '^[^a-h]'; select * from websites where name in ('Google', '菜鸟教程'); select id,name from websites where name in ('Google', '菜鸟教程'); select * from websites where alexa between 1 and 20; select * from websites where alexa not between 1 and 20; select * from websites where (alexa between 1 and 20) and country not in ('usa','ind'); select * from websites where name between 'a' and 'h'; select * from websites where name not between 'a' and 'h'; select * from access_log where date between '2016-05-10' and '2016-05-14'; #不同的数据库 between的范围也不同. 我这两头全部包括了. select name as n, country as c from websites; select name, concat(url, ', ', alexa, ', ', country) as site_into from websites; #concat可以把三列连在一起还能加别名 select w.name, w.url, a.count, a.date from websites as w, access_log as a where a.site_id=w.id and w.name='菜鸟教程';#有三个对应的id就会显示三排数据 select websites.name, websites.url, access_log.count, access_log.date from websites, access_log where websites.id=access_log.site_id and websites.name='菜鸟教程'; select * from access_log; select * from websites; select websites.id, websites.name, access_log.count, access_log.date from websites inner join access_log on websites.id = access_log.site_id; select * from websites inner join access_log on websites.id = access_log.site_id; #和下一条效果一样, 而且inner可以省略 select * from websites, access_log where websites.id=access_log.site_id;#这也是种inner join啊 select * from websites left join access_log on websites.id = access_log.site_id; #左表全有, 右表为NULL. 不知道full join 啥意思, 难道两头为null? select websites.name, access_log.count, access_log.date from websites inner join access_log on websites.id = access_log.site_id order by access_log.count; select w.name, a.count, a.date from websites as w inner join access_log as a on w.id = a.site_id order by a.count; select w.name, a.count, a.date from websites as w left join access_log as a on w.id=a.site_id order by a.count desc; insert into `access_log` (`aid`, `site_id`, `count`, `date`) values('10', '6', '111', '2016-03-09'); select websites.name, access_log.count, access_log.date from websites right join access_log on access_log.site_id=websites.id order by access_log.count desc; select websites.name, access_log.count, access_log.date from websites right join access_log on access_log.site_id=websites.id; select websites.name, access_log.count, access_log.date from websites right join access_log on websites.id =access_log.site_id; select websites.name, access_log.count, access_log.date from access_log right join websites on websites.id =access_log.site_id; #和上面对比发现, on后面的顺序不影响查出的顺序, 而from会影响. #select websites.name, access_log.count, access_log.date from websites full outer join access_log on websites.id = access_log.site_id order by access_log.count desc; #mysql不支持full outer 可以在sql server里面试下. select country from websites union select country from apps order by country; select country from websites union all select country from apps order by country; select country,id from websites union all select country,url from apps order by country; #两列可以, 列数不相同会报错.列名不同也可以,数据类型相同就行 select * from websites; select * from access_log; select * from apps; select country, name from websites where country='cn' union all select country, app_name from apps where country='cn' order by country; #country虽然是一样的, 但是顺序变了.不知道按什么顺序排的 select country, name from websites where country='cn' union all select country, app_name from apps where country='cn'; create table apps2 as select * from apps; #mysql不支持select into, 但支持insert into select insert into apps2 select * from websites; #列数不匹配报错 insert into apps2 select * from apps; select * from apps2; create table apps3 select * from apps; select * from apps3; alter table apps3 add six varchar(30); #six不能加引号 insert into apps3 select * from websites; #只要列数一样,不管你名字直接套过来. create table apps4 select * from apps where 1=0; select * from apps4; insert into apps3 select websites.name, access_log.count, access_log.date from websites left join access_log on websites.id = access_log.site_id; insert into apps3 select websites.id, access_log.count, access_log.date, apps2.id, apps2.url from websites left join access_log on websites.id = access_log.site_id left join apps2 on apps2.id = websites.id; select * from websites; insert into websites(name, country) select app_name, country from apps where id = 1; create table persons ( personID int, LastName varchar(255), FirstName varchar(255), Address varchar(255), City varchar(255) ); drop table persons; create table Persons( ID int not null, lastnName varchar(255) not null, firstName varchar(255) not null, age int ); alter table persons modify age int null; create table persons2( P_ID int not null, LastName varchar(255) not null, FirstName varchar(255), Address varchar(255), City varchar(255), UNIQUE(P_ID) ); alter table persons2 add unique(firstname); #不区分大小写的, 不知道查询页面的蓝色里面的黑色图标是啥意思. 蓝色是unique, 黑色是not null alter table persons2 drop index firstname; #取消unique之后马上变红了, 这个自动检测真是牛 alter table persons2 add constraint zidingyi unique (p_id, lastname); #如何查询表信息, constraint key 这些 alter table persons2 drop constraint zidingyi; #对于MySQL是错误语法 alter table persons2 drop index zidingyi; #mysql用的是index alter table persons2 drop index key; show full columns from persons2; show create table persons2; #这个比上面更全, 可以看约束key信息 alter table persons2 add PRIMARY key(p_id,lastname,firstname); #三列一个主键, 那能一起自增吗. 主键是不能为空的 alter table persons2 drop primary key; insert into persons2(address) values ('aaa'); insert into persons2(p_id) values (111); insert into persons2(p_id) values ('aaa'); alter table persons2 modify column P_ID int null; #有数字的列可以转字符串, 但反过来不行 #表头显示是分大小写的, create里面设置也不分大小写 create table orders( O_ID int not null, orderNo int not null, P_ID int, primary key (o_id), foreign key (p_id) references websites(id)); insert into orders values (1,2,11); alter table orders add foreign key(orderno) references websites(id); #重复设置外键不会报错, 会增加好几个key alter table orders add constraint zidingyi foreign key(p_id) references websites(alexa); alter table orders drop foreign key orders_ibfk_4; show create table orders; #原来未命名的key也可以删除 alter table orders drop key orderno; alter table orders drop primary key; alter table orders modify column p_id varchar(255) null; alter table orders add unique(p_id); alter table orders add primary key(p_id);#有空值不能设置为主键, null会自动变成not NULL alter table orders change p_id p_id int auto_increment;#字符串类型列能否设置为主键, 可以, 不知道还能不能自增, 不能, 只有int才能加自增. unique可以多个null. alter table好多料啊, 有drop, change, modify, add alter table persons2 add constraint chkp check(p_id>0 and city = 'sandes'); select * from persons2; insert into persons2(p_id) values(-1); insert into persons2(city) values('gz'); show create table persons2; alter table persons2 drop check chkp; #mysql里check约束是添加不上去的, 虽然不会报错. alter table persons2 alter city set default 'beijing'; alter table persons2 alter city set default 'jing'; #直接覆盖了 alter table persons2 alter city SET date default getdate(); #报错了, 怎么alter函数? alter table persons2 alter city drop default; CREATE TABLE Orders ( O_Id int NOT NULL, OrderNo int NOT NULL, P_Id int, OrderDate date DEFAULT GETDATE() ); #不能用这个函数啊 create index p on persons(lastnname, firstname); select * from persons; show create table persons; create unique index n on persons(lastnname, firstname); #索引的名字只能有一个, 值可以重复. 那索引是怎么用的, 怎么根据索引来查呢? create index s on persons(lastnname, firstname); alter table persons add index a(firstname, lastnname); alter table persons drop index s; truncate table persons2; #key都还在 alter table persons add dateofbirth date; alter table persons alter column dateofbirth set int; #报错了试下modify alter table persons modify dateofbirth year; show create table persons; alter table persons drop column dateofbirth; alter table persons modify id int auto_increment; #报错提示必须先定义为key alter table persons modify id int auto_increment=100; #没有这个语法,(100)也不行 insert into persons(lastnname, firstname) values('aa','bb'); alter table persons add index q(id); select * from persons; alter table persons drop index n; #那重复key的话, 索引搜出来的是什么? create view aaa as select name, url from websites where name = 'google'; drop view aaa; #加个列都要重新create. view只是个查询结果, 对数据不能修改 select now(), curdate(), curtime(), date(now()), extract(hour_minute from now()), date_sub(now(),interval 10 day), datediff(now(), '2011-11-30'), date_format(now(), '%b %d %Y %h:%i %p'); #小时数以分钟的形式. 语法没错, 没注意前面少了个括号. 只有值的日期部分参与运算, 返回的是天数. create table timeorder( order_date date, order_date2 datetime, order_date3 timestamp); insert into timeorder values(now(), now(), now(), now()); select * from timeorder; alter table timeorder add order_date4 year; set global time_zone = '+8:00';#真的可以用, 设置多几次就可以了, 都不用重启mysql服务吗 flush PRIVILEGES ; show variables like '%time_zone'; select * from persons where id is not null; #null是用is. 运行正常, 不知道为什么会爆红. create table products( p_id int, productname varchar(255), unitprice double, unitsInStock int, unitsOnOrder double ); insert into products values(1,'aaa', 0.1, 1,1); insert into products values(1,'aaa', 0.11, 0.1,null); select * from products; select productname,unitprice*(unitsInStock+unitsOnOrder) from products; select productname,unitprice+unitsOnOrder from products; select productname,unitprice+ifnull(unitsOnOrder,0) from products; select productname,unitprice+coalesce(unitsOnOrder,0) from products;#two or more things coalesce, they come or grow together to form one thing or system. 联合,合并 create table datatype2( char1 character(11), #固定长度 var1 varchar(255), #可变长度 binary1 binary(11), #二进制串是只能输1和2么. 非可变就是说一定会有十一位,其他的用0代替 bool1 boolean, varbinary1 varbinary(5), intA int(5), #怎么整数值还有精度的? 是5个字节不是5位数么,还真是不过是加unsigned zerofill自动补0. 加精度不会改变字节大小 small1 smallint, #精度5就是说最长5位数 intB int, #默认只有10位 intC bigint, #精度19 deci decimal, #不写精度默认是多少呢? 默认没有小数 deci2 decimal(3,1), #一共3位数, 小数点后1位. 整数最多两位, 小数会忽略或者补0. deci3 numeric(3,1), #与decimal相同 flo float, #没说默认是多少. 底下说了默认16 flo2 float(3), real1 real, #近似数值, 尾数精度7, 那不就是个7的float dp double precision, #尾数精度16,那不就是默认float date1 date, time1 time, ts timestamp #interval, array, multiset, xml都不是类型 ); drop table datatype2; show create table datatype2; select * from datatype2; truncate datatype2; insert into datatype2(char1) values('aaaaaaaaaaaaa');#提示太长 insert into datatype2(binary1) values(123456789012); #就是说存的还是十一位字符,不过是以二进制的形式 insert into datatype2(binary1) values('哈哈哈哈哈哈哈哈哈'); #十一个汉字是不行的, 不知道存进去是什么编码 insert into datatype2(bool1) values('哈');#只能存一个字节的整数大小 insert into datatype2(intA) values(111111.91); #自动进1 alter table datatype2 modify column intA int(10) unsigned zerofill; alter table datatype2 modify column small1 smallint(10) unsigned zerofill; insert into datatype2(small1) values(555); #默认也是五位补零, 加精度没用. insert into datatype2(deci2) values(22.2222); insert into datatype2(deci3) values(22); insert into datatype2(real1) values(22.2222222222222); #尾数精度7, 这都不止七位了呀. 反正float和real 不能精确存储数值. 噢 就是说只能精确到小数点后第7位数字. 不对, 好像是一共七位 insert into datatype2(flo, real1) values(22.22222222222222, 22.2222222222222); # insert into datatype2(flo,flo2) values(22.22222222222222, 22.2222222222222); # insert into datatype2(flo,flo2) values(22.3333333333333, 22.33333333333333); # insert into datatype2(dp,flo) values(22.3333333333333, 22.33333333333333); # select flo+real1 from datatype2; #加出来果然不准了,但每次insert结果都一样 select flo2+flo from datatype2; #不知道为什么float后面也是精确到五位小数,我设置的3啊 select flo2+dp from datatype2; #double precision也是小数点后五位 select flo+dp from datatype2; #float和float(3)好似没分别 #原来上面是通用数据类型, 下面是mysql专用的. create table mtext( char1 char(5), var1 varchar(255), text1 text, #65535 ttext tinytext, #255 mtext mediumtext, #16,777,215字符串 ltext longtext, #4,294,967,295 blob1 blob,#binary large objects, 最多65535字节的数据 lblob longblob, #4,294,967,295 enum1 enum('x'), #最多可以列出65535, 插入别的值就是空. set1 set('x','y','a') #只能列64个选项, 而且不能插入1,是只能同类型还是不支持整数 ); select * from mtext; alter table mtext modify column set1 set('x','y','z'); #不支持整数 1,2,3 insert into mtext(set1) values('x,y,z'); #要这样存,查出来也有逗号 create table mdate( d date, dt datetime, ts timestamp,#自动设置为当前的日期与时间,而不是null. 而且支持多种格式的类型 t time, y year ); insert into mdate values(now(), now(), now(),now(),now()); insert into mdate values(now(), now(), 111111,now(),now()); #自动识别年月日 insert into mdate values(now(), 11111111, 20111111,now(),now()); #ts只支持70-38 insert into mdate(d) values(now()); select * from mdate; create table mnum( ti tinyint(5), si smallint(5), #只能放4位数字,无论正负. 不是哦, 可以放5位2.带符号是32767. 那如何不带符号呢 mi mediumint(5), i int(5), bi bigint(5), fi float(5), #没有小数了, 整数部分会显示大于5位 di double(5,5), deci decimal(5,5) ); select * from mnum; insert into mnum values (111.999, 22222, 5555555, 1.9, 1.9, 444444444.4444444, null, 0.1, 0.444444); insert into mnum values (111.999, 22222, 5555555, 11111111, 1.9, 444444444.4444444, 0, 0, 0.444444); #两个问题, 小数类型不能添加带整数的? 为什么float后面自动加了三个0? insert into mnum values (1,1,1,1,1,1,0,0,0); alter table mnum add column fi2 float(5,5); #小数点后面只会显示5位 alter table mnum modify column ti tinyint(5) unsigned zerofill; #怎么其他列也填充0了? 难道是idea的bug? show create table mnum; create table mnum2( fi float(5,5), di double(5,5), deci decimal(5,5) ); drop table mnum2; insert into mnum2 values(00000000000.000000000000,0,0); insert into mnum2 values(1,1,1); select * from mnum2; #为啥这三个只能放小数了. 我懂了, 5,5会导致整数部分没有位置了 insert into mnum2 values(0.5555555,0.55555555,0); create table mnum3( deci decimal(5,5) ); insert into mnum3 values(0.333333333); select * from mnum3; #sql函数 aggregate和scalar select * from access_log; select avg(count) as countaverge from access_log; #默认是0,不知道有null会怎样. 有null的话这一行就不会计算进去了. alter TABLE access_log modify count int default null; #null不会转成0. show create table access_log; select count(count) as nums from access_log where site_id=3; #null不算. 为什么要加别名nums呢? select count(count) from access_log where site_id=3; select count(*) from access_log; #就是总行数, 那一行全部是null还算么. 算的 insert into access_log values(null,null,null,null); alter table access_log modify site_id int null; alter table access_log drop primary key; select count(distinct site_id) from access_log; #null不算的 select name from websites limit 1; select name from websites order by name; select name from websites order by convert(name using gbk); #汉字还是没有排在字母前面 #mysql里的汉字是用什么排序的? 解决方式有两个:1.修改数据库字符集,把utf-8改为gbk。2.修改sql语句:把select * from user order by name desc 改为 select * from user order by convert(name using gbk) desc 这样排序的字段就按照字母顺序排列了。 估计是按utf8编码顺序排的 select * from websites; select max(alexa) from websites; select max(name) from websites; #不知道为什么菜鸟教程是最大的. 减成一个字菜它还是最大的,难道是按首字母拼音排序? 改成我之后百度变成最大的了, 肯定不是首字母拼音. select max(convert(name using gbk)) from websites; #为什么这里我会是最大 select sum(country) from websites; #汉字加出来是0, 字母也是, 数字会自动转型,1,1啊,都会识别到1. 只能识别到最前面的一个数字. select sum(alexa) from websites; # select websites.name, count(access_log.aid) as nums from access_log left join websites on access_log.site_id = websites.id group by websites.name; select * from access_log left join websites on access_log.site_id=websites.id group by websites.name; #必须得以count连用. 提示nonaggregated, 按组来进行函数处理 select * from access_log left join websites on true; #每个和每个都配了一遍 select * from access_log left join websites on false; #每个都是NULL select websites.name, websites.url, sum(access_log.count) as nums from access_log inner join websites on access_log.site_id=websites.id group by websites.name having sum(access_log.count) > 200; #报错了, 因为url即不是分类名, 又没有参与分组运算. select * from websites; show create table websites; select websites.name, sum(access_log.count) as nums from websites inner join access_log on access_log.site_id=websites.id where websites.alexa < 200 group by websites.name having sum(access_log.count) > 200; #分组之后进行判断哪些组的总数大于200. 这段话变成了下面查询语句的标题 select websites.name, websites.url from websites where not exists(select count from access_log where websites.id = access_log.site_id and count > 200); #查出来的count变成了行. 就是选中不符合第二个select的列, 那我为什么不直接一个select搞定呢? select websites.name, websites.url from websites where websites.id = access_log.site_id and count > 200;#这样是不行的,表名报错, 必须声明在from后面 select websites.name, websites.url from websites left join access_log on websites.id = access_log.site_id where not (count > 200); #exists效果一样, 但not exists就不知道是咋个回事. 不符合查询条件的怎么这么多. != 两个条件取反也不行. 噢not exists那个语句它还是基于的websites表, 所以要用left join. 但他只能表示大于或小于,还有一些非数字的它查不出来. not 只是把小于变大与. 给count加个exists也不行, 好像只能套个完整的查询语句. select * from websites; select * from access_log; select ucase(name), lcase(url) from websites;#插进去的数据不分大小写么. 分的 insert into websites(name) values('aA'); select mid(name,1,4) from websites; #中文也是四个字符,从1到4 select length(name) from websites; #字节数, 一个汉字三个字节. QQ APP长度是6; 百度长度是6. select * from products; select round(unitprice, 2) from products; #round返回值编程一个bigint? 不是double么,表头上有写. select name, url, date_format(now(), '%Y-%m-%d') as date1 from websites; #除了date_format还有其他format么 #学完了才发现是sql教程, 不是mysql教程.下面是mysql select * from websites; update websites set name='百度2' where id=8; delete from websites where name='stackoverflow'; #没加where直接删表\ select * from websites where name like '%e'; select name from websites union all select country from apps order by name DESC; #from后面可以加where SET NAMES utf8; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for `employee_tbl` -- ---------------------------- DROP TABLE IF EXISTS `employee_tbl`; CREATE TABLE `employee_tbl` ( `id` int(11) NOT NULL, `name` char(10) NOT NULL DEFAULT '', `date` datetime NOT NULL, `singin` tinyint(4) NOT NULL DEFAULT '0' COMMENT '登录次数', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of `employee_tbl` -- ---------------------------- BEGIN; INSERT INTO `employee_tbl` VALUES ('1', '小明', '2016-04-22 15:25:33', '1'), ('2', '小王', '2016-04-20 15:25:47', '3'), ('3', '小丽', '2016-04-19 15:26:02', '2'), ('4', '小王', '2016-04-07 15:26:14', '4'), ('5', '小明', '2016-04-11 15:26:40', '4'), ('6', '小明', '2016-04-04 15:26:54', '2'); COMMIT; SET FOREIGN_KEY_CHECKS = 1; select * from employee_tbl; select name, count(*) from employee_tbl group by name; #这个名字有几行记录 select name, sum(singin) as singin_count from employee_tbl group by name with rollup; #每个组的总数加起来. select coalesce(name, '总数'), sum(singin) as singin_count from employee_tbl group by name with rollup; #coalesce null用总数代替的name列 select name from employee_tbl where name regexp '^小'; select name from employee_tbl where name regexp '丽$'; select name from employee_tbl where name regexp '王'; select name from employee_tbl where name regexp '^[小eiou]|ok$'; create table trans( id int(5) ); select * from trans; begin; insert into trans value(5); insert into trans value(6); commit; begin; insert into trans value(8); rollback;#begin后, rollback 之前还是可以查到刚插入的数据. 直接全部roll完了, 不管你savepoint set autocommit = 1; #默认是1, 是0的话还可以roll回去,不需要begin. savepoint savepoint_name; rollback to savepoint_name; release savepoint savepoint_name; select * from trans; alter table trans add i int first; alter table trans add i2 int after i; alter table trans modify i char(10) after id; #菜鸟教程说modify可以用first和after, 可是modify不是已经指定了列名么. 当我没说 alter table trans change j i bigint after i2;#不加类型不行 alter table trans modify i bigint not null default 100; #有null值不能设置 alter table trans alter i set default 1000; alter table trans alter i drop default ; alter table trans engine = MYISAM; alter table trans rename to trans2; show create table trans2; create unique index a on trans2(i);#这个a不用加引号的. 另外加反引号是为了和关键字区分. 表名和库名一般都要加以防万一 alter table trans2 add unique index b(i); #alter也可以加. 可以add 居然不能drop alter table trans2 drop index b; #噢 可以drop, 要去掉列名 drop index a on trans2; show index from trans2; #\G,命令应该是控制台用的 create temporary table trans3 as( select * from trans2 limit 0,1000 ); select *from trans3; show create table trans3; CREATE TABLE `trans4` ( `i2` int(11) DEFAULT NULL, `id` int(5) DEFAULT NULL, `i` char(10) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 INSERT INTO trans4 SELECT i3, id, i FROM trans2; #哇这都没有用values.表名不对没事,类型不对就不行了. select * from trans4; select * from trans2; alter table trans2 change i3 i3 char; select version(); select database(); select user(); show status; show variables; alter table trans2 auto_increment=100; show create table trans2; insert into trans2 value(1,1,1); insert into trans2 value(null,null,null); select * from trans2; #都不知道哪个是主键,所以没有自增 #函数太多了,啥功能都有, 自查 #https://www.runoob.com/mysql/mysql-functions.html #附上牛客网在线练习题, 线上练习sql小试牛刀 #https://www.nowcoder.com/activity/oj?tab=1