Code:https://github.com/lotapp/BaseCode/tree/master/safehtml
本周须要自行研究学习的任务贴一下:前端
数据库系列去年就开始陆陆续续的发文,这周任务简单带过,概念部分我更新了一下,其余部分看扩展吧~mysql
引用百科的一段抽象
描述:git
“关系型数据库,是指采用了关系模型来组织数据的数据库,其以行和列的形式存储数据,以便于用户理解,关系型数据库这一系列的行和列被称为表,一组表组成了数据库。用户经过查询来检索数据库中的数据,而查询是一个用于限定数据库中某些区域的执行代码。关系模型能够简单理解为二维表格模型,而一个关系型数据库就是由二维表及其之间的关系组成的一个数据组织。”github
通俗讲就是:现实中的东西抽象成一个个关系,而后存储在一张张行列组成的表中,这些表就组成了关系型数据库面试
PS:重点就是各数据之间的
关系
(Join)redis
最经典的莫过于:MySQL
、SQLServer
、PostgreSQL
、SQLite
、Oracle
sql
先看看传统数据库的好处:数据库
最典型的特征就是:事物的ACID特性express
PS:抽象的就不说了,举个例子来讲明
ACID
:
化学反应不可再分的基本微粒
能量守恒
来理解国家互不干涉内政
交易留的底单
,这个就是持久化的表现保留字段
也容易由于预留名的不肯定性容易出错主从复制
,读数据在Salver
进行到没啥事,可是大量写数据库怼到Master
上去就吃不消了,必须得加主数据库了。数据不一致
(一样数据在两个主数据库更新成不同的值),这时候得结合分库分表,把表分散在不一样的主数据库中。扩充:如今对修改表结构是这么的解决方案:
PS:虽然都是借助工具来操做但原理仍是要了解下:
先建立新表,而后旧表中建立一个触发器(处理产生的新数据),而后把一条条数据转移到新表中,接着删除旧表,更名新表
(和旧表名同样)
引用百科一段抽象
描述:
“非关系型数据库,又被称为NoSQL(Not Only SQL ),主要是指非关系型、分布式、不提供ACID的数据库设计模式”
通俗化讲就是:为了弥补SQL的不足而建立的(能够逆推NoSQL的优点)
PS:你能够理解为:NoSQL就是对原来SQL的扩展补充(
NewSQL
=SQL + NoSQL
)
先说说优点:
NoSQL的特性就是CAP
:
PS:CAP是分布式系统须要考虑的三个指标,数据共享只能知足两个而不可兼得:
表明:传统关系型数据库
若是想避免分区容错性问题的发生,一种作法是将全部的数据(与事务相关的)都放在一台机器上。虽然没法100%保证系统不会出错,但不会碰到由分区带来的负面效果(会严重的影响系统的扩展性)
做为一个分布式系统,放弃P,即至关于放弃了分布式,一旦并发性很高,单机服务根本不能承受压力。像不少银行服务,确确实实就是舍弃了P,只用高性能的单台小型机保证服务可用性。(全部NoSQL数据库都是假设P是存在的)
表明:Zookeeper
、Redis
(分布式数据库、分布式锁)
PS:NoSQL大部分都是CP
相对于放弃“分区容错性”来讲,其反面就是放弃可用性。一旦遇到分区容错故障,那么受到影响的服务须要等待数据一致
(等待数据一致性期间系统没法对外提供服务)
表明:DNS数据库
(IP和域名相互映射的分布式数据库
,联想修改IP后为何TTL
须要10分钟左右保证全部解析生效)
放弃强一致,保证最终一致性。全部的NoSQL
数据库都是介于CP
和AP
之间,尽可能往AP
靠
PS:传统关系型数据库注重数据一致性,而对NoSQL来讲可用性和分区容错性优先级高于数据一致性
不一样数据对一致性要求是不同的,eg:
传统关系型数据库通常都是使用悲观锁的方式,可是例如秒杀这类的场景就玩不转了,这时候每每就使用乐观锁了(CAS机制),CAP不能同时知足的时候也就剩下这两个方案了:
分布式事物来保证数据一致性
了(这就是问什么项目里面常常提到的缘由)Redis
的AOF
)经常使用的已经加粗:
LevelDB
和RocksDB
也是比较高效的解决方案pika
(redis的补充)能够解决Redis容量过大的问题tinydb
sonic
很火RedisGraph
Dgraph
、Beam
PS:项目中最经常使用的其实就是Redis
、Elasticsearch
、MongoDB
最早接触的是SQLServer,然后才是MySQL系,下面我尽可能使用通用SQL
来讲说传统概念:
create、drop、alter
insert、delete、update、select
grant
(受权)、revoke
(回收)PS:CURD
(定义了用于处理数据的基本原子操做):建立(Create)更新(Update)读取(Retrieve)删除(Delete)操做
官方文档:
以MariaDB
为例,简单列举下经常使用类型:(倾体说明和MySQL
不同)
char()
:不区分字符大小写类型的字符串,max:255个字符
varchar()
: 不区分字符大小写类型的字符串
utf8编码下最多支持21843个字符
)SQLServer
的nvarchar
text
:不区分字符大小写的不限长字符串
单选值
多选值
MySQL系
独有,SQLServer
没有SQLServer
是bit
MySQL
的tinyint(1)
tinyint
:微小整型(1字节,8位)
[-2^7, 2^7)
(-128 ~ 127
)[0, 2^8)
(0 ~ 255
)0 ~ 65535
PS:SQLServer中没这个类型
int
(4bytes,32bit)
[-2^31, 2^31)
,[-2147483648,2147483648)
[0, 2^32)
,[0,4294967296)
bigint
(8bytes,64bit)
[-2^63, 2^63)
[0, 2^64)
double
:双精度浮点数(8字节)
SQLServer
的float
类型至关于MySQL
的double
decimal
:精确小数类型(比double更精确)
decimal(位数,小数点位数)
decimal(3,2)
=> x.xx
MySQL
同样)
year(2)
:00~99(1bytes)
year(4)
:0000~9999(1bytes)
SQLServer没有这个类型
datetime
:既有时间又有日期(8bytes)timestamp
:时间戳(4bytes)【精度更高】null
| not null
default xxx_value
primary key
unique key
unsigned
(MySQL系独有)auto_increment
(通常只用于整型,MSSQL是identity
)
last_insert_id()
primary key(xx,...)
unique key(xx,...)
index index_name (xx,...)
PS:如今新版本数据库兼容了SQLServer的nvarchar
写法(执行成功后数据类型变成varchar
)【不推荐使用】
课后拓展:
MySQL:char、varchar、text的区别
create database [if not exists] db_name;
drop database [if exists] db_name;
create table [if not exists] tb_name(列名1,数据类型 修饰符,列名2,数据类型 修饰符);
drop table [if exists] db_name.tb_name;
alter table tb_name add 列名 数据类型 修饰符 [first | after 列名];
[first | after 列名]
alter table tb_name change 旧列名 新列名 类型 类型修饰符
alter table tb_name modify 列名 类型 类型修饰符
alter table tb_name alter 列名 set default df_value
alter table tb_name drop 字段名
create index index_name on tb_name(列名,...);
)
alter table tb_name add index [ix_name] (列名,...);
alter table tb_name add unique [uq_name] (列名,列名2...);
drop index index_name on tb_name
)
alter table tb_name drop index index_name;
alter table tb_name drop index uq_name;
通俗讲:SQL_Mode就是设置SQL语法检测的级别
MariaDB 5.x的SQLMode通常是空(没什么约束)
PS:
select version();
能够查看DB的版本,select @@sql_mode;
能够查看SQL_Mode的值
MySQL 5.7.27的SQLMode默认是:ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
简单解析一下:
ONLY_FULL_GROUP_BY
:使用group by
时查询的字段必须是group by
子句的列
select count(url),name from file_records group by url;
STRICT_TRANS_TABLES
:对全部支持事物类型的表作严格约束(线上版本通常都是这个)NO_ZERO_IN_DATE
和NO_ZERO_DATE
:防止0000-00-00
插入日期中ERROR_FOR_DIVISION_BY_ZERO
:分母为0则报错(默认是警告)NO_AUTO_CREATE_USER
:建立用户的时候必须identified by 'pass'
来指定密码
create user bryan@'%' identified by '含大小写字母+数字的密码';
NO_ENGINE_SUBSTITUTION
:建表的时候指定不可用存储引擎会报错PS:项目开发通常设置为traditional
(使用传统模型,不容许对非法值作插入操做),线上通常使用strict_trans_tables
来提升并发(阿里云默认值)
以Ubuntu为例:sudo vi /etc/mysql/mysql.conf.d/mysqld.cnf
(sql_mode='strict_trans_tables'
)
而后重启mysql使配置生效:
sudo systemctl restart mysql
效果:
PS:从MySQL8开始,可经过set persist
命令将全局变量的修改持久化到(/var/lib/mysql/mysqld-auto.cnf
)配置文件中
eg:
set persist sql_mode='strict_trans_tables';
-- 若是存在就删除数据库 drop database if exists safe_db; -- 建立数据库 create database if not exists safe_db;
-- 若是存在就删除表 drop table if exists safe_db.users; -- mysql> help create table(低版本的默认值不支持函数) -- 建立表 create table users(字段名 类型 修饰符,...) create table if not exists safe_db.users ( id int unsigned auto_increment, -- 主键,自增加【获取ID:last_insert_id()】 username varchar(20) not null, password char(40) not null, -- sha1:40 email varchar(50) not null, ucode char(36) not null, -- uuid createtime datetime not null default now(), updatetime datetime not null default now(), datastatus tinyint not null default 0, -- 默认值为0 primary key (id), -- 主键可多列 unique uq_users_email (email), index ix_users_createtime_updatetime (createtime, updatetime) -- 索引,不指定名字默认就是字段名 ) -- 表选项 -- engine = 'innodb', -- 引擎 -- character set utf8, -- 字符集 -- collate utf8_general_ci, -- 排序规则 ;
-- 修改表 mysql> help alter table -- 3.1.添加一列 alter table tb_name add 列名 数据类型 修饰符 [first | after 列名] alter table safe_db.users add uid bigint not null unique first; -- MSSQL没有[first | after 列名] -- 在email后面添加手机号码列 -- 手机号不会用来作数学运算,varchar能够模糊查询(eg:like ‘138%’) -- 牵扯到国家代号时,可能出现+、-、()等字符,eg:+86 alter table safe_db.users add tel varchar(20) not null after email; -- 3.2.删除一列 alter table tb_name drop 字段名 alter table safe_db.users drop uid; -- 3.3.添加索引 alter table tb_name add index [ix_name] (列名,...) alter table safe_db.users add index ix_users_ucode (ucode); -- 不指定名字默认就是字段名 -- add index (ucode, tel); -- 不指定索引名字,默认就是第一个字段名 -- 添加惟一键 alter table tb_name add unique [uq_name] (列名,列名2...) alter table safe_db.users add unique uq_users_tel_ucode (tel, ucode); -- add unique (tel, ucode);-- 不指定索引名字,默认就是第一个字段名 -- 3.4.删除索引 alter table tb_name drop index ix_name alter table safe_db.users drop index ix_users_ucode; -- 删除索引(惟一键) alter table tb_name drop index uq_name alter table safe_db.users drop index uq_users_tel_ucode; -- drop index tel; -- 惟一键的索引名就是第一个列名 -- 3.5.修改字段 -- 1.修改字段名:`alter table tb_name change 旧列名 新列名 类型 类型修饰符` -- 此时必定要从新指定该列的类型和修饰符 alter table safe_db.users change ucode usercode char(36); -- 2.修改字段类型 alter table safe_db.users modify username varchar(25) not null; -- 3.添加默认值:`alter table tb_name alter 列名 set default df_value` alter table safe_db.users alter password set default '7c4a8d09ca3762af61e59520943dc26494f8941b';
示例服务器:SQLServer 2014
use master --存在就删除 if exists(select * from sysdatabases where Name = N'safe_db') begin drop database safe_db end --建立数据库(简化版:create database safe_db) create database safe_db on primary --数据库文件,主文件组 ( name ='safe_db_Data', --逻辑名 size =10 mb, --初始大小 filegrowth =10%, --文件增加 maxsize =1024 mb, --最大值 filename =N'D:\Works\SQL\safe_db_data.mdf'--存放路径(包含文件后缀名) ) log on --日记 ( name ='safe_db_Log', size =5 mb, filegrowth =5%, filename =N'D:\Works\SQL\safe_db_log.ldf' ); -- 切换数据库 use safe_db;
--存在就删除表 if exists(select * from sysobjects where name = N'users') begin drop table users end -- safe_db.dbo.users create table users ( id int identity, -- 主键,自增加 username nvarchar(20) not null, email varchar(50) not null, password char(40) not null, -- sha1 ucode char(36) not null default newid(), -- guid createtime datetime not null default getdate(), updatetime datetime not null default getdate(), datastatus tinyint not null default 0, -- 默认值为0 primary key (id), -- 主键可多列 unique (email), index ix_users_createtime_updatetime (createtime, updatetime) -- 索引 );
-- 3.1.添加一列 alter table tb_name add 列名 数据类型 修饰符 -- 在email后面添加手机号码列 alter table users add tel varchar(20) not null; -- 3.1.1.添加含惟一键的列 -- 先添加列 alter table users add uid bigint not null -- 再添加约束 alter table tb_name add constraint uq_name alter table users add constraint uq_users_uid unique (uid); -- 自定义名称 -- 3.1.2.定义和约束一步走(系统设置名字) -- alter table users -- add uid bigint not null unique; -- 默认名称 -- 3.2.含惟一键的列 -- 3.2.1.删除约束 alter table tb_name drop constraint uq_name if exists(select * from sysobjects where name = 'uq_users_uid') alter table users drop constraint uq_users_uid; -- 3.2.2.删除列 alter table tb_name drop column 字段名 alter table users drop column uid; -- 3.3.修改字段 -- 3.3.1.修改列名:exec sp_rename '表名.旧列名','新列名'; exec sp_rename 'users.ucode', 'usercode'; -- 3.3.2.修改字段类型 alter table users alter column username varchar(25) not null; -- 3.3.3.添加默认值:`alter table tb_name alter 列名 set default df_value` alter table users add default '7c4a8d09ca3762af61e59520943dc26494f8941b' for password;
PS:SQL Server默认端口为TCP 1433
简单列举下上面的区别(欢迎补充):
auto_increment
,MSSQL是identity
unsigned
,MSSQL不能够直接设置无符号整型,须要经过约束之类的来限制alter table
的时候,MSSQL没有[first | after 列名]
,并且语法差异也挺大select语句执行流程:
from 表
[inner|left|right] join 表 on 条件
where 条件
group by 字段
分组
,以用作聚合
运算having 条件
group by
)后的结果进行过滤order by 字段 [asc|desc]
asc
)select 字段
limit [偏移量,]显示数量
-- 4.1.插入 help insert -- 自增加主键和默认值的字段能够不写 insert into safe_db.users(username, password, email, tel, usercode, createtime, updatetime, datastatus) values ('test', '7c4a8d09ca3762af61e59520943dc26494f8941b', 'test@qq.com', '18738002038', uuid(), now(), now(), 1); -- 批量插入 insert into safe_db.users(username, password, email, tel, usercode, createtime, updatetime, datastatus) values('xxx', '7c4a8d09ca3762af61e59520943dc26494f8942b', 'xxx@qq.com', '13738002038', uuid(), now(), now(), 0),('mmd', '7c4a8d09ca3762af61e59520943dc26494f8941b', 'mmd@qq.com', '13718002038', uuid(), now(), now(), 1),('小张', '7c4a8d09ca3762af61e59520943dc26494f8941b', 'zhang@qq.com', '13728002038', uuid(), now(), now(), 1); -- 4.2.修改 help update update safe_db.users set datastatus=99, updatetime = now() where username = 'mmd'; -- 必定要有where条件!开发中通常都是先写where条件再写update -- 4.3.删除 -- 删除数据(自增加不重置)help delete; delete from safe_db.users where datastatus = 0; -- 删除所有数据(自增加重置)help truncate; truncate table safe_db.users;
file_records
的建表语句我放在附录了,这边只谈语法
PS:查询相关的帮助文档:
help select
1.查询来源url
use safe_db; -- 查询来源url(去重后) select distinct url from file_records; -- 查询来源url(分组方式) select url from file_records group by url;
2.统计url出现的次数
-- 分别统计一下url出现的次数(分组+聚合) -- 分组通常都和聚合函数一块儿使用 select url, count(*) as count from file_records group by url; -- 分别统计一下url出现的次数大于1次的url(删除的不统计) select url, count(*) as count from file_records where datastatus = 1 -- 99表明删除的数据 group by url having count > 1; -- 在group by的结果上筛选
3.统计一下url出现的次数并查出对应的id
-- 分别统计一下url出现的次数并查出对应的id select group_concat(id) as ids, url from file_records group by url;
4.查询上传文件的用户详细信息,并按文件名降序排序
-- 内链接查询 innet join tb_name on 关联条件 select file_records.id, users.id as uid, users.username, users.email, file_records.file_name, file_records.md5, inet_ntoa(file_records.ip) as ip, file_records.url from users inner join file_records on file_records.user_id = users.id -- 链接条件 where users.datastatus = 1 and file_records.datastatus = 1 order by file_records.file_name desc; -- 文件名降序排序
5.查询前五条文件上传信息
-- MySQL没有`select top n`语法,可使用 limit来实现,eg:top 5 select * from file_records limit 5; -- limit 0,5
6.分页查询相关
-- 分页查询 -- page:1,count=5 ==> 0,5 ==> (1-1)*5,5 -- page:2,count=5 ==> 5,5 ==> (2-1)*5,5 -- page:3,count=5 ==> 10,5 ==> (3-1)*5,5 -- 推理:limit (page-1)*count,count select file_records.id, users.id as uid, users.username, users.email, file_records.file_name, file_records.md5, inet_ntoa(file_records.ip) as ip, file_records.url from file_records inner join users on file_records.user_id = users.id limit 0,5; -- limit后面跟表达式就会报错 select file_records.id, users.id as uid, users.username, users.email, file_records.file_name, file_records.md5, inet_ntoa(file_records.ip) as ip, file_records.url from file_records inner join users on file_records.user_id = users.id limit 5,5; -- limit (2-1)*5,5; -- limit错误写法 -- limit要放在最后 select file_records.id, users.id as uid, users.username, users.email, file_records.file_name, file_records.md5, inet_ntoa(file_records.ip) as ip, file_records.url from file_records inner join users on file_records.user_id = users.id order by username desc, file_name desc limit 10,5; -- 先order by排完序,而后再取第三页的5个数据
7.链接查询
-- 查找一下历来没上传过文件的用户 -- right join:以右边表(users)为基准链接 select file_records.id as fid, users.id as uid, users.username, users.email, file_records.file_name, file_records.md5, inet_ntoa(file_records.ip) as ip, file_records.url from file_records right join users on file_records.user_id = users.id where users.datastatus = 1 and file_records.id is null order by username desc, file_name desc; -- 自链接案例: -- 二级联动 p:province,c:city,a:area -- 前端通常都会显示省级信息,用户选择后能够得到对应的二三级信息 select c.name, a.name from city_infos as c inner join city_infos as a on a.pcode = c.code where c.pcode = '320000'; -- pcode设置为索引 -- 经过省名称查询 select p.name, c.name, a.name from city_infos as c inner join city_infos as p on c.pcode = p.code inner join city_infos as a on a.pcode = c.code where p.name = '江苏省';
-- 简单提一下视图: -- 建立视图 create view view_userinfo as select id, username, password, email, tel, datastatus from safe_db.users; -- 查询视图 select id, username, password, email, tel, datastatus from safe_db.view_userinfo; -- 删除视图 drop view if exists view_userinfo;
知识点:
-- 把ip转换成int select inet_aton('43.226.128.3'); -- inet6_aton() -- 把int转换成ip select inet_ntoa('736264195'); -- inet6_ntoa() ipv6 -- 将多个字符串链接成一个字符串 select concat(user_id, ',', file_name, ',', ip, ',', url) as concat_str from file_records; -- 将多个字符串链接成一个字符串+能够一次性指定分隔符 select concat_ws(',', user_id, file_name, ip, url) as concat_str from file_records; -- 在有group by的查询语句中,select指定的字段要么就包含在group by语句的后面,做为分组的依据,要么就包含在聚合函数中 -- group_concat():将group by产生的同一个分组中的值链接起来,返回一个字符串结果 select group_concat(file_name) as file_name, url, count(*) from file_records group by url; -- having通常对group by的结果进行筛选,where是对原表进行筛选 select group_concat(file_name) as file_name, group_concat(url) as url, count(*) as count from file_records group by url having count >= 3; -- 四舍五入到指定位数 select round(3.12345, 4); -- 存小数数据为了避免损伤精读通常都是转成整数,eg:3.1415 ==> 整数:31415,倍数:10000
数据构造:
-- 编号,文件名,文件MD5,Meta(媒体类型),当前用户,请求IP,来源地址,请求时间,数据状态 drop table if exists safe_db.file_records; create table if not exists safe_db.file_records ( id int unsigned auto_increment primary key, file_name varchar(100) not null, md5 char(32) not null, meta_type tinyint unsigned not null default 1, user_id int unsigned not null, ip int unsigned not null, url varchar(200) not null default '/', createtime datetime not null, -- default now(), datastatus tinyint not null default 0 ); -- 能够插入2~3次(方便下面演示) insert into safe_db.file_records(file_name, md5, meta_type, user_id, ip, url, createtime, datastatus) values ('2.zip', '3aa2db9c1c058f25ba577518b018ed5b', 2, 1, inet_aton('43.226.128.3'), 'http://baidu.com', now(), 1), ('3.rar', '6f401841afd127018dad402d17542b2c', 3, 3, inet_aton('43.224.12.3'), 'http://qq.com', now(), 1), ('7.jpg', 'fe5df232cafa4c4e0f1a0294418e5660', 4, 5, inet_aton('58.83.17.3'), 'http://360.cn', now(), 1), ('9.png', '7afbb1602613ec52b265d7a54ad27330', 5, 4, inet_aton('103.3.152.3'), 'http://cnblogs.com', now(), 1), ('1.gif', 'b5e9b4f86ce43ca65bd79c894c4a924c', 6, 3, inet_aton('114.28.0.3'), 'http://qq.com', now(), 1), ('大马.jsp', 'abbed9dcc76a02f08539b4d852bd26ba', 9, 4, inet_aton('220.181.108.178'), 'http://baidu.com', now(), 99);
select语句执行流程:
from 表
join类型 join 表 on 条件
where 条件
group by 字段
分组
,以用作聚合
运算having 条件
group by
)后的结果进行过滤select distinct 字段
order by 字段 [asc|desc]
asc
)top 多少行
limit
-- 4.1.插入 help insert -- 自增加主键和默认值的字段能够不写 insert into safe_db.dbo.users(username, password, email, tel, usercode, createtime, updatetime, datastatus) values ('mmd', '7c4a8d09ca3762af61e59520943dc26494f8941b', 'mmd@qq.com', '18738002038', newid(), getdate(), getdate(), 1); -- 批量插入 SQLServer一次批量插入最多1000行左右 insert into safe_db.dbo.users(username, password, email, tel, usercode, createtime, updatetime, datastatus) values ('xxx', '7c4a8d09ca3762af61e59520943dc26494f8942b', 'xxx@qq.com', '13738002038', newid(), getdate(), getdate(), 0), ('mmd', '7c4a8d09ca3762af61e59520943dc26494f8941b', 'mmd@qq.com', '13738002038', newid(), getdate(), getdate(), 1), ('小明', '7c4a8d09ca3762af61e59520943dc26494f8941b', 'xiaoming@qq.com', '13718002038', newid(), getdate(), getdate(), 1), ('小张', '7c4a8d09ca3762af61e59520943dc26494f8941b', 'zhang@qq.com', '13728002038', newid(), getdate(), getdate(), 1), ('小潘', '7c4a8d09ca3762af61e59520943dc26494f8941b', 'pan@qq.com', '13748002038', newid(), getdate(), getdate(), 1), ('小周', '7c4a8d09ca3762af61e59520943dc26494f8941b', 'zhou@qq.com', '13758002038', newid(), getdate(), getdate(), 1), ('小罗', '7c4a8d09ca3762af61e59520943dc26494f8941b', 'luo@qq.com', '13768002038', newid(), getdate(), getdate(), 1); -- 4.2.修改 help update update safe_db.dbo.users set datastatus=99, updatetime = getdate() where username = 'mmd'; -- 必定要有where条件!开发中通常都是先写where条件再写update -- 4.3.删除 -- 删除数据(自增加不重置)help delete; delete from safe_db.dbo.users where datastatus = 0; -- 删除所有数据(自增加重置)help truncate; truncate table safe_db.dbo.users;
-- 查询来源url(去重后) select distinct url from file_records; -- 查询来源url(分组方式) select url from file_records group by url; -- 分别统计一下url出现的次数(分组+聚合) -- 分组通常都和聚合函数一块儿使用 select url, count(*) as count from file_records group by url; -- 分别统计一下url出现的次数,已经删除的文件不算进去 select url, count(*) as count from file_records group by url having count(*) > 3; -- 在group by的结果上筛选,★写成count就不行了★ -- 分别统计一下url出现的次数并查出对应的id -- SQLServer2017新增string_agg select ids =(select stuff((select ',' + cast(id as varchar(20)) from file_records as f where f.url = file_records.url for xml path ('')), 1, 1, '')),url from file_records group by url; -- 内链接查询 innet join tb_name on 关联条件 select file_records.id, users.id as uid, users.username, users.email, file_records.file_name, file_records.md5, file_records.ip, file_records.url from users inner join file_records on file_records.user_id = users.id -- 链接条件 where users.datastatus = 1 and file_records.datastatus = 1 order by file_records.file_name desc; -- 文件名降序排序 -- 显示前5个数据 select top 5 * from file_records; -- 分页查询 第3页,每页5条 select * from (select row_number() over (order by username desc, file_name desc) as id, file_records.id as fid, users.id as uid, users.username, users.email, file_records.file_name, file_records.md5, file_records.ip, file_records.url from file_records inner join users on file_records.user_id = users.id) as temp where id > (3 - 1) * 5 and id <= 3 * 5; -- 简单提一下视图: -- 存在就删除 if exists(select * from sysobjects where name = N'view_userinfo') begin drop view view_userinfo end -- 建立视图 create view view_userinfo as select id, username, password, email, tel, datastatus from users; -- 查询视图 select id, username, password, email, tel, datastatus from view_userinfo;
知识点:
select getdate() as datatime, newid() as uuid; -- 相似于concat的效果 select cast(id as varchar(20)) + ',' from file_records for xml path (''); -- 移除多余的字符 -- STUFF(<character_expression>,<开始>,<长度>,<character_expression>) -- 将字符串插入到另外一个字符串中。它会删除开始位置第一个字符串中的指定长度的字符,而后将第二个字符串插入到开始位置的第一个字符串中 select stuff((select ',' + cast(id as varchar(20)) from file_records for xml path ('')), 1, 1, '');
数据构造:
--存在就删除表 if exists(select * from sysobjects where name = N'file_records') begin drop table file_records end -- 由于SQLServer的int没有unsigned,因此推荐使用bigint create table file_records ( id bigint identity (1,1) primary key, file_name varchar(100) not null, md5 char(32) not null, meta_type tinyint not null default 1, user_id int not null, ip bigint not null, -- 在程序中自行转换 url varchar(200) not null default '/', createtime datetime not null default getdate(), datastatus tinyint not null default 0 ); -- 能够插入3次(方便下面演示) insert into file_records(file_name, md5, meta_type, user_id, ip, url, createtime, datastatus) values ('2.zip', '3aa2db9c1c058f25ba577518b018ed5b', 2, 1, 736264195, 'http://baidu.com', getdate(), 1), ('3.rar', '6f401841afd127018dad402d17542b2c', 3, 3, 736103427, 'http://qq.com', getdate(), 1), ('7.jpg', 'fe5df232cafa4c4e0f1a0294418e5660', 4, 5, 978522371, 'http://360.cn', getdate(), 1), ('9.png', '7afbb1602613ec52b265d7a54ad27330', 5, 4, 1728288771, 'http://cnblogs.com', getdate(), 1), ('1.gif', 'b5e9b4f86ce43ca65bd79c894c4a924c', 6, 3, 1914437635, 'http://qq.com', getdate(), 1), ('大马.jsp', 'abbed9dcc76a02f08539b4d852bd26ba', 9, 4, 3702877362, 'http://baidu.com', getdate(), 99);
聊聊数据库~1.开篇(主要是NoSQL)
聊聊数据库~2.SQL环境篇:
聊聊数据库~3.SQL基础篇:
聊聊数据库~4.SQL优化篇:
聊聊数据库~5.SQL运维上篇:
聊聊数据库~6.SQL运维中篇:
CentOS7安装MySQL8.0小计:
MySQL的SQL_Mode修改小计:http://www.javashuo.com/article/p-vmgtwffb-u.html
MySQL5.7.26 忘记Root密码小计:
小计:协同办公衍生出的需求:
IDE相关:JetBrains全家桶破解思路(最新更新:2019-08-01):
SQLServer性能优化之----强大的文件组----分盘存储(水平分库)
SQLServer性能优化之---水平分库扩展:
SQLServer性能优化之---分表分库技术(同义词+连接服务器)
SQLServer性能优化之---数据库级日记监控(XEVENT)
PS:逆天之前整理的SQLServer脚本:
https://github.com/lotapp/BaseCode/tree/master/database/SQL/SQLServer
我为NET狂官方面试题-数据库篇答案:
牛逼的OSQL----大数据导入:
数据库更名系列(数据库名,逻辑名,物理文件名)
SQLServer文件收缩-图形化+命令:
数据库分离附加(附日记丢失的处理)
数据库备份相关:
利用SQLServer数据库发送邮件:
【恢复挂起的解决方案】附加文件时候的提示“没法从新生成日志,缘由是数据库关闭时存在打开的事务/用户,该数据库没有检查点或者该数据库是只读的。”【数据库恢复】