赞
踩
数据库是是按照数据结构来组织、存储和管理数据的仓库。---->存储和管理数据的仓库
是专门用于管理数据库的计算机系统软件。数据库管理系统能够为数据库提供数据的定义、建立、维护、查询和统计等操作功能,并完成对数据完整性、安全性进行控制的功能。
注意:我们一般说的数据库,就是指的DBMS
使用指针来表示数据之间的联系。
经典的里程碑阶段,代表的DBMS有:Oracle、DB2、MySQL、SQL Server、SyBase等。
由于关系型数据库中存在数据模型、性能、拓展伸缩性差的缺点,所以出现了ORDBMS(面向对象数据库技术),NoSQL(结构化数据库技术)。
Structured Query Language,即SQL,SQL是关系型数据库标准语言,其特点:简单,灵活,功能强大。SQL包含6个部分:
其语句,也称为“数据检索语句”,用以从表中获得数据,确定数据怎样在应用程序给出。保留字SELECT是DQL(也是所有SQL)用得最多的动词,其他DQL常用的保留字有WHERE,ORDER BY,GROUP BY和HAVING。这些DQL保留字常与其他类型的SQL语句一起使用。
其语句包括动词INSERT,UPDATE和DELETE。它们分别用于添加,修改和删除表中的行。也称为动作查询语言。
它的语句能确保被DML语句影响的表的所有行及时得以更新。TPL语句包括BEGIN TRANSACTION,COMMIT和ROLLBACK。
它的语句通过GRANT或REVOKE获得许可,确定单个用户和用户组对数据库对象的访问。某些RDBMS可用GRANT或REVOKE控制对表单个列的访问。
其语句包括动词CREATE和DROP。在数据库中创建新表或删除表(CREAT TABLE 或 DROP TABLE);为表加入索引等。DDL包括许多与人数据库目录中获得数据有关的保留字。它也是动作查询的一部分。
它的语句,像DECLARE CURSOR,FETCH INTO和UPDATE WHERE CURRENT用于对一个或多个表单独行的操作。
下载路径:https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads
直接下载Developer版本,下载后:是一个镜像文件—直接解压,就可以去执行Exe文件安装了
拉取镜像
docker pull mcr.microsoft.com/mssql/server:2019-latest
查看镜像
docker images
启动容器
docker run -e "ACCEPT_EULA=Y" -e "SA_PASSWORD=密码" -u 0:0 -p 1433:1433 --name mssql -v /data/mssql:/var/opt/mssql -d mcr.microsoft.com/mssql/server:2019-latest
参数 | 说明 |
---|---|
-e ‘ACCEPT_EULA=Y’ | 设置此参数说明同意 SQL SERVER 使用条款 , 否则无法使用 |
-e ‘SA_PASSWORD=密码’ | 此处设置 SQL SERVER 数据库 SA 账号的密码 |
-p 1433:1433 | 将宿主机 1433 端口映射到容器的 1433 端口 |
–name mssql | 设置容器名为 mssql |
-v /data/mssql:/var/opt/mssql | 将宿主机 /data/mssql 映射到容器 /var/opt/mssql , 方便备份数据 |
检查容器是否启动
docker ps -a
检查STATUS 是不是 Up 状态,如果是 Exited 状态的话,可以尝试使用 docker logs mssql 查看日志,日志内会提供相对应的代码,以及解决链接。
服务器本地连接测试
docker exec -it mssql /bin/bash
不报错就是连接成功
SSMS连接测试
链接:https://pan.baidu.com/s/1y65sOlVhMyDRrTXxFbq1yg
提取码:1234
建议先画E-R图,再生成数据库
创建项目,填写项目名称,选择保存目录
创建模型文件
创建表,添加字段
可以显示字段说明
生成物理数据模型
生成SQL脚本
创建模型,选择数据库类型
配置数据库连接导出模型
Standard data type | DBMS-specific physical data type | Content | Length |
---|---|---|---|
Integer | int / INTEGER | 32-bit integer | — |
Short Integer | smallint / SMALLINT | 16-bit integer | — |
Long Integer | int / INTEGER | 32-bit integer | — |
Byte | tinyint / SMALLINT | 256 values | — |
Number | numeric / NUMBER | Numbers with a fixed decimal point | Fixed |
Decimal | decimal / NUMBER | Numbers with a fixed decimal point | Fixed |
Float | float / FLOAT | 32-bit floating point numbers | Fixed |
Short Float | real / FLOAT | Less than 32-bit point decimal number | — |
Long Float | double precision / BINARY DOUBLE | 64-bit floating point numbers | — |
Money | money / NUMBER | Numbers with a fixed decimal point | Fixed |
Serial | numeric / NUMBER | Automatically incremented numbers | Fixed |
Boolean | bit / SMALLINT | Two opposing values (true/false; yes/no; 1/0) | — |
Standard data type | DBMS-specific physical data type | Content | Length |
---|---|---|---|
Characters | char / CHAR | Character strings | Fixed |
Variable Characters | varchar / VARCHAR2 | Character strings | Maximum |
Long Characters | varchar / CLOB | Character strings | Maximum |
Long Var Characters | text / CLOB | Character strings | Maximum |
Text | text / CLOB | Character strings | Maximum |
Multibyte | nchar / NCHAR | Multibyte character strings | Fixed |
Variable Multibyte | nvarchar / NVARCHAR2 | Multibyte character strings | Maximum |
Standard data type | DBMS-specific physical data type | Content | Length |
---|---|---|---|
Date | date / DATE | Day, month, year | — |
Time | time / DATE | Hour, minute, and second | — |
Date & Time | datetime / DATE | Date and time | — |
Timestamp | timestamp / TIMESTAMP | System date and time | — |
Standard data type | DBMS-specific physical data type | Content | Length |
---|---|---|---|
Binary | binary / RAW | Binary strings | Maximum |
Long Binary | image / BLOB | Binary strings | Maximum |
Bitmap | image / BLOB | Images in bitmap format (BMP) | Maximum |
Image | image / BLOB | Images | Maximum |
OLE | image / BLOB | OLE links | Maximum |
Other | — | User-defined data type | — |
Undefined | undefined | Undefined. Replaced by the default data type at generation. | — |
数据库的设计范式是数据库设计所需要满足的规范,满足这些规范的数据库是简洁的、结构明晰的。
以公司为单位,定制的一些内部的规范,统一的习惯对这个团队来说,会有促进作用
存储在4个字节中,其中1个二进制位表示符号位,其它31个二进制位表示长度和大小,可以表示-231~231-1范围内的所有整数。
存储在8个字节中,其中1个二进制位表示符号位,其它63个二进制位表示长度和大小,可以表示-263~263-1范围内的所有整数。
存储在2个字节中,其中1个二进制位表示符号位,其它15个二进制位表示长度和大小,可以表示-215~215-1范围内的所有整数。
存储在1个字节中,可以表示0~255范围内的所有整数。
浮点数据类型存储十进制小数,浮点数据为近似值,Sql Server中采用了只入不舍的方式进行存储,即当要舍入的数是一个非零数时,就进1。
存储在4个字节中,可以存储正的或者负的十进制数值,它的存储范围从-3.40E+38~-1.18E-38、0以及 1.18E-38~3.40E+38。
存储用字符串表示的日期数据,可以表示0001-01-01~9999-12-31(公元元年1月1日到公元9999年12月31日)间的任意日期值。数据格式为“YYYY-MM-DD”,该数据类型占用3个字节的空间。
YYYY:表示年份的四位数字,范围为0001~9999。
MM:表示指定年份中月份的两位数字,范围为01~12。
DD:表示指定月份中某一天的两位数字,范围为01~31(最高值取决于具体月份)。
以字符串形式记录一天的某个时间,取值范围为00:00:00.0000000~23:59:59.9999999,数据格式为“hh:mm:ss[.nnnnnnn]”,存储时占用5个字节的空间。
hh:表示小时的两位数字,范围为0~23。
mm:表示分钟的两位数字,范围为0~59。
ss:表示秒的两位数字,范围为0~59。
n:是07位数字,范围为09999999,它表示秒的小部分。
用于存储时间和日期数据,从1753年1月1日到9999年12月31日,默认值为 1900-01-01 00:00:00,当插入数据或在其它地方使用时,需用单引号或双引号括起来。可以使用“/”、“-”和“.”作为分隔符。该类型数据占用8个字节的空间。
datetime的扩展类型,其数据范围更大,默认的最小精度最高,并具有可选的用户定义的精度。默认格式为:YYYY-MM-DD hh:mm:ss[.fractional seconds],日期的存取范围是0001-01-01~9999-12-31(公元元年1月1日到公元9999年12月31日)。
smalldatetime类型与datetime类型相似,只是其存储范围是从1900年1月1日到2079年6月6日,当日期时间精度较小时,可以使用smalldatetime,该类型数据占用4个字节的存储空间。
用于定义一个采用24小时制与日期相组合并可识别时区的时间。默认格式是:“YYYY-MM-DD hh:mm:ss[.nnnnnnn][{+|-}hh:mm]”。
hh:两位数,范围是-14~14。
mm:两位数,范围为00~59。
这里hh是时区偏移量,该类型数据中保存的是世界标准时间(UTC)值,eg:要存储北京时间2011年11月11日12点整,存储时该值将是2011-11-11 12:00:00+08:00,因为北京处于东八区,比UTC早8个小时。存储该数据类型数据时默认占用10个字节大小的固定存储空间。
用于存储文本数据,服务器代码页中长度可变的非Unicode数据,最大长度为2的31次方-1(2147 483 647)个字符。当服务器代码页使用双字节字符时,存储仍是2147 483 647字节。
与text类型作用相同,为长度可变的非Unicode数据,最大长度为 2^30-1 (1073 741 283)个字符。存储大小是所输入字符个数的两倍。
长度可变的二进制数据,范围为 :0—2^31-1个字节。用于存储照片、目录图片或者图画,容量也是2147 483 647个字节,由系统根据数据的长度自动分配空间,存储该字段的数据一般不能使用insert语句直接输入。
用于存储货币值,取值范围为正负922 337 213 685 477.580 8之间。money数据类型中整数部分包含19个数字,小数部分包含4个数字,因此money数据类型的精度是19,存储时占用8个字节的存储空间。
与money类型相似,取值范围为正负214 748.346 8之间,smallmoney存储时占用4个字节存储空间。
bit 称为位数据类型,只取0或1为值,长度1字节。bit值经常当作逻辑值用于判断true(1)或false(0),输入非0值时系统将其替换为1。
长度为n个字节的固定长度二进制数据,其中n是从1~8000的值。存储大小为n个字节。在输入binary值时,必须在前面带0x,可以使用0xAA5代表AA5,如果输入数据长度大于定于的长度,超出的部分会被截断。
可变长度二进制数据。其中n是从1~8000的值,存储大小为所输入数据的实际长度+2个字节。
每个数据都有一个计数器,当对数据库中包含rowversion列的表执行插入或者更新操作时,该计数器数值就会增加。此计数器是数据库行版本。一个表只能有一个rowversion列。每次修改或者插入包含rowversion列的行时,就会在rowversion列中插入经过增量的数据库行版本值。
公开数据库中自动生成的唯一二进制数字的数据类型。rowversion通常用作给表行加版本戳的机制。存储大小为8个字节。rowversion数据类型只是递增的数字,不保留日期或时间。
时间戳数据类型,timestamp的数据类型为rowversion数据类型的同义词,提供数据库范围内的唯一值,反映数据修改的唯一顺序,是一个单调上升的计数器,此列的值被自动更新。在create table或alter table语句中不必为timestamp数据类型指定列名。
16字节的GUID(Globally Unique Identifier,全球唯一标识符),是Sql Server根据网络适配器地址和主机CPU时钟产生的唯一号码,其中,每个为都是09或af范围内的十六进制数字。例如:6F9619FF-8B86-D011-B42D-00C04FC964FF,此号码可以通过newid()函数获得,在全世界各地的计算机由此函数产生的数字不会相同。
游标数据类型,该类型类似与数据表,其保存的数据中的包含行和列值,但是没有索引,游标用来建立一个数据的数据集,每次处理一行数据。
用于存储除文本,图形数据和timestamp数据外的其它任何合法的Sql Server数据,可以方便Sql Server的开发工作。
用于存储对表或视图处理后的结果集。这种新的数据类型使得变量可以存储一个表,从而使函数或过程返回查询结果更加方便、快捷。
存储xml数据的数据类型。可以在列中或者xml类型的变量中存储xml实例。存储的xml数据类型表示实例大小不能超过2GB。
create database database_name
[ on
[primary] [<filespec> [,...n] ]
]
[ log on
[<filespec>[,...n]]
];
<filespec>::=
(
name=logical_file_name
[ , newname = new_login_name ]
[ , fileName = {'os_file_name' | 'fileStream_path'} ]
[ , size = size[ KB | MB | GB | TB] ]
[ , MaxSize = {max_size [ KB | MB |GB |TB] | UNLIMITED} ]
[ , filegrowth = growth_increment [ KB | MB |GB | TB | %] ]
);
创建一个数据库sample_db,该数据库的主数据文件逻辑名为sample_db,物理文件名称为sample_db.mdf,初始大小为5MB,最大尺寸为30MB,增长速度为5%;数据库日志文件的逻辑名称为sample_log,保存日志文件的物理名称为sample_log.ldf,初始大小为1MB,最大尺寸为8MB,增长速度为10%
create database[sample_db] on primary
(
name='sample_db',
filename='C:\SQL_SERVER_temp\sampl_db.mdf',
size=5120KB,
maxsize=30MB,
filegrowth=5%
)
log on
(
name='sample_log',
filename='C:\SQL_SERVER_temp\sample_log.ldf',
size=1024KB,
maxsize=8192KB,
filegrowth=10%
)
增加或删除数据文件、改变数据文件或日志文件的大小和增长方式,增加或者删除日志文件和文件组。
alter database database_name
{
modify name=new_database_name
| Add file<filespec> [ ,...n ] [ TO filegroup { filegroup_name } ]
| Add log file <filespec> [ ,...n ]
| remove file logical_file_name
|modify file <filespec>
}
<filespec>::=
(
name=logical_file_name
[ , newname = new_login_name ]
[ , fileName = {'os_file_name' | 'filestream_path'} ]
[ , size = size[ KB | MB | GB | TB] ]
[ , MaxSize = {max_size [ KB | MB |GB |TB] | UNLIMITED} ]
[ , FILEGROWTH = growth_increment [ KB | MB |GB | TB | %] ]
[ , offline ]
);
将sample_db数据库中的主数据文件的初始大小修改为15MB
alter database sample_db
modify file
(
name='sample_db',
size=15MB
);
drop database XXX
CREATE TABLE dbo.Products
(ProductID int PRIMARY KEY NOT NULL,
ProductName varchar(25) NOT NULL,
Price money NULL,
ProductDescription varchar(max) NULL)
GO
drop table 表名
alter table 表名 rename column A to B
alter table 表名 alter column 字段名 type not null
--如果字段有默认值,则需要先删除字段的约束,在添加新的默认值
alter table 表名 add default (0) for 字段名 with values
--根据约束名称删除约束
alter table 表名 drop constraint 约束名
--根据表名向字段中增加新的默认值
alter table 表名 add default (0) for 字段名 with values
alter table 表名 add 字段名 type not null default 0
alter table 表名 drop column 字段名
--修改字段为必填,此字段才能设置为主键
ALTER TABLE StudentTB ALTER COLUMN Code VARCHAR(12) NOT NULL
--主键约束
ALTER TABLE StudentTB ADD CONSTRAINT main_key PRIMARY KEY(Code)
--唯一性约束
ALTER TABLE StudentTB ADD CONSTRAINT unique_Name UNIQUE(Name)
--添加默认约束
ALTER TABLE StudentTB ADD CONSTRAINT default_Name DEFAULT('HAHAHA') FOR Name
--添加检查约束
ALTER TABLE StudentTB ADD CONSTRAINT more_than_12 CHECK(Age < 12);
主键
外键
--查询全部字段
select * from 表名
--查询部分字段
select 字段1,字段2 from 表名
--查询去重字段
select distinct 字段1 from 表名
--字段别名
select 字段1 别名 from 表名
select 字段1 as 别名 from 表名
--字段计算
select 字段1*字段2 as 别名 from 表名
--简单条件
select * from 表名 where 字段=值
--in、not in
select * from 表名 where 字段 in()
select * from 表名 where 字段 not in()
--between and
select * from 表名 where 字段 between A and B
--and 并且
select * from 表名 where 条件1 and 条件2
--or 或者
select * from 表名 where 条件1 or 条件2
--not
select * from 表名 where 字段!=值
select * from 表名 where 字段<>值
--空值
select * from 表名 where 字段 is NULL
select * from 表名 where 字段 is not NULL
--模糊查询 %: 表示零或多个字符 _ : 表示一个字符
select * from 表名 where 字段 like '%值%'
select * from 表名 where 字段 not like '%值%'
select * from 表名 where 字段 like '_值%'
--ASC: 升序 (默认,可省),DESC:降序
--字段1升序基础上相同的,字段2降序
select * from 表名 order by 字段1 asc,字段2 desc
--ROW_NUMBER() over 按照over的排序进行排序的结果集编号newRow,然后取值
select * from
(select *, ROW_NUMBER() over(order by 字段 desc) as newRow from 表名) as t
where t.newRow between 1 and 2
--offset 跨过3行取剩下2行
select * from 表名 order by 字段 desc
offset 3 rows fetch next 2 rows only
--COUNT 统计结果的记录数
select count(*) from 表名
select count(字段1) from 表名
--MAX 统计计算最大值
select max(字段1) from 表名
--MIN 统计最小值
select min(字段1) from 表名
--SUM 统计计算求和
select sum(字段1) from 表名
--AVG 统计计算平均值
select avg(字段1) from 表名
--分组查询+聚集函数+过滤条件
select 字段1,字段2,count(*) as 别名 from 表名 where 条件 group by 字段1,字段2 having count(*)>1
多表查询会产生笛卡尔积。 假设集合A={a,b},集合B={0,1},则两个集合的笛卡尔积为{(a,0),(a,1),(b,0),(b,1)},尽量避免,可以加链接条件去掉不需要的数据结果集,否则数据量是乘积行数,会非常大。
链接的表符合等式条件的数据才展示
--隐世内连接
select * from A,B where A.列=B.列
--显示内连接 inner 可省略
select * from A [inner] join B on A.列=B.列
左外连接:查询出JOIN左边表的全部数据,JOIN右边的表不匹配的数据用NULL来填充,关键字:left join
右外连接:查询出JOIN右边表的全部数据,JOIN左边的表不匹配的数据用NULL来填充,关键字:right join
全连接: (左连接 - 内连接) +内连接 + (右连接 - 内连接) = 左连接+右连接-内连接 关键字:full join
--左外连接
select * from A left join B on A.列=B.列
--右外连接
select * from A right join B on A.列=B.列
--全连接
select * from A full join B on A.列=B.列
把一张表看成两张表来做查询
--完整表达式
insert into tableName (c1,c2,c3 ...) values (x1,x2,x3,...)
--全字段插入可以省略字段名
insert into tableName values (x1,x2,x3,...)
--插入多条
insert into tableName values(x11,x21,x31,...),
(x12,x22,x32,...),
(x13,x23,x33,...);
--插入查询结果
insert into table1 (x1,x2)
select c1,c2 from table2 where condition
--delete删除
delete from tableName where condition
--truncate是删除全表
--和delete删除全表而言,如果是自增主键,truncate 后从1开始,delete后还要接着原先的自增
--truncate无法回滚,delete可以回滚
truncate tableName
--单表更新
update tableName set x1=xx [, x2=xx] where condition
--关联表更新
update table1
set table1.x1='abc'
from table1
join table2 on table1.id=table2.uId where condition
--关联更新多张表
update table1,table2
set table1.字段1 ='XXX',table2.字段2='YYY'
where table1.字段3=table2.字段3
--返回字符串中最左侧的第一个值的ASCII代码值
select ASCII('TEST'),ASCII('TS'),ASCII('123')
--将整数类型的ASCII值转换成对应的字符
select CHAR(123),CHAR(234)
--从左侧或者从右侧获取指定个数的元素
select LEFT('testtest',6) as p1
select RIGHT('testtest',5) as p2
--从左侧去空格或者从右侧去空格
select LTRIM(' test ')
select RTRIM(' test ')
--逆序字符串 tset
select REVERSE('test')
--返回字符串的长度 4 2
select LEN('test'),LEN('测试')
--查找字符串的开始位置
--CHARINDEX(str1,str,[start])函数返回子字符串str1在字符串str中的开始位置,start为搜索的开始位置,如果指定start参数,则从指定位置开始搜索;如果不指定start参数或者指定为0或者负值,则从字符串开始位置搜索
select CHARINDEX('a','banana'),CHARINDEX('a','banana',4), CHARINDEX('na','banana', 4)
--截取字符串的指定位置
--下面1代表从第一个位置开始截取,5代表截取字符的长度为5,testt
select SUBSTRING('testtest',1,5)
--大小写转换 TEST test
select UPPER('Test'),LOWER('Test')
--替换函数 xxx.baidu.com
select REPLACE('www.baidu.com','w','x')
--将数值类型转换成字符数据
--第一个参数是要转换的数值,第二个参数是转换後的总长度(含小数点,正负号),第三个参数为小数位,这里长度优先于小数位
select STR(3141.59,6,1),STR(123.45,5,2)
--绝对值
select ABS(-2.5),ABS(4.5)
--圆周率
select PI()
--平方根
select SQRT(4),SQRT(9)
--随机数
--RAND(x)返回一个随机浮点值v,范围在0~1之间(即0<=v<=1.0)。若指定一个整数参数x,则它被用作种子值,使用相同的种子数将产生重复序列。如果同一种子值多次调用RAND函数,它将返回同一生成值。
select RAND(),RAND(),RAND(),RAND(5),RAND(5),RAND(5)
--四舍五入
--ROUND(x,y)返回接近于参数x的数,其值保留到小数点后面y位,若y为负值,则将保留x值到小数点左边y位
--1.50 1.60 10.00
select ROUND(1.54,1),ROUND(1.56,1),ROUND(12.54,-1)
--判断正、负、零 1 -1 0
select SIGN(10),SIGN(-10),SIGN(0)
--CEILING(x)返回不小于x的最小整数值 -3 4
select CEILING(-3.35), CEILING(3.35)
--FLOOR(x)返回不大于x的最大整数值 -4
select FLOOR(-3.35)
--POWER(x,y) 求x的y次方 8
select POWER(2,3)
--SQUARE(x) 求x的平方 9 4 0
select SQUARE(3),SQUARE(-2),SQUARE(0)
select CAST('121231' AS DATE), CAST(100 AS CHAR(3)),CAST('2012-05-01 12:11:10' AS CHAR(3))
select CONVERT(DATE,'2012-05-01 12:11:10'),CONVERT(CHAR(3),100 ),CONVERT(DATE,'2012-05-01 12:11:10')
--获取系统当前日期的函数(普通时间和UTC时间)
select GETDATE() as CurrentTime,GETUTCDATE() as UTCTIme
--返回指定日期的d是一个月中的第几天、月份、年数
select DAY('2020-08-05 12:11:08')
select MONTH('2020-08-05 12:11:08')
select YEAR('2020-08-05 12:11:08')
--返回指定日期的 年、月、第n天、天、第n周、星期几、小时、分钟、秒
SELECT DATENAME(year,'2020-04-03 08:12:36') AS yearValue,
DATENAME(month,'2020-04-03 08:12:36') AS monthValue,
DATENAME(dayofyear,'2020-04-03 08:12:36') AS dayofyearValue,
DATENAME(day,'2020-04-03 08:12:36') AS dayValue,
DATENAME(week,'2020-04-03 08:12:36') AS weekValue,
DATENAME(weekday,'2020-04-03 08:12:36') AS weekdayValue,
DATENAME(hour,'2020-04-03 08:12:36') AS hourValue,
DATENAME(minute,'2020-04-03 08:12:36') AS minuteValue,
DATENAME(second,'2020-04-03 08:12:36') AS secondValue
--获取日期中指定部分的整数值的函数
SELECT DATEPART(year,'2020-04-03 08:12:36') AS yearValue,
DATEPART(month,'2020-04-03 08:12:36') AS monthValue,
DATEPART(dayofyear,'2020-04-03 08:12:36') AS dayofyearValue
--日期的加运算
SELECT DATEADD(year,1,'2020-04-03 08:12:36') AS yearAdd,
DATEADD(month ,2, '2020-04-03 08:12:36') AS weekdayAdd,
DATEADD(hour,3,'2020-04-03 08:12:36') AS hourAdd
数据库事务( transaction)是访问并可能操作各种数据项的一个数据库操作序列,这些操作要么全部执行,要么全部不执行,是一个不可分割的工作单位。事务由事务开始与事务结束之间执行的全部数据库操作组成。
begin transaction
begin try
do somthing ...
commit transaction
end try
begin catch
rollback transaction
end catch
数据库并不会出现无限等待的情况,是因为数据库搜索引擎会定期检测这种状况,一旦发现有情况,立马【随机】选择一个事务作为牺牲品。牺牲的事务,将会回滚数据。
死锁不可能完全避免,更多的是降低死锁的概率
不用锁就不会死锁,建议大家使用乐观锁
统一操作表顺序,先A后B再C,在系统中所有的操作都需要统一顺序
最小单元锁,锁里面操作尽量减少操作
避免事务中等待用户输入,避免在事务中等待时间过久
减少数据库并发,微服务
设置死锁时间 set lock_timeout(锁超时时间)
select * from sys.dm_tran_locks
dbcc opentran
set lock_timeout 4000
update 表 set 字段=XXX where 主键=YYY and 版本=SSS
存储过程封装了复杂的SQL操作,简化了操作流程。
加快了应用程序系统的运行速度,因为存储过程只在创建时编译,此后的调用无须重新编译。
实现了模块化的程序设计,存储过程可以被多次调用,为应用程序提供了统一的数据库访问接口,提高了程序的可维护性,充分体现了模块化的开发思想。
提高了代码的安全性,数据库管理员可以为存储过程设定指定的用户可访问的权限。
降低网络流量,有存储过程是存放在服务器上的,所以在应用程序与服务器通信过程中,不会产生大量的T_SQL代码
系统存储过程示例:
创建无参的存储过程
if (exists (select * from sys.objects where name = 'PROC_XXX'))
drop proc PROC_XXX
go
create procedure PROC_XXX
as
select * from 表名
修改指定存储过程的内容
go
alter proc PROC_XXX
as
select * from 表名 where 条件
删除存储过程
drop proc PROC_XXX;
重命名存储过程(调用系统自带的存储过程来实现)
go
sp_rename PROC_XXX,PROC_YYY;
调用无参存储过程
exec PROC_XXX;
创建带参数返回值的存储过程
if (exists (select * from sys.objects where name = 'GetMsg'))
drop proc GetMsg
go
create proc GetMsg(
@id varchar(32), --输入参数,无默认值
@userName varchar(50) output, -- 输出参数,无默认值
@count int output --输出参数 ,无默认值
)
as
select @userName=userName from UserInfor where id=@id;
select @count=COUNT(*) from UserInfor;
-- 执行该存储过程
declare @myUserName varchar(50); --声明变量来接收存储过程的返回值
declare @myCount int; --声明变量来接收存储过程的返回值
exec GetMsg @id='002',@userName=@myUserName output,@count=@myCount output;
select @myUserName as '姓名',@myCount as '总条数';
--或者这样调用
--declare @myUserName varchar(50); --声明变量来接收存储过程的返回值
--declare @myCount int; --声明变量来接收存储过程的返回值
--exec GetMsg '002',@myUserName output,@myCount output;
--select @myUserName,@myCount
创建带通配符的存储过程
if (exists (select * from sys.objects where name = 'GetInfor'))
drop proc GetInfor
go
create proc GetInfor(
@userName varchar(50) --输入参数
)
as
select * from UserInfor where userName like @userName;
-- 执行该存储过程
exec GetInfor 'y%'; --userName 以y开头
exec GetInfor '%p%'; --userName 中间有个p
exec GetInfor '_p%'; --userName p为第二个字符,p前有一个字符,p后不定
索引是一个单独的,存储在磁盘上的数据结构,它们包含对数据表里所有记录的引用指针,使用索引用于快速找出在某个或多个列中有某一特定值的行,对相关列使用索引是降低查询操作时间的最佳途径。索引可以是由表或视图中的一列或多列生成的键。
SQL Server中的索引有两种:聚集索引和非聚集索引,它们的区别是在物理数据的存储方式上。
聚集索引
聚集索引基于数据行的键值,在表内排序和存储这些数据行。
每张表只能有一个聚集索引,因为数据行本身只能按一个顺序存储。
表中的物理顺序和索引中行的物理顺序是相同的,创建任何非聚集索引之前要先创建聚集索引,这是因为非聚集索引改变了表中行的物理顺序。
关键值的唯一性使用UNIQUE关键字或者由内部的唯一标识符明确维护。
在索引的创建过程中,SQL Server临时使用当前数据库的磁盘空间,所以要保证有足够的空间创建索引。
非聚集索引
考虑使用非聚集索引的情况
--查看表的索引
exec sp_helpindex 'tableName';
--查看索引的统计信息
DBCC SHOW_STATISTICS ('数据库名.dbo.表名',索引名);
--修改索引名称
exec sp_rename '表名.旧索引名' ,'新索引名', index;
--删除索引
DROP INDEX 表名.索引名
--创建索引
CREATE [UNIQUE] [CLUSTERED|NONCLUSTERRED] INDEX 索引名 ON {table名|view名}(column名 [ASC|DESC] [,...n])
触发器是数据库用于保证数据完整性的一种方式,可以说它是与表事件相关的一种特殊的存储过程,它的执行不能由程序调用,也不能手动启用,而只能是通过事件来触发,比如当对表进行 Insert、Delete、Update操作的时候,就会激活触发器来执行,所以触发器通常用于保证数据完整性和一些业务约束规则等。
触发器通常分为三类
根据触发器执行顺序分类
从临时表的角度分析
从执行流程的角度分析
从三种实际触发器插入临时表的角度分析
查看相关触发器
--1. 查看数据库中所有的触发器
select * from sysobjects where xtype='TR';
-- 查看触发器的内容
exec sp_helptext 'trig_del1';
-- 查看某张表的所有触发器
exec sp_helptrigger UserInfor
启用和禁用触发器
-- 启用UserInfor表上的触发器
alter table UserInfor enable trigger insert_forbidden20;
-- 启用UserInfor表上的所有触发器
alter table UserInfor enable trigger ALL;
-- 禁用UserInfor表上的触发器
alter table UserInfor disable trigger insert_forbidden20;
-- 禁用UserInfor表上的所有触发器
alter table UserInfor disable trigger ALL;
修改触发器
-- 把触发器的内容改为删除的时候显示删除的数据了
alter trigger trig_Notdel
on RoleInfor
after delete
as
begin
select roleName,roleDescirption,addTime from deleted
end;
删除触发器
--删除下面两个触发器
drop trigger insert_forbidden20,trig_del1;
创建触发器
create trigger trig_Notdel
on RoleInfor
after delete
as
begin
--insert into RoleInfor(roleName,roleDescirption) select roleName,roleDescirption from deleted; --部分字段恢复
insert into Roleinfor select * from deleted; --全字段恢复
end;
视图是一个虚拟表,是从一个或多个表中到处,行为与表相似,同样可以Select、Insert、Update、对视图的最终操作都会转换成对数据表的操作,可以保障数据系统的安全性。
简化用户的操作,所见即所要,不必再指定一些特殊查询条件。
从安全角度来考虑,视图只是一些SQL语句的集合。可以防止用户接触数据表,从而不知表结构;用户只能修改或者查看他所用到的数据,其它数据 和 表是不可以访问,视图和表的设置权限是互不影响的。
屏蔽真实表结构带来的变化。
视图是已经编译好的SQL语句,是基于SQL语句的结果集的可视化表,而表不是。
除了索引视图外,其它视图是没有实际的物理记录,而基本表有,即表是占物理空间的,视图不占,只是逻辑概念的存在。
视图的创建和删除只影响视图,不影响其对应的表结构。
创建视图
if (exists (select * from sys.objects where name='UserInfor_View'))
drop view UserInfor_View
go
create view UserInfor_View
as
select id,userAge from UserInfor where userAge >=20;
--执行视图
select * from UserInfor_View;
查看视图
-- 使用sp_help存储过程查看视图的定义信息
exec sp_help 'UserInfor_View';
-- 使用sp_helptext系统存储过程使用来显示规则,默认值,未加密的存储过程,用户定义函数,触发器或视图的文本
exec sp_helptext 'UserInfor_View';
修改视图
alter view UserInfor_View
as
select id,userAge from UserInfor where userAge >=10;
删除视图
drop view UserInfor_View;
复制模式、镜像传输、日志传输、和 Always On技术
发布服务器按**'预定的时间间隔**'向订阅服务器发送已发布数据的快照。
快照发布,就是将所有要发布的内容,做成一个镜像文件,然后一次性复制到订阅服务器,两次快照之间的更新不会实时同步,而是按照设置的’预定间隔’进行。这种方式占用带宽较多,因此比较适用内容不是很大,或者更新不需要很频繁的场景。
数据库镜像传输,严格来说不是主从架构,而是主备架构,将两台数据库服务器通过一台中间监控服务器关联起来,两台服务器通过镜像文件,实时同步数据(有延迟,延迟很短)。当主服务器宕机之后,监控服务器自动切换到备份服务器上。
此方案优点是可以快速的切换主备方案,相比较Always on集群,可以不用共享磁盘即可实现,避免了数据库集群存储单点故障,导致整个集群崩溃。
缺点也很明显,无论是主备服务器,要实现同步操作,都是依赖于性能低的那一端,因此两台服务器都要是高性能的才可以保证同步的及时性;同时备份服务器只是备份和故障转移,不能提供从服务器的只读访问,因此才说是主备服务器,而且是一对一,只能有一台备份服务器。
与镜像传输模式类似,是将主数据库日志备份,发送到从服务器上,然后从服务器还原日志,更新数据。
此方式优点在于从服务器可以有多台从服务器,而且当主服务器脚本操作异常后,只需要在日志同步之前,及时拦截日志传输,即可保留从服务器数据,减少灾难损失;此方式相较于“复制发布”模式,还有一个有点就是无论是新增表、视图等等,都会通过日志同步给从服务器,而复制模式不行,相应的缺点就是通过日志备份传输,在还原,会有较大的时间延迟。而且无法自动转移故障,只能手动转移。
AlwaysOn是基于Windows的故障转移集群,集群技术是微软提供的,可用性最高的主备方案。它是将多台服务器通过一个共享的外部存储区域(SAN),连接成一个资源共享的服务器群体,数据库文件和实例,都存放并运行在该共享区域节点上,每台服务器相当于一个节点,共同访问共享的节点实例。服务器只有一个节点处于活动状态,当活动节点出现故障,会有其他节点主动启动,取代当前故障点,整个过程只需要几秒钟,用户无法感知。
集群有很多优点,是目前最高效的高可用技术,但是他也有很明显的缺点,所有的节点,都依赖于共享节点实例,如果共享节点出现故障,将会导致整个集群失去作用,且很难恢复。
配置服务器可以远程访问
创建一个写主库,两个读库,数据表
USE [DbTestWrite]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[User](
[id] [nvarchar](50) NULL,
[name] [nvarchar](50) NULL,
[sex] [nvarchar](50) NULL,
[age] [int] NULL
) ON [PRIMARY]
GO
创建快照文件夹共享
如果是首次配置读写分离,需要配置分发服务器,后续不再配置。 如果不想用之前的分发服务器,可以右键复制,禁用分发服务器,然后重新配置。
从库修改的数据会被主库覆盖,快照最少需要10秒才能同步一次
USE [DbTestWrite]
GO
INSERT INTO [dbo].[User]
([id]
,[name]
,[sex]
,[age])
VALUES
(1
,'test1'
,'男'
,18)
GO
拆分数据库,一个数据库变成多个数据库,无论去做数据库中的任何操作,都需要先确定在哪个数据库中,然后再操作。
数据库中的数据量不一定是可控的,业务增长是成几何式增长,在未进行分库分表的情况下,随着时间和业务的发展,库中的表会越来越多,表中的数据量也会越来越大,相应地,数据操作,增删改查的开销也会越来越大;另外,由于无法进行分布式式部署,而一台服务器的资源(CPU、磁盘、内存、IO等)是有限的,最终数据库所能承载的数据量、数据处理能力都将遭遇瓶颈。
特点:数据库和数据库之间不会出现相同表,把一个库中的表通过业务上的划分,分别部署到不同的数据库。
按照业务维度拆分,
比如电商:会员,订单,商品、物流、仓储、支付、类别、财务,评论,售后、众筹、预售
特点:只是化整为零,每个小数据库中的数据表的结构完全一样,但是数据是不一样的;
针对于部分的表中数据量随着业务的不断增长,表中的数据量也会越来越大,相应地,数据操作,增删改查的开销也会越来越大;另外,由于无法进行分布式式部署,而一台服务器的资源(CPU、磁盘、内存、IO等)是有限的,最终数据库所能承载的数据量、数据处理能力都将遭遇瓶颈。
特点:把一个表变成多个表,表格和表格一对一的关系,可以保存相同的主键。
特点:更加常见,一般出现在单表数据量过于庞大的场景,把表由一个表变成多个表,每个表结构完全一样,数据完全不同;
可以解决性能问题,但增加操作查询数据的复杂性。
SQlserver自己带的功能; 自己去维护如何保存数据库;自己去维护分区。一般情况下,我们建立数据库表时,表数据都存放在一个文件里。但是如果是分区表的话,表数据就会按照你指定的规则分放到不同的文件里,把一个大的数据文件拆分为多个小文件,还可以把这些小文件放在不同的磁盘下由多个cpu进行处理。这样文件的大小随着拆分而减小,还得到硬件系统的加强,自然对我们操作数据是大大有利的。所以大数据量的数据表,对分区的需要还是必要的,因为它可以提高查询效率,还可以对历史数据经行区分存档等。但是数据量少的数据表就不要分区啦,因为表分区会对数据库产生不必要的开销。
生成的脚本执行一下就完成了分区
USE [DbTestWrite]
GO
BEGIN TRANSACTION
CREATE PARTITION FUNCTION [pmethod](int) AS RANGE LEFT FOR VALUES (N'10', N'20', N'30')
CREATE PARTITION SCHEME [pschema] AS PARTITION [pmethod] TO ([filegroup1], [filegroup2], [filegroup3], [PRIMARY])
CREATE CLUSTERED INDEX [ClusteredIndex_on_pschema_637719204427225842] ON [dbo].[User]
(
[age]
)WITH (SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF) ON [pschema]([age])
DROP INDEX [ClusteredIndex_on_pschema_637719204427225842] ON [dbo].[User]
COMMIT TRANSACTION
添加文件组
代码格式:
ALTER DATABASE <数据库名称> ADD FILEGROUP<文件组名>
代码示例:
ALTER DATABASE DemoADD FILEGROUP DemoFileGroup
添加文件
代码格式:
ALTER DATABASE <数据库名称> ADD FILE < 数据标识> TO FILEGROUP<文件组名称>
注意:数据标识中name为逻辑文件名、filename为物理文件路径名、size为文件初始大小(单位:kb/mb/gb/tb)、filegrowth为文件自动增量(单位:kb/mb/gb/tb)、maxsize为文件增大的最大大小(单位:kb/mb/gb/tb/unlimited)
代码示例:
ALTER DATABASE TestDb ADD FILE (
NAME='TestFile1',
FILENAME='D:\ProgramFiles\Microsoft SQL Server\MSSQL\DATA\TestFile1.mdf',
SIZE=5MB,
FILEGROWTH=5MB)
TO FILEGROUP TestFileGroup
定义分区函数
分区函数是用于判定数据行该属于哪个分区,通过分区函数中设置边界值来使得根据行中特定列的值来确定其分区。
代码格式:
CREATE PARTITIONFUNCTION partition_function_name( input_parameter_type )
ASRANGE [ LEFT | RIGHT ]
FORVALUES ( [ boundary_value [ ,...n ] ] )
其中“LEFT”和“RIGHT”决定了“VALUES”中的边界值被划分到哪一个分区中(即,边界值属于左侧分区还是右侧分区)。
代码示例:
CREATE PARTITIONFUNCTION TestPartitionFunction(datetime2(0))
ASRANG ERIGHT
FORVALUES('2018-01-01 00:00:00','2019-01-01 00:00:00')
查看分区函数是否创建成功
SELECT * FROM sys.partition_functions
定义分区架构
定义完分区函数仅仅是知道了如何将列的值区分到了不同的分区,而每个分区的存储方式,则需要分区构架来定义。分区构架仅仅是依赖分区函数.分区构架中负责分配每个区属于哪个文件组,而分区函数是决定如何在逻辑上分区。
代码格式:
CREATE PARTITIONSCHEME partition_scheme_name
ASPARTITION partition_function_name [ ALL ]
TO( { file_group_name | [ PRIMARY ] } [ ,...n ])
代码示例:
CREATE PARTITIONSCHEME TestPartitionScheme
ASPARTITION TestPartitionFunction
TO (TestFileGroup,[PRIMARY],TestFileGroup)
查看分区架构是否创建完成:
SELECT *FROM sys.partition_schemes
定义分区表
表在创建的时候就已经决定是否是分区表了。虽然在很多情况下都是你在发现已经表已经足够大的时候才想到要把表分区,但是分区表只能够在创建的时候指定为分区表。
代码格式:
CREATE TABLE table_name(
...
) ON partition_scheme_name(column_name)
代码示例:
CREATE TABLE dt(
id BIGINT,
date datetime2(0),
desc varchar(50)
) ON TestPartitionScheme(date)
优点:
缺点:
在数据库中,通过数据页保存数据,数据页包含8Kb容量,数据页又在存储区域,一个存储区域包含 8 个数据页
超过8KB的数据存储在文本图像页。
数据页,存储区域体积大,索引页相对轻巧查询快,通过索引查询数据可以提升性能,正因为索引页是独立出来存储的,所以索引需要单独维护,增加,删除,修改数据的时候,索引页需要调整,降低了性能,适合存储经常查询,修改比较少的数据。
提交的sql语句,数据库查询优化器,经过分析生成多个数据库可以识别的高效执行查询方式。然后优化器会在众多执行计划中找出一个资源使用最少,而不是最快的执行方案,给你展示出来,可以是xml格式,文本格式,也可以是图形化的执行方案。
在执行Sql语句的时候,经过分析,给我们定制一个相对较好的执行方案;在这个方案中,我们可以看到这个Sql语句在执行的时候,所需要的各种资源信息,所有消耗的一个清单。可以根据执行计划优化sql和数据结构。建议大家写SQL语句尽量参数化,SQL会缓存可以提高性能。
实际的执行计划:可能会有出入,需要把SQl语句执行完毕才能知道,大部分实际的计划和预估计划是一致的。
缓存的执行计划可以手工清除
dbcc freeprocache
dbcc flushprocindb(db_id)
查看预估执行计划
连线越粗表示扫描影响的行数愈多,性能越差。
Table Scan(表扫描)
当表中没有聚集索引,又没有合适索引的情况下,会出现这个操作。这个操作是很耗性能的,他的出现也意味着优化器要遍历整张表去查找你所需要的数据。
Clustered Index Scan(聚集索引扫描)、Index Scan(非聚集索引扫描)
聚集索引扫描:聚集索引的数据体积实际是就是表本身,也就是说表有多少行多少列,聚集索引就有多少行多少列,那么聚集索引扫描就跟表扫描差不多,也要进行全表扫描,遍历所有表数据,查找出你想要的数据。
非聚集索引扫描:非聚集索引的体积是根据你的索引创建情况而定的,可以只包含你要查询的列。那么进行非聚集索引扫描,便是你非聚集中包含的列的所有行进行遍历,查找出你想要的数据。
建议大家在Sql语句查询的时候,尽量不要使用* 查询。
Key Lookup(键值查找)
查找与扫描在性能上完全不是一个级别的,扫描需要遍历整张表,而查找只需要通过键值直接提取数据,返回结果,性能要好。当你查找的列没有完全被非聚集索引包含,就需要使用键值查找在聚集索引上查找非聚集索引不包含的列。
RID Lookoup(RID查找)
跟键值查找类似,只不过RID查找,是需要查找的列没有完全被非聚集索引包含,而剩余的列所在的表又不存在聚集索引,不能键值查找,只能根据行表示Rid来查询数据。
Clustered Index Seek(聚集索引查找)、Index Seek(非聚集索引查找)
聚集索引查找:聚集索引包含整个表的数据,也就是在聚集索引的数据上根据键值取数据。
非聚集索引查找:非聚集索引包含创建索引时所包含列的数据,在这些非聚集索引的数据上根据键值取数据。
Hash Match
表关联或者数据聚合运算时会用到。
Hashing:在数据库中根据每一行的数据内容,转换成唯一符号格式,存放到临时哈希表中,当需要原始数据时,可以给还原回来。类似加密解密技术,但是他能更有效的支持数据查询。
Hash Table:通过hashing处理,把数据以key/value的形式存储在表格中,在数据库中他被放在tempdb中。
建议:把关联的字段加上索引
Nested Loops
把两个不同列的数据集汇总到一张表中。提示信息中的Output List中有两个数据集,下面的数据集(inner set)会一一扫描与上面的数据集(out set),扫描完为止,这个操作才算是完成。
Merge Join
这种关联算法是对两个已经排过序的集合进行合并。如果两个聚合是无序的则将先给集合排序再进行一一合并,由于是排过序的集合,左右两个集合自上而下合并效率是相当快的。
Sort(排序)
对数据集合进行排序,需要注意的是,有些数据集合在索引扫描后是自带排序的。
Filter(筛选)
根据出现在having之后的操作运算符,进行筛选
Computer Scalar
在需要查询的列中需要自定义列,比如count(*) as cnt ,select name+‘’+age 等会出现此符号。
Microsoft SQL Server Profiler 是 SQL 跟踪的图形用户界面,用于监视数据库引擎或 Analysis Services 的实例。 您可以捕获有关每个事件的数据并将其保存到文件或表中供以后分析。 例如,可以对生产环境进行监视,了解哪些存储过程由于执行速度太慢而影响了性能。SQL Server Profiler 用于下列活动中:
可以从SQL Server Management Studio中打开
也可以直接快捷方式打开
可以选择显示所有监听的事件显示所有的列信息
设置好筛选条件之后确定就行了。
这里需要介绍一下默认选择器的含义:
如果显示所有事件,还有其他一些列,比如现在筛选数据库id是6的数据库,查找数据库id可以用如下sql
select DB_ID ('数据库名称');
可以开始监听,暂停,关闭
可以对监听结果进行筛选
清空跟踪窗口
新建跟踪
新建跟踪模板
导出导入跟踪模板
打开跟踪文件,如果跟踪配置了将跟踪结果保存到文件,后续就可以打开跟踪文件
查看当前的跟踪属性,跟踪停止后才能编辑
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。