0
点赞
收藏
分享

微信扫一扫

SQL Server 数据库(高级)完结篇


SQL Server 数据库

  • ​​1.0 数据库设计​​
  • ​​1.1 什么是数据库设计?​​
  • ​​1.2 设计数据库的重要性​​
  • ​​1.3 实体—关系​​
  • ​​1.4 数据库设计步骤:​​
  • ​​1.5 绘制E-R图​​
  • ​​1.6 映射基数​​
  • ​​1.7 将E-R图转换为表​​
  • ​​1.8 设计中的问题​​
  • ​​1.9 一个好的数据库设计应满足如下条件:​​
  • ​​1.10 规范设计(数据库设计三大范式)​​
  • ​​2.0 Transact-SQL编程​​
  • ​​2.1 变量:局部变量 和 全局变量​​
  • ​​2.2 输出语句​​
  • ​​2.3 逻辑控制语句​​
  • ​​3.0 SQL高级查询​​
  • ​​3.1 子查询简介​​
  • ​​3.2 使用in 和 not in完成子查询​​
  • ​​3.3 使用exists 和not exists完成子查询​​
  • ​​3.4 使用some、any、all进行查询​​
  • ​​3.5 使用compute和compute by进行汇总查询​​
  • ​​3.6 排序函数语法:​​
  • ​​3.7 排序函数:​​
  • ​​3.8 公式表表达式​​
  • ​​4.0 索引和视图​​
  • ​​4.1 聚集索引和非聚集索引的区别​​
  • ​​4.2 其他类型索引​​
  • ​​4.3 指定按索引查询:​​
  • ​​4.4 适合创建索引的列:​​
  • ​​4.5 视图​​
  • ​​5.0 事务和游标​​
  • ​​5.1 事务​​
  • ​​5.2 事务的模式​​
  • ​​5.3 事务处理​​
  • ​​5.4 游标​​
  • ​​5.5 三种游标​​
  • ​​5.6 游标的基本操作​​
  • ​​6.0 存储过程​​
  • ​​6.1 存储过程的使用​​
  • ​​6.2 用户定义的存储过程​​
  • ​​7.0 触发器​​
  • ​​7.1 创建insert触发器​​
  • ​​7.2 创建delete触发器​​
  • ​​7.3 创建update触发器​​

1.0 数据库设计

1.1 什么是数据库设计?

        规划和结构化数据库中的数据对象及这些数据之间关系的过程

1.2 设计数据库的重要性

不经过设计或者糟糕的数据库设计最终很可能导致:
    ● 数据库运行效率低下
    ● 更新、删除和查询数据时出现诸多问题

良好的数据库设计最终可表现为:
    ● 执行效率高
    ● 使应用程序更便于开发
    ● 容易进一步扩展

1.3 实体—关系

​实体​​​:凡是可以互相区别而被人们认识的事、物、概念等统统抽象为实体
​​​属性​​​:实体一般具有若干特征,称之为实体的属性;属性对应表中的列
​​​关系​​:实体与实体之间的关系抽象为联系

1.4 数据库设计步骤:

(1)需求分析阶段;(2)概要设计阶段;(3)详细设计阶段

1.5 绘制E-R图

矩形表示​​实体集​​​、 椭圆表示​​属性​​​、 菱形表示​​关系​​​ 直线用来连接实体集与属性,同时也用来连接实体集与关系
直线上的箭头用来表示实体集之间的映射基数

1.6 映射基数

一对一 、一对多 、多对一 、多对多

1.7 将E-R图转换为表

(1) 将各实体转化为对应的表,将各属性转换为各表中对应的列
(2) 标识每张表中的主键
(3) 将实体之间的关系转换为表与表之间的主外键关系

1.8 设计中的问题

1、 数据冗余大
2、 插入异常
3、 删除异常
4、 更新异常

1.9 一个好的数据库设计应满足如下条件:

◾ 尽可能少的数据冗余
◾ 没有插入异常
◾ 没有删除异常
◾ 没有更新异常

1.10 规范设计(数据库设计三大范式)

第一范式(1NF):关系中的每个属性必须是不可再分的简单项,不能是属性组合,即属性的取值必须是不可拆分的原子值
第二范式(2NF):◾ 表必须符合第一范式 ◾ 表中的每列必须依赖主键
第三范式(3NF):确保每列都和主键列直接相关,而不是间接相关
        定义:如果一个关系满足2NF,并且除了主键外的其他列既不部份依赖也不传递依赖于主键列,则满足第三范式

2.0 Transact-SQL编程

2.1 变量:局部变量 和 全局变量

局部变量(在方法中声明的变量)

--声明局部变量的语法:  declare @变量名 数据类型
--局部变量的赋值: select @变量名 = 值 (直接赋值或查询数据赋值)
--例:
select @变量名 = ‘111’ 或 ( set @变量名= ‘111’ )
select @变量名 = 字段名 from 表明 [where 条件]

全局变量(声明为static的变量)
        ​​​全局变量​​是SQL Server系统内部使用的变量,其作用范围并不局限于某一程序而是任何程序均可随时调用
        全局变量不是有用户的程序定义它们是在服务器级定义的,只能使用预先说明及定义的全局变量
        引用全局变量是必须以@@开头,局部变量的名称不能与全局变量的名称相同,否则会在应用中出错

全局变量

含 义

@@connections

返回SQL Server自上次启动以来尝试的连接次数,无论链接是成功还是失败

@@cursor_rows

返回连接上打开的上一个游标中的当前限定行的数目

@@error

返回执行上的一个Transact-SQL语句

@@identity

返回最后插入的标识值的系统函数

@@language

返回当前所用语言的名称

@@max_connections

返回SQL Server实例允许同时进行的最大用户连接数

@@procid

返回Transact-SQL当前模块的对象标识符(ID)。Transact-SQL模块可以是存储过程、用户定义函数或触发器

@@rowcount

返回受上一句影响的行数

@@servername

返回运行在SQL Server的本地服务器的名称

@@servicename

返回SQL Server正在其下运行的注册表项的名称。若当前实例为默认实例,则@@servicename

@@version

返回当前的SQL Server的安装版本、处理器体系结构、生成日期和操作系统

2.2 输出语句

        T-SQL支持输出语句,用于输出处理的数据结果
                常用输出语句有两种: ​​​print​​​变量或表达式 || ​​select​​ 变量或表达式

2.3 逻辑控制语句

        if-else语句

--语法结构:
if( 条件表达式 )
begin
命令行或程序块
end
else
begin
命令行或程序块
end

        while-continue-break语句

--语法结构:
while(条件表达式)
begin
命令行或程序块
[break] →→ 跳出循环
[continue] →→ 可以让程序跳过continue命令之后的语句
命令行或程序块
end

        case语句

--语法结构:
case
begin
when 条件表达式 then 运算式
when 条件表达式 then 运算式
[else 运算式]
end

--批处理( go )
-- 批处理可以提高语句的执行效率 go关键字标志着批处理的结束

3.0 SQL高级查询

3.1 子查询简介

子查询是一个嵌套在select、insert、update、delete语句的其他查询中的查询。任何允许使用表达式的地方都可以使用子查询。子查询也称为内部查询或内部选择,而包含子部查询的语句也称为外部查询或外部选择

子查询的特点和优势:
(1)使用灵活
        ● 可以成为SQL语句的多个部分
        ● 子查询作为查询条件使用
        ● 子查询作为临时表使用
        ● 子查询作为列使用
(2)降低SQL语句的复杂度,提高SQL语句的可读性

3.2 使用in 和 not in完成子查询

        ​​in​​​ 和 ​​not in​​​ 通常在where子句中使用,在​​in​​​ 或 ​​not in​​ 后接的子查询中可以有多个值出现

3.3 使用exists 和not exists完成子查询

        ​​exists​​​ 和 ​​not exists​​​表示存在和不存在的意思。在语句中会判断​​exists​​​ 或 ​​not exists​​后接的子句是否存在和是否不存在

3.4 使用some、any、all进行查询

在SQL查询中,​​some​​​、​​any​​​、​​all​​ 后必须跟子查询
        some和any的查询功能是一样的,where条件能够满足some和any所接的子查询中的任意一个值,就表示where条件成立

all表示的是能够满足all所接的子查询中的所有值才成立
--例:
all(1,2,3)表示大于3。>all表示至少大于一个值,即大于最小值

3.5 使用compute和compute by进行汇总查询

​compute​​​ 和 ​​compute by​​​子句使您得以用同一​​select​​语句即查看明细行,有查看汇总行。可以计算子组的汇总值,也可以计算整个结果集的汇总值

当​​compute​​​不带可选的​​by​​​子句时,​​select​​​语句有两个结果集:
        ● 每个组的第一个结果集是包含选择列表信息的所有明细行
        ● 第二个结果集有一行,其中包含compute子句中所指定的聚合函数的合计

​compute​​​子句需要下列信息:
        ● 可选by关键字。它基于每一列计算指定的行聚合
        ● 行聚合函数名称 ​​​SUM​​​、​​AVG​​​、​​MIN​​​、​​MAX​​​、或 ​​COUNT​​         ● 要对其执行行聚函数的列

对结果先进行分组然后进行汇总计算时使用:​​compute by​​进行分组汇总查询

3.6 排序函数语法:

排序函数 ​​over​​​( [分组子句] 排序子句[desc][asc] )
排序子句:​​​order by​​​ 排序列,排序列···
分组子句:​​​partition by​​分组列,分组列···

3.7 排序函数:

​row_number()​​​ 特点:没有并列编号,不跳空编号
​​​rank()​​​ 特点:有并列编号,有跳空编号
​​​dense_rank()​​ 特点:有并列编号,不跳空编号

3.8 公式表表达式

公用表表达式(CET)视为临时结果集,在​​select​​​、​​insert​​​、​​update​​​、​​delete​​​ 或 ​​create view​​语句的执行范围内进行定义

--CET基本语法结构:
with 公用表表名 (字段列表)
as ( 命令行或程序块 )
select * from 公用表表名

4.0 索引和视图

        索引:数据表中数据和相应存储位置的列表;能根据简单的信息查找到数据所在的位置
        作用:提高执行查询的速度
        分类:聚集索引 和 非聚集索引
:默认情况下主键就是聚集索引,一张表只能有一个聚集索引
        聚集索引:表中数据行的物理存储顺序和索引顺序完全相同
        非聚集索引:不改变表中数据行的物理存储位置,数据和索引分开存储,通过索引指向的地址与表中数据发生关系

4.1 聚集索引和非聚集索引的区别

聚集索引

非聚集索引

每个表只允许有一个聚集索引

最多可以有249个非聚集索引

物理地重排表中的数据以符合索引约束

创建一个键值列表键值指向数据在数据页中的位置

用于经常查找数据的列

用于从中查找单个值的列

4.2 其他类型索引

        唯一索引:如果希望索引键都不相同,可以创建唯一索引,聚集索引和非聚集索引都可以是唯一索引
        包含性列索引:在SQL2008系统中索引的最大数量是16个,索引列的字节总数的最高值是900,如果当多个列的字节总数大于900,且又想将这些列都包含在索引中时,可以使用包含性列索引
        视图索引:如果希望提高视图的查询效率,可以将视图的索引物理化,也就是说将结果永久的储存在索引中,可以创建视图索引
        XML索引:与XML数据关联的索引形式,是XML二进制BLOB的已拆分持久表示形式
        全文索引:一种特殊类型的基于标记的功能性索引,由SQL全文引擎服务创建和维护,用于帮助在字符串中搜索复杂的词

--创建索引:
--语法:
create 索引类型 index IX_name
on table_name(字段)
[where fillfactor = x]

        unique:唯一索引
        clustered:聚集索引
        nonclustered:非聚集索引
        table_anme:数据表名,也可以是视图名
        fillfactor:设置填充因子的大小,指定0-100之间的值,该值指示索引页填满的空间所占百分比,一般为30

4.3 指定按索引查询:

​Select * from table_name with(index = IX_name) where 条件​

4.4 适合创建索引的列:

        当数据表中的某一列被频繁用于数据搜索时,或者该列用于对数据进行排序时可以创建成索引

4.5 视图

● 视图名称必须遵循标识符的规则
● 可以对其他视图创建视图,嵌套不得超过32层,视图最多可包含1024个字段
● 不能将规则或default定义以视图相关联
● 定义视图的查询不能包含compute子句、compute by子句或into关键字
● 定义视图的查询不能包含 order by子句,除非在select语句的选择列表中还有一个top子句

下列情况必须指定视图中每列的名称

● 视图中的任何列都是从算术表达式、内置函数或常量派生而来的
● 视图中有两列或多列具有相同名称
● 希望为视图中的列指定一个与其原列不同的名称,也可以在视图中重命名列,无论重名与否,视图列都会继承其源列的数据类型

创建视图

--语法:
create view view_name(别名)
[with encryption] 创建加密视图
as
<select 语句>

--查看视图
Select * from view_name

5.0 事务和游标

5.1 事务

        事务是一个不可分割的逻辑单元

特点:
原子性:事务内的所有工作要么全部完成,要么全部没有完成
一致性:事务内的任何操作都不能违反数据库的任何约束或规则
隔离性:事务之间是相互隔离的
持久性:事务完成后,他对数据库的影响是持久的

5.2 事务的模式

显式事务、自动提交事务、隐式事务

5.3 事务处理

​begin transaction​​​ 标记一个本地事务的开始
​​​commit transaction​​​ 用于提交事务
​​​rollback transaction​​​ 用于事务回滚

使用@@error全局变量记录执行过程中的错误

--语法:
begin transaction tran_name
declare @tran_error int -- →定义变量用于记录错误
--< T-SQL语句 >
set(select) @tran_error = @tran_error + @@error
if @tran_error <> 0
begin
--执行事务回滚
rollback transaction
print”***”
end
else
begin
--提交事务
commit transaction
print”***”
end

5.4 游标

游标是一种能从包括多条数据记录的结果集中每次提取一条记录的机制

使用游标,可以实现以下目标
● 允许定位到结果集中的特定行
● 从结果集的当前位置检索一行或多行数据
● 支持对结果集中当前位置的行进行修改
:游标不建议 使用

5.5 三种游标

T-SQL游标、API游标、客户端游标

5.6 游标的基本操作

定义游标、打开游标、循环读取游标、关闭游标、删除游标

--定义一个游标
declare游标名 cursor scroll for select字段列表 from 表名
--打开游标
open 游标名
--定义变量,用于存放游标读取出来的值
declare @xxx 数据类型
--读取游标的第一条数据,并存放在变量中
fetch first from 游标名 into @xxx
--循环记录游标读取的数据
print '读取的数据如下:'
while(@@FETCH_STATUS =0)
begin
--使用print输出读取的数据
print'文字说明:'+xxx
--读取下一条记录
fetch next from 游标名 into @xxx
end
--读取完成后关闭游标
close 游标名
go
--删除游标
deallocate 游标名
go

全局变量 @@FETCH_STATUS 的值有三种:
        0:表示fetch语句成功
        -1:表示fetch语句执行失败或此行不在结果集中
        -2:表示被提取的行不存在

6.0 存储过程

        存储过程:是一组为了完成特定功能的SQL语句集合

常用系统存储过程

说明

sp_databases

列出服务器上的所有数据库

sp_tables

返回可在当前环境中查询的对象列表

sp_columns

返回可在当前环境中查询的指定表或视图的列信息

sp_helpindex

报告有关表或视图上索引的信息

sp_helpconstraint

返回某个表的约束

sp_stored_procedures

返回当前环境中的存储过程列表

sp_helptext

显示用于在多行中创建对象的定义

sp_helpdb

报告有关指定数据库或所有数据库信息

sp_defaultdb

更改Microsoft SQL Server登录名的默认数据库

sp_renamedb

更改数据库的名称

sp_rename

在当前数据库中更改用户创建对象的名称,此对象可以是表、索引、列

用法:exec 存储过程

6.1 存储过程的使用

--使用系统存储过程在D盘创建一个“Back”文件夹
select * from sys.configurations where name = 'xp_cmdshell' or name = 'show advanced options'
go
use master --使用系统数据库
go
reconfigure --刷新配置
go
exec sp_configure 'show advanced options',1 --启用 xp_cmdshell 高级配置
go
reconfigure --刷新配置
go
exec sp_configure 'xp_cmdshell',1 --打开xp_cmdshell进行文件夹操作
go
reconfigure --刷新配置
go
exec xp_cmdshell 'md D:\Back',no_output
go

--创建数据库放在D盘的Back文件夹下
if exists(select * from sys.databases where name = 'StuInfo')
drop database StuInfo
go
create database StuInfo
on(
name = 'StuInfo',
filename = 'D:\Back\StuInfo.mdf'
)
log on(
name = 'StuInfo_log',
filename = 'D:\Back\StuInfo.ldf'
)
exec xp_cmdshell 'dir D:\Back\'
go

6.2 用户定义的存储过程

if exists(select * from sysobjects where name = 'proc_xxx')
drop proc proc_xxx
go
create proc proc_xxx
@xxx 数据类型,有参
@xxx 数据类型 = 值,默认参数
@xxx 数据类型 output 输出参数
as
SQL语句
go
declare @xxx 数据类型
select @xxx = 值
exec proc_xxx 参数值, @xxx output
print '文字说明'+参数变量
go

--自定义错误
if exists(select * from sys.objects where name='proc_xxx')
drop proc proc_xxx
go
create proc proc_xxx
@xxx 数据类型
as
if @g <0 or @g>100
begin
--定义错误信息
例:raiserror('及格线必须在0~100之间',16,1)
return
end
select @xxx
go
exec proc_xxx 参数值
go

7.0 触发器

        触发器是对表进行插入、更新或者删除的时候会自动执行的特殊存储过程

对表的操作

inserted逻辑表

deleted逻辑表

增加记录(insert)

存放增加的记录


删除记录(delete)


存放被删除的记录

修改记录(update)

存放更新后的记录

存放更新前的记录

7.1 创建insert触发器

if exists(select * from sysobjects where name = 'trigger_xxx_insert')
drop trigger trigger_xxx_insert
go

create trigger trigger_xxx_insert
on table_Name --对应表名
for insert --触发器类型
as
--定义变量
declare @xxx
--赋值
select @xxx = xxx from table_Name
--判断操作类型
if @TransType = '存入'
update backupTABLE set 字段名+= @xxx where 字段名=@xxx
else
update backupTABLE set 字段名-= @xxx where 字段名=@xxx
--查询当前账户总金额
select @xxx = 字段名 from table_Name where 字段名=@xxx
print '文字说明'+参数
go

--测试触发器
insert SQL语句
print '原账户信息'
select * from table_Name
PRINT '交易信息'
select * from table_Name
PRINT '账户最新信息'
select * from table_Name
go

7.2 创建delete触发器

if exists(select * from sys.objects where name = 'trigger_xxx_delete')
drop trigger trigger_xxx_delete
go

create trigger trigger_xxx_delete
on TRANsInfo
for delete
as
print'备份中...'
if exists(select * from sys.objects where name ='backupTRANsInfo')
insert into backupTRANsInfo select * from deleted
else
select * into backupTRANsInfo from deleted
print'备份成功!'
go

--测试触发器
set nocount on
print '删除前原始表的数据'
select * from TRANsInfo
delete from TRANsInfo
print '删除后备份表的数据'
select * from backupTABLE
go

7.3 创建update触发器

if exists(select * from sys.objects where name = 'trigger_StockInfo_update')
drop trigger trigger_StockInfo_update
go

create trigger trigger_StockInfo_update
on StockInfo
for update
as
--定义变量 交易前数量 交易后的数量 交易数量
declare @BeforAmount int ,@AfteAmount int ,@TransAmount int
--赋值
select @BeforAmount = StockAmount from deleted --交易前数量
select @AfteAmount = StockAmount from inserted --交易后的数量
select @TransAmount = @BeforAmount - @AfteAmount --交易数量
--判断交易金额是否正常(>0)
if @TransAmount>0
begin
--如果交易数量大于库存数量
if @TransAmount > @BeforAmount
begin
print'交易数量:'+convert(varchar(10),ABS(@BeforAmount - @AfteAmount))
--提示错误信息
raiserror('商品库存不足',16,1)
--回滚事务
rollback transaction
end
end
go

--测试触发器
set nocount on
select * from StockInfo
update StockInfo set StockAmount -= 100 where GoodsID = 1
select * from StockInfo
go


举报

相关推荐

0 条评论