1.sql sever增删改相关

-- 切换数据库

-- use 数据库名;

1.1创建部门表

create table Department

(

-- 部门编号,primary key:主键,identity(1,1),自动增长,初始值1增长步长1

DepartmentId int primary key identity(1,1),

-- 部门名称

DepartmentName nvarchar(50) not NULL,

-- 部门描述

DepartmentRemark text

)

 

说明:

-- char:定长,char(10),无论存储数据是否真的到了10个字节,都要占用10个字节。

-- char(10)存储'ab',仍然占用10个字节。

-- varchar:变长,varchar(10),最多占用10个字节。

-- varchar(10)存储'ab',占用2个字节

-- text长文本

-- char,varchar,text前面加n:存储unicode字符,对中文友好

-- varchar(100):存储100个字母或者50个汉字。

-- nvarchar(100):存储100个字母或者100个汉字。

创建职级表[Rank]:

create table [Rank]

(

-- 部门编号,primary key:主键,identity(1,1);自动增长,初始值1,增长步长1

RankId int primary key identity(1,1),

-- 部门名称

RankName nvarchar(50) not NULL,

-- 部门描述

RankRemark text

)

创建员工表:

create table People

(

People int primary key identity(1,1), -- 员工编号

DepartmentId int references Department(DepartmentId)not null,-- 部门

RankId int references [Rank](RankId)not null,-- 职级(引用外键)

PeopleName nvarchar(50) not null, -- 姓名

PeopleSex nvarchar(1)default('男') check(PeopleSex='男' or PeopleSex='女') not null,-- 性别

PeopleBirth smalldatetime not null,-- 生日

PeopleSalary decimal(12,2) check(PeopleSalary>=1000 and PeopleSalary<=10000000) not null,-- 月薪

-- unique代表唯一约束,为数据提供唯一性保证

PeoplePhone varchar(20)unique not null,-- 电话

PeopleAddress nvarchar(100)-- 地址

-- datetime和smalldatechar(100)都可以表示时间类型,getdate()用于获取系统当前时间,default()设置默认值

PeopleAddTime smalldatetime default(getdate()) -- 添加时间

)

1.2修改表结构:

  • 添加字段(列)

-- alter table 表名 add 新列名 数据类型

alter table people add PeopleMail varchar(200)

  • 删除字段(列)

-- alter table 表名 drop column PeopleMail

alter table People drop column PeopleMail

  • 修改字段(列)

-- alter table 表名 alter column 列名 数据类型

alter table People alter column PeopleAddress varchar(200)

1.3维护约束(删除,添加):

-- 删除约束

-- alter table 表名 drop constraint 约束名

-- 删除月薪的约束

alter table People drop constraint CK_PeopleSa_34C8D9D1

约束添加:

-- 添加约束(check约束)

-- alter table People add constraint 约束名 check()

-- 添加工资字段约束,工资必须在1000-1000000之间

alter table People add constraint CK_People_PeoPleSal

check(PeopleSalary>=1000 and PeopleSalary<=1000000)

-- 添加约束(主键)

--alter table 表名 add constraint 约束名 primary key(列名)

-- 添加约束(唯一)

--alter table 表名 add constraint 约束名 unique(列名)

-- 添加约束(默认值)

--alter table 表名 add constraint 约束名 default 默认值 for 列名

-- 添加约束(外键)

-- alter table 表名 add constraint 约束名 foreign key(列名) references 关联表名(列名(主键))

1.4数据插入:

-- insert into 表名(column1,column2,column3…)value(…,…,…,)

1.5修改数据:

-- 语法

-- update 表名 set 字段1=值1,字段2=值2 where 条件

-- 工资调整,每个人加薪1000

update People set PeopleSalary=PeopleSalary+1000

-- 将员工编号为7的人加薪500

update People set PeopleSalary=PeopleSalary+500 where PeopleId=7

-- 将软件部(部门编号1)人员工资低于10000的调整成10000

update People set PeopleSalary=10000 where DepartmentId=1 and PeopleSalary<10000

-- 修改刘备的工资是以前的两倍,并且把刘备的地址改成北京

update People set PeopleSalary=PeopleSalary*2,PeopleAddress='北京' where PeopleName='刘备'

1.6删除数据:

-- 语法:

--delete from 表名 where 条件

-- 删除员工表所有数据

delete from People

-- 删除市场部(部门编号3)工资大于10000的人

delete from People where DepartmentId=3 and PeopleSalary>10000

注:关于删除(drop,truncate,delete)

-- 删除表对象

drop table People

-- 删除数据(清空数据)

-- 删除所有数据,表对象即表结构依然存在

truncate table People delete from People

-- truncate和delete区别

-- truncate清空所有数据不能有条件,delete可以删除所有数据也可以带条件,删除符合条件的数据

-- 自动编号:

-- 假设表中自动编号为1,2,3,4,5

-- 使用truncate清空数据之后再添加数据,编号仍然是1,2,3,4,5,

-- 使用delete删除数据,删除的自动编号将永远不存在了

-- 如果使用delete删除了所有的数据之后再添加数据,编号就变成了,6,7,8,9,10

 

2.查询相关:

2.1简单查询:

-- 查询所有列所有行

select * from Department

-- 查询指定列(姓名,性别,生日,月薪,电话)

select PeopleName,PeopleSex,PeopleBirth,PeopleSalary,PeoplePhone from People

-- 查询指定列(姓名,性别,生日,月薪,电话)(显示中文列名)

select PeopleName 姓名,PeopleSex 性别,PeopleBirth 生日,PeopleSalary 月薪,PeoplePhone 电话 from People

-- 查询员工所在城市

select distinct(PeopleAddress) from People

-- 假设准备加工资(上调20%),查询出加工资前和加工资后的员工数据

select PeopleName 姓名,PeopleSex 性别,PeopleSalary 原始月薪,PeopleSalary*1.2 加薪后的月薪 from People

2.2条件查询:

SQL中常用运算符

2.3多条件查询

-- 查询月薪大于等于10000的员工,或者月薪大于等于8000的女员工

select * from People where PeopleSalary>=10000 or (PeopleSalary>=8000 and PeopleSex='女')

-- 查询出出生年月在1980-1-1之后,而且月薪大于等于10000的女员工

select * from People where PeopleBirth>=('1980-1-1') and (PeopleSalary>=10000 and PeopleSex='女')

-- 查询月薪在10000-20000之间的员工信息(多条件)

select * from People where PeopleSalary>=10000 and PeopleSalary<=20000

select * from People where PeopleSalary between10000 and 20000

-- 查询地址在武汉或者北京的员工信息

select * from People where PeopleAddress='武汉' or PeopleAddress='北京'

select * from People where PeopleAddress in('武汉' ,'北京')

2.4排序:

-- 查询所有员工信息,根据工资排序,降序

-- asc升序(默认),desc降序

select * from People order by PeopleSalary desc

-- 查询所有员工信息,根据名字长度排序(降序)

select * from People order by .len(PeopleName) desc

-- 查询出工资最高的5个人的信息

select top 5 * from People order by PeopleSalary decs

-- 查询出工资最高的10%的员工信息

select top 10 percent * from People order by PeopleSalary desc

-- 查询null:空值

-- 查询出地址没有填写的员工信息

select * from People where PeopleAddress is null

-- 查询出地址填写的员工信息

select * from People where PeopleAddress is not null

-- 查询出80后的员工信息

select * from People where PeopleBirth>='1980-1-1' and PeopleBirth>='1989-12-31'

select * from People where People Birth between '1980-1-1' and '1989-12-31'

select * from People where year(PeopleBirth) between 1980 and 1989

-- 查询30-40岁之间,并且工资在15000-30000之间的员工信息

-- 假设 年龄=当前年份-生日年份

select * from People where

(year(getdatea())-year(peopleBirth)>=30 and year(getdate())-year(PeopleBirth)<=40)

and

(PeopleSalary between 15000 and 30000)

select * from People where

(year(getdatea())-year(peopleBirth) between 30 and 40)

and

(PeopleSalary between 15000 and 30000)

-- 查询出星座是巨蟹座的员工信息(6.22-7.22)

select * from People where

(month(PeopleBirth)=6 and day(PeopleBirth)>=22)

or

(month(PeopleBirth)=7 and day(PeopleBirth)<=22)

2.5子查询:

-- 查询出工资比赵云高的信息

select * from People where PeopleSalary>

(select PeopleSalary from People where PeopleName='赵云')

-- 查询出和赵云在一个城市的人的信息

select * from People where PeopleAddress=

(select PeopleAddress from People where PeopleName='赵云')

-- 查询出生肖是鼠的人员信息

-- 鼠 (子)、牛 (丑)、虎 (寅)、兔 (卯)、龙 (辰)、蛇 (巳)、马 (午)、羊 (未)、猴 (申)、鸡 (酉)、狗 (戌)、猪 (亥)

-- 出生年份%12                12生肖对应——>4 5 6 7 8 9 10 0 1 2 3

select * from People where year(PeopleBirth)%12=4

-- 查询所有员工信息,添加一列,显示生肖

select *,

case

when year(PeopleBirth)%12=4 then '鼠'

when year(PeopleBirth)%12=5 then '牛'

when year(PeopleBirth)%12=6 then '虎'

when year(PeopleBirth)%12=7 then '兔'

when year(PeopleBirth)%12=8 then '龙'

when year(PeopleBirth)%12=9 then '蛇'

when year(PeopleBirth)%12=10 then '马'

when year(PeopleBirth)%12=11 then '羊'

when year(PeopleBirth)%12=0 then '猴'

when year(PeopleBirth)%12=1 then '鸡'

when year(PeopleBirth)%12=2 then '狗'

when year(PeopleBirth)%12=3 then '猪'

end 生肖

from People

select *,

case year(PeopleBirth)%12

when 4 then '鼠'

when 5 then '牛'

when 6 then '虎'

when 7 then '兔'

when 8 then '龙'

when 9 then '蛇'

when 10 then '马'

when 11 then '羊'

when 0 then '猴'

when 1 then '鸡'

when 2 then '狗'

when 3 then '猪'

end 生肖

from People

2.6模糊查询:

  • %:代表匹配0个字符、1个字符或多个字符
  • _:代表匹配有且只有1个字符
  • []:代表匹配范围内
  • [^]:代表匹配不在范围内

(1)查询姓刘的员工信息

select * from People where PeopleName like '刘%'

(2)查询名字中含有尚的员工信息

select * from People where PeopleName like '%尚%'

(3)查询名字中含有“尚”或者“史”的员工信息

select * from People where PeopleName like '%尚%' or '%史%'

(4)查询出姓刘的员工信息(名字两个字)

select * from People where PeopleName like '刘_'

-- SUBSTRING(字符串',开始,个数)

-- SUBSTRING('hello,world',3,1) -- l

select * from People where SUBSTRING(PeopleName,1,1)='刘'

and len(PeopleName)=2

-- 查询名字最后一个字为香,名字一共是三个字的员工信息

select * from People where SUBSTRING(PeopleName,3,1)='香'

and len(PeopleName)=3

-- 查询出电话号码,开头为138的员工信息

select * from People where PeoplePhone like '138%'

-- 查询出电话号码开头为138的,第四位好像是7或8,最后一个号码是5

select PeoplePhone from People where PeoplePhone like '138[7,8]%5'

-- 查询出电话号码开头为138的,第四位好像是2-5之间,最后一个号码不是2和3

select PeoplePhone from People where PeoplePhone like '138[2,3,4,5]%[^2,3]'

select PeoplePhone from People where PeoplePhone like '138[2-5]%[^2-3]

2.7聚合函数:

SQL SERVER中聚合函数主要有:

count:求数量

max:求最大值

min:求最小值

sum:求和

avg:求平均值

一、聚合函数举例应用

(1)求员工总人数

select COUNT(*) 数量 from People

(2)求最大值,求最高工资

select MAX(PeopleSalary) 最高工资 from People

(3)求最小时,求最低工资

select MIN(PeopleSalary) 最低工资 from People

(4)求和,求所有员工的工资总和

select SUM(PeopleSalary) 工资总和 from People

(5)求平均值,平均工资

select round(AVG(PeopleSalary),2) 平均工资 from People

-- 四舍五入,保留两位小数

select round(25.5555,2)-- 25.5600

(6)求数量,最大值,最小值,总和,平均值,在一行显示

select COUNT(*) 数量,MAX(PeopleSalary) 最高工资,MIN(PeopleSalary) 最低工资,SUM(PeopleSalary) 工资总和,round(AVG(PeopleSalary),2) 平均工资 from People

(7)查询武汉地区的人数量,工资最大值,最小值,总和,平均值,在一行显示

select COUNT(*) 数量,MAX(PeopleSalary) 最高工资,MIN(PeopleSalary) 最低工资,SUM(PeopleSalary) 工资总和,round(AVG(PeopleSalary),2) 平均工资 from People where PeopleAddress='武汉'

(8)求出工资比平均工资高的人员信息

select * from People where PeopleSalary>(select round(AVG(PeopleSalary),2) from People)

(9)求数量,年龄最大值,年龄最小值,年龄总和,年龄平均值在一行显示

-- 方案一:

select COUNT(*) 数量,

year(getdate())-year(PeopleBirth) 年龄,

MAX(year(getdate())-year(PeopleBirth)) 年龄最大值,

MIN(year(getdate())-year(PeopleBirth)) 年龄最小值,

SUM(year(getdate())-year(PeopleBirth)) 年龄总和,

round(AVG(year(getdate())-year(PeopleBirth))) 年龄平均值

from People

-- 方案二:DATEDIFF(单位,被减数,减数)

select COUNT(*) 数量,

DATEDIFF(year,PeopleBirth,getdate()) 年龄,

MAX(DATEDIFF(year,PeopleBirth,getdate())) 年龄最大值,

MIN(DATEDIFF(year,PeopleBirth,getdate())) 年龄最小值,

SUM(DATEDIFF(year,PeopleBirth,getdate())) 年龄总和,

AVG(DATEDIFF(year,PeopleBirth,getdate())) 年龄平均值

from People

(10)计算出月薪在10000以上的男性员工的最大年龄,最小年龄和平均年龄

select '月薪10000以上' 月薪,'男' 性别,

COUNT(*) 数量,

DATEDIFF(year,PeopleBirth,getdate()) 年龄,

MAX(DATEDIFF(year,PeopleBirth,getdate())) 年龄最大值,

MIN(DATEDIFF(year,PeopleBirth,getdate())) 年龄最小值,

SUM(DATEDIFF(year,PeopleBirth,getdate())) 年龄总和,

AVG(DATEDIFF(year,PeopleBirth,getdate())) 年龄平均值

from People

where PeopleSalary >10000 and PeopleSex='男'

(11)统计出所在地在“武汉或上海”的所有女员工数量以及最大年龄,最小年龄和平均年龄

select '武汉或上海' 地区,'女' 性别,

COUNT(*) 数量,

DATEDIFF(year,PeopleBirth,getdate()) 年龄,

MAX(DATEDIFF(year,PeopleBirth,getdate())) 年龄最大值,

MIN(DATEDIFF(year,PeopleBirth,getdate())) 年龄最小值,

SUM(DATEDIFF(year,PeopleBirth,getdate())) 年龄总和,

AVG(DATEDIFF(year,PeopleBirth,getdate())) 年龄平均值

from People

where PeopleAddress in('武汉','上海') and PeopleSex='女'

(12)求出年龄比平均年龄高的人员信息

select * from People where DATEDIFF(year,PeopleBirth,getdate())>

(select AVG(DATEDIFF(year,PeopleBirth,getdate())) from People)

2.8分组查询:

(1)根据员工所在地区分组统计员工人数,员工工资总和,平均工资,最高工资和最低工资

-- group by:

select PeopleAddress 地区,COUNT(*) 数量,MAX(PeopleSalary) 最高工资,MIN(PeopleSalary) 最低工资,SUM(PeopleSalary) 工资总和,ROUND(AVG(PeopleSalary),2) 平均工资 from People

group by PeopleAddress

(2)根据员工所在地区分组统计员工人数,员工工资总和,平均工资,最高工资和最低工资,1985年及以后出生的员工不参与统计

select PeopleAddress 地区,COUNT(*) 数量,MAX(PeopleSalary) 最高工资,MIN(PeopleSalary) 最低工资,SUM(PeopleSalary) 工资总和,ROUND(AVG(PeopleSalary),2) 平均工资 from People

where PeopleBirth<'1985-1-1'

group by PeopleAddress

(3)根据员工所在地区分组统计员工人数,员工工资总和,平均工资,最高工资和最低工资,要求筛选出员工人数至少在2人及以上的记录,并且1985年及以后出生的员工不参与统计

-- having 、where的使用

select PeopleAddress 地区,COUNT(*) 数量,MAX(PeopleSalary) 最高工资,MIN(PeopleSalary) 最低工资,SUM(PeopleSalary) 工资总和,ROUND(AVG(PeopleSalary),2) 平均工资 from People

where PeopleBirth<'1985-1-1'

group by PeopleAddress

having COUNT(*)>=2

2.9多表查询:

--笛卡尔乘积

select * from People,Department -- 查询结果将Department所有的记录和People表所有记录一次排列组合形成的结果

-- 简单多条查询

-- 查询员工信息,显示部门名称

select * from People,Department

where People.DepartmentId=Department.DepartmentId

-- 查询员工信息,显示部门名称,显示职级名称

select * from People,Department,[rank]

where People.DepartmentId=Department.DepartmentId

and People.RankId=[Rank].RankId

2.10内连接查询:

-- 查询员工信息,显示部门名称

select * from People inner join Department

on People.DepartmentId=Department.DepartmentId

-- 查询员工信息,显示部门名称,显示职级名称

select * from People

inner join Departmenton on People.DepartmentId=Department.DepartmentId

inner join [rank] on People.RankId=[Rank].RankId

简单多表查询和内连接共同的特点:不符合主外键关系的数据不会被显示出来

3.连接查询

3.1外连接(左外连left join,右外连right join,全外连full join):

-- 左外联:以左表为主表进行数据显示,主外键关系找不到的数据null取代

-- 查询员工信息,显示部门名称

select * from People

left join Department on People.DepartmentId=Department.DepartmentId

-- 查询员工信息,显示职别名称

select * from People

left join [Rank] on People.RankId=[Rank].RankId

-- 查询员工信息,显示部门名称,显示职级名称

select * from People

left join Departmenton on People.DepartmentId=Department.DepartmentId

left join [rank] on People.RankId=[Rank].RankId

-- 右连接:A left join B =B right join A

-- 下面两个查询含义相同

select * from People

left join Department on People.DepartmentId=DepartmentId

select * from Department

right join People on People.DepartmentId=DepartmentId

-- 全外联:两张表的数据,无论是否符合关系,都要显示

select * from People

full join Department on People.DepartmentId=DepartmentId

3.2多表查询综合案例:

(1)查询出武汉地区所有的员工信息,要求显示部门名称以及员工的详细资料(显示中文别名)

select PeopleName 姓名,People.DepartmentId 部门编号, DepartmentName 部门名称,

PeopleSex 性别,PeopleBirth 生日,

PeopleSalary 月薪,PeoplePhone 电话,PeopleAddress 地区

from People left join Department on People.DepartmentId=Department.DepartmentId

where PeopleAddess='武汉'

(2)查询出武汉地区所有的员工信息,要求显示部门名称,职级名称以及员工的详细资料

select PeopleName 姓名,People.DepartmentId 部门编号, DepartmentName 部门名称,

PeopleSex 性别,PeopleBirth 生日,

PeopleSalary 月薪,PeoplePhone 电话,PeopleAddress 地区

from People left join Department on People.DepartmentId=Department.DepartmentId

left join [Rank] on People.RankId=[Rank].RankId

where PeopleAddess='武汉'

(3)根据部门分组统计员工人数,员工工资总和,平均工资,最高工资和最低工资

select DepartmentName 部门名称,count(*) 员工人数,sum(PeopleSalary) 员工工资总和,avg(PeopleSalary) 平均工资,max(PeopleSalary) 最高工资,min(PeopleSalary) 最低工资

from People

left join Department

on People.DepartmentId=Department.DepartmentId

group by Department.DepartmentId,DepartmentName

注:如果以名称分组,容易重名

(4)根据部门分组统计员工人数,员工工资总和,平均工资,最高工资和最低工资,平均工资在10000以下的不参与统计,并且根据平均工资降序排列

select DepartmentName 部门名称,count(*) 员工人数,sum(PeopleSalary) 员工工资总和,avg(PeopleSalary) 平均工资,max(PeopleSalary) 最高工资,min(PeopleSalary) 最低工资

from People

inner join Department

on People.DepartmentId=Department.DepartmentId

group by Department.DepartmentId,DepartmentName

having avg(PeopleSalary) >=10000

order by round(avg(PeopleSalary),2) desc

(5)根据部门名称,然后根据职位名称分组统计员工人数,员工工资总和,平均工资,最高工资和最低工资

select DepartmentName 部门名称,RankName 职位名称,count(*) 员工人数,sum(PeopleSalary) 员工工资总和,avg(PeopleSalary) 平均工资,max(PeopleSalary) 最高工资,min(PeopleSalary) 最低工资

from People

inner join Department on People.DepartmentId=Department.DepartmentId

inner join [Rank] on People.RankId=[Rank].RankId

group by Department.DepartmentId,DepartmentName,[Rank].RankId,RankName

3.3自连接(自己连自己)

DeptId

DeptName

parenId

1

软件部

0

2

硬件部

0

3

软件研发部

1

4

软件实施部

1

5

硬件研发部

2

6

硬件测试部

2

-- 起别名

select A.DeptId 部门编号,A.DeptName 部门名称,B.DeptName 上级部门 from Dept A

inner join Dept B on A.ParenId=B.DeptId

4.数据库设计

4.1数据库结构设计三范式

第一范式(1NF)是指表中的字段都是不可再分的原子属性,同时表需要有一个主键。

修改:

第二范式(2NF)首先需要满足第一范式,非主键字段必须完全依赖于主键字段,不能只依赖于主键的一部分。

修改:

        第三范式(3NF)首先需要满足第二范式,非主键字段不能依赖于其他非主键字段。为了提高查询性能可以降低规范化的级别,也就是反规范化(Denormalization)。

修改:

4.2表关系(一对一,一对多,多对多)

一对多(专业表、学生表)-- 可合并

一对一(学生基本信息(学号、姓名、性别),学生详细信息(电话、邮箱、地址))-- 添加字段关联

多对多(学生信息,课程信息)-- 可通过一张表关联

4.3案例分析:

业务需求说明:

模拟银行业务,设计简易版的银行数据库表结构,要求可以完成以下基本功能需求

1.银行开户(注册个人信息)及开卡(办理银行卡)(一个人可以办理多张银行卡,但是最多只能办理3张)

2.存钱

3.查询余额

4.取钱

5.转账

6.查看交易记录

7.账户挂失

8.账户注销

表设计

1.账户信息表

2.银行卡表

3.交易信息表(存储存钱和取钱的记录)

4.转账信息表(存储转账信息记录)

5.状态信息变化表(存储银行卡状态1:正常,2:挂失,3:冻结,4:注销)

表结构设计

create table AccountInfo -- 账户信息表

(

AccountId int primary key identity(1,1),-- 账户编号

AccountCode varchar(20) not null,-- 身份证号码

AccountPhone varchar(20) not null,-- 电话号码

RealName varchar(20) noy null,-- 真实姓名

OpenTime smalldatetime not null,-- 开户时间

)

create table BankCard --银行卡

(

CardNo varchar(30) primary key, -- 银行卡卡号

AccountId int primary key identity(1,1), -- 账户编号(域账户信息表形成主外键关系)

CardPwd varchar(30) not null, -- 银行卡密码

CardMoney money not null, -- 银行卡余额

CardState int not null, -- 1:正常,2:挂失,3:冻结,4:注销

CardTime smalldatetime default(getdate()), -- 开卡时间

)

create table CardExchange-- 交易信息表(存储存钱和取钱的记录)

(

ExchangeId int primary key identity(1,1), -- 交易自动编号

CardNo varchar(30) not null,-- 银行卡号(与银行卡表形成主外键关系)

MoneyInBank money not null,-- 存钱金额

MoneyOutBank money not null, -- 取钱金额

ExchangTime smalldatetime not null -- 建议时间

)

create table CardTransfer-- 转账信息表(存储转账信息记录)

(

TransferId int primary key identity(1,1),-- 转账自动编号

CardNoOut varchar(30) not null,-- 转出银行卡号(与银行卡表形成主外键关系)

CardNoIn varchar(30) not null,-- 转入银行卡号(与银行卡表形成主外键关系)

TransferMoney money not null,-- 交易金额

TransferTime smalldatetime not null,-- 交易时间

)

create table CardStateChange-- 状态信息变化表(存储银行卡状态1:正常,2:挂失,3:冻结,4:注销)

(

StateId int primary key identity(1,1),-- 状态信息自动编号

CardNo varchar(30) not null, -- 银行卡号(与银行卡表形成主外键关系)

CardState int not null,-- 银行卡原始状态

NewState int not null,-- 银行卡新状态

StateWhy varchar(200) not null,-- 状态变化原因

StateTime smalldatetime not null,-- 记录产生时间

)

案例:

为刘备,关羽,张飞三个人进行开户开卡的操作

刘备身份证:420107198905064135

关羽身份证:420107199507104133

张飞身份证:420107199602034138

insert into AccountInfo(AccountCode,AccountPhone,RealName,OpenTime)

values('420107198905064135','13555687749','刘备',GETDATE())

insert into BankCard(CardNo,AccountId,CardPwd,CardMoney,CardState,CardTime)

values('6225125478544587',1,'123456',0,1)

insert into AccountInfo(AccountCode,AccountPhone,RealName,OpenTime)

values('420107199507104133','13555687749','关羽',GETDATE())

insert into BankCard(CardNo,AccountId,CardPwd,CardMoney,CardState,CardTime)

values('6225125478544698',2,'123456',0,1)

insert into AccountInfo(AccountCode,AccountPhone,RealName,OpenTime)

values('420107199602034138','13555687749','张飞',GETDATE())

insert into BankCard(CardNo,AccountId,CardPwd,CardMoney,CardState,CardTime)

values('6225125478544709',3,'123456',0,1)

刘备存钱:2000元

update BankCard set CardMoney=CardMoney+2000 where CardNo='6225125478544587'

insert into CardExchange(CardNo,MoneyInBank,MoneyOutBank,ExchangeTime)

values('6225125478544587',2000,0,GETDATE())

转账:刘备给张飞转账1000元

update BankCard set CardMoney - 1000 Where CardNo='6225125478544587'

update BankCard set CardMoney + 1000 Where CardNo='6225125478544709'

insert into CardTransfer(CardNoOut,CardNoIn,TransferMoney,TransferTime)

Values('6225125478544587','6225125478544709',1000,GETDATE())

5.使用sql进行信息打印

5.1变量

①局部变量:以@开头,先声明,再赋值

declare @str varchar(20)

set @str ='I like sql'

-- select @str='i like sql'

print @str

-- set 和select进行赋值时的区别

-- set:赋值变量指定的值

-- select:一般用于表中查询出的数据赋值给变量,如果查询结果有多条,取最后一条赋值

-- exp:select @a=字段名 from 表名

-- 当前表最后一行的某个字段的值给@a

②全局变量:以@@开头,由系统进行定义和维护

@@CONNECTIONS

--返回自上次启动以来连接或试图连接的次数。

@@CURSOR_ROWS

--返回连接上最后打开的游标中当前存在的合格行的数量(返回被打开的游标中还未被读取的有效数据行的行数)

@@DATEFIRST

--返回每周第一天的数字

@@ERROR 

--返回最后执行的SQL 语句的错误代码。

@@FETCH_STATUS

--返回被 FETCH 语句执行的最后游标的状态,而不是任何当前被连接打开的游标的状态。

@@IDENTITY 

--返回最后插入的标识值

@@LANGID

--返回当前所使用语言的本地语言标识符(ID)。

@@LANGUAGE

--返回当前使用的语言名。

@@LOCK_TIMEOUT 

--返回当前会话的当前锁超时设置,单位为毫秒。 

@@PROCID

--返回当前过程的存储过程标识符 (ID) 。

@@ROWCOUNT 

--返回受上一语句影响的行数。 

@@SERVERNAME 

--返回运行 的本地服务器名称。 

@@SPID

--返回当前用户进程的服务器进程标识符 (ID)。

@@TRANCOUNT

--返回当前连接的活动事务数。

@@VERSION

--返回当前安装的日期、版本和处理器类型。

@@CPU_BUSY

--返回自SQL Server 最近一次启动以来CPU 的工作时间其单位为毫秒

@@DATEFIRST

--返回使用SET DATEFIRST 命令而被赋值的DATAFIRST 参数值SET DATEFIRST,命令用来指定每周的第一天是星期几

@@DBTS

--返回当前数据库的时间戳值必须保证数据库中时间戳的值是惟一的

@@ERROR

--返回执行Transact-SQL 语句的错误代码

@@FETCH_STATUS

--返回上一次FETCH 语句的状态值

@@IDLE

--返回自SQL Server 最近一次启动以来CPU 处于空闭状态的时间长短单位为毫秒

@@IO_BUSY

---返回自SQL Server 最近一次启动以来CPU 执行输入输出操作所花费的时间其单位为毫秒

@@LANGID

--返回当前所使用的语言ID 值

@@LANGUAGE

--返回当前使用的语言名称

@@LOCK_TIMEOUT

--返回当前会话等待锁的时间长短其单位为毫秒

@@MAX_CONNECTIONS

--返回允许连接到SQL Server 的最大用户连接数目

@@MAX_PRECISION

--返回decimal 和numeric 数据类型的精确度

@@NESTLEVEL

--返回当前执行的存储过程的嵌套级数初始值为0

@@OPTIONS

--返回当前SET 选项的信息

@@PACK_RECEIVED

--返回SQL Server 通过网络读取的输入包的数目

@@PACK_SENT

--返回SQL Server 写给网络的输出包的数目

@@PACKET_ERRORS

--返回网络包的错误数目

@@PROCID

--返回当前存储过程的ID 值

@@REMSERVER

--返回远程SQL Server 数据库服务器的名称

@@SERVICENAME

--返回SQL Server 正在其下运行的注册表项的名称

@@SPID

--返回当前用户处理的服务器处理ID 值

@@TEXTSIZE

--返回SET 语句的TEXTSIZE 选项值SET 语句定义了SELECT 语句中text 或image数据类型的最大长度基本单位为字节

@@TIMETICKS

--返回每一时钟的微秒数

@@TOTAL_ERRORS

--返回磁盘读写错误数目

@@TOTAL_READ

--返回磁盘读操作的数目

@@TOTAL_WRITE

--返回磁盘写操作的数目

@@TRANCOUNT

--返回当前连接中处于激活状态的事务数目

5.2实例:

(1)为赵云此人进行开户操作,赵云身份证:420107199904054233

insert into AccountInfo(AccountCode,AccountPhone,RealName,OpenTime)

values('420107199904054233','13555687766','赵云',GETDATE())

declare @AccountId int

set @AccountId=@@IDENTITY

insert into BankCard(CardNo,AccountId,CardPwd,CardMoney,CardState,CardTime)

values('6225125478544710',@AccountId,'123456',0,1)

(2)需要求出张飞的银行卡号和余额,张飞身份证:420107199602034138

select CardNo 卡号,CardMoney 余额 from BankCard

inner jion AccountInfo on BankCard.AccountId=AccountInfo.AccountId

where AccountCode ='420107199602034138'

declare @AccountId int

select @AccountId=

(select AccountId from AccountInfo where AccountCode='420107199602034138')

select CardNo 卡号,CardMoney 余额 from BankCard

where AccountId=@AccountId

5.3 go语句

1)等待go语句之前代码执行结束才能执行后面的代码

-- 例:

create datebase DBTEST1

use DBTEST1

create table AccountInfo --账户信息表

(

AccountId int primary key identity(1,1),-- 账户编号

AccountCode varchar(20) not null,-- 身份证号码

AccountPhone varchar(20) not null,-- 电话号码

RealName varchar(20) not null,-- 真实姓名

OpenTime smalldatetime not null,-- 开户时间

)

-- 执行失败,建库失败未完成,不能使用

create datebase DBTEST1

go -- 等待建库成功,才可以继续执行

use DBTEST1

create table AccountInfo --账户信息表

(

AccountId int primary key identity(1,1),-- 账户编号

AccountCode varchar(20) not null,-- 身份证号码

AccountPhone varchar(20) not null,-- 电话号码

RealName varchar(20) not null,-- 真实姓名

OpenTime smalldatetime not null,-- 开户时间

)

2)批处理结束的一个标志

declare @num int --@num作用范围全局

set @num =100

set @num =200

go

declare @num1 int --@num1作用范围在两个go之间

set @num1 =100

go

set @num1 =200 -- 不能赋值

6.运算符

6.1 sql中使用的运算符分为7

  1. 算数运算符:+、-、*、/、%(模)
  2. 逻辑运算符:AND 、OR、LIKE、EXISTS()-- 存在、NOT、ALL()-- 所有、ANY()-- 存在
  3. 赋值运算符:=
  4. 字符串运算符:+
  5. 比较运算符:=、>、<、>=、<=、<>(不等于)
  6. 位运算符:|、&、^
  7. 符合运算符:+=、-=、/=、%=、*=

6.2运算符示例:

(1)已知长方形的长和宽,求长方形的周长和面积

declare @c int =10

declare @k int =5

declare @zc int

declare @mj int

set @zc=(@c+@k)*2

set @mj=@c*@k

-- print '圆周长:'+cast(varchar(10),@zc)

-- print '圆面积:'+cast(varchar(10),@mj)

print'圆周长:'+Convert(@zc as varchar(10))

print'圆面积:'+Convert(@mj as varchar(10))

(2)查询银行卡状态为冻结,并且余额超过1000000的银行卡信息

select * from BankCard where CardState=3 and CardMoney>1000000

(3)查询出银行卡状态为冻结或者余额等于0的银行卡信息

select * from BankCard where CardState=3 or CardMoney=0

(4)查询出姓名中含有‘刘’的账户信息以及银行卡信息

select * from AccountInfo

inner join BankCard on AccountInfo.AccountId=BankCard.AccountId

where RealName like '%刘%'

(5)关羽身份证号:420107199507104133,关羽到银行来开户,查询身份证在账户表是否存在,不存在则进行开卡,存在则不开户直接开卡

declare @AccountId int

if EXISTS(select * from AccountInfo where AccountId='420107199507104133') -- 存在此人

begin

select @AccountId=

(select AccountId from AccountInfo where AccountId='420107199507104133')

insert into BankCard(CardNo,AccountId,CardPwd,CardMoney,CardState,CardTime)

values('6225125478544721',@AccountId,'123456',0,1)

end

else -- 不存在此人

begin

insert into AccountInfo(AccountCode,AccountPhone,RealName,OpenTime)

values('420107199904054233','13555687766','关羽',GETDATE())

set @AccountId=@@IDENTITY

insert into BankCard(CardNo,AccountId,CardPwd,CardMoney,CardState,CardTime)

values('6225125478544721',@AccountId,'123456',0,1)

end

(6)扩展:上面需求上添加一个限制,即一个人最多只能开3张银行卡

declare @AccountId int -- 账号编号

declare @CardCount int -- 卡数量

if EXISTS(select * from AccountInfo where AccountId='420107199507104133') -- 存在此人

begin

select @AccountId=

(select AccountId from AccountInfo where AccountId='420107199507104133')

select @CardCount=

(select count(*) from BankCard where AccountId=@AccountId)

if @CardCount<=2

begin

insert into BankCard(CardNo,AccountId,CardPwd,CardMoney,CardState,CardTime)

values('6225125478544721',@AccountId,'123456',0,1)

end

else

begin

print '您名下的银行卡太多了,最多只能有3张银行卡'

end

end

else -- 不存在此人

begin

insert into AccountInfo(AccountCode,AccountPhone,RealName,OpenTime)

values('420107199904054233','13555687766','关羽',GETDATE())

set @AccountId=@@IDENTITY

insert into BankCard(CardNo,AccountId,CardPwd,CardMoney,CardState,CardTime)

values('6225125478544721',@AccountId,'123456',0,1)

end

7.流程控制

7.1选择分支结构

(1)某用户银行卡号为“6225547854125656”

该用户执行取钱操作,取钱5000元,余额充足则进行取钱操作

并提示“取钱成功”,否则提示“余额不足”

declare @balance money

select @balance=

(select * from BankCard where BankMoney>=5000)

if @balance>=5000 -- 可以取钱

begin

update BankCard set CardMoney=CardMoney - 5000

where CardNo='6225547854125656'

insert into CardExchange(CardNo,MoneyInBank,MoneyOutBank,ExchangeTime)

values('6225547854125656',0,5000,GETDATE())

print '取钱成功'

end

else -- 不能取钱

begin

print '余额不足'

end

(2)查询银行卡信息,将银行卡状态1,2,3,4,分别转换为汉字“正常,挂失,冻结,注销”,并且根据银行卡余额显示银行卡等级;30万以下为“普通用户”,30万以上为“VIP用户”,显示分别为卡号,身份证,姓名余额,用户等级,银行卡状态

select CardNo卡号,AccountCode 身份证号,RealName 姓名,CardMoney 余额,

(case

when CardMoney>=300000 then 'VIP用户'

else '普通用户'

end) 用户等级,

(case CardState

when 1 then '正常'

when 2 then'挂失'

when 3 then '冻结'

when4 then '注销'

else '异常'

end) 银行卡状态

from BankCard

inner join AccountInfo on BankCard.AccountId=AccountInfo.AccountId

-- 注:

-- case 判断

-- when 修改前 then 修改后

-- when 修改前 then 修改后

-- else 其他

-- end

7.2循环结构(while)

(1)循环打印1-10

declare @i int =1

while @i<=10

begin

print @i

set @i=@i+1

end

(2)循环打印九九乘法表

-- 特殊字符:char(9):制表符

declare @i int =1

while @i<=9

begin

declare @str varchar(1000)=''

declare @j int =1

while @j<=@i

begin

set @str=@str+cast(@j as varchar(1))+'x'+cast(@i as varchar(1))+'='+cast(@j*@i as varchar(2)) +char(9)

set @j=@j+1

end

set @i=@i+1

print @str

end

7.3子查询

(1)关羽的银行卡号为“6225547858741263”

-- 查询出余额比关羽多的银行卡信息,显示卡号,身份证,姓名,余额。

select CardNo 卡号,AccountId 身份证,RealName 姓名,CardMoney 余额 from BankCard

inner join AccountInfo on BankCard.AccountId=Account.AccountId

where CardMoney>(select CardMoney from BankCard where CardNo='6225547858741263')

(2)从所有账户信息中查询出余额最高的交易明细(存钱取钱信息)。

select  * from CardExchange CardNo in

(select CardNo from BankCard where CardMoney=

(select MAX(CardMoney) from BankCard))

(3)查询有取款记录的银行卡及账户信息,显示卡号,身份证,姓名,余额

select CardNo 卡号,AccountCode 身份证,RealName 姓名,BankMoney 余额 from BankCard

inner join AccountInfo on BankCard.AccountId=Account.AccountId

where CardNo in (select CardNo from BankExchange where MoneyOutBank>0)

(4)查询出没有存款记录的银行卡及信息,显示卡号,身份证,姓名,余额

select CardNo 卡号,AccountCode 身份证,RealName 姓名,BankMoney 余额 from BankCard

inner join AccountInfo on BankCard.AccountId=Account.AccountId

where CardNo not in (select CardNo from BankExchange where MoneyInBank>0)

(5)关羽的银行卡号为“6225547858741263”,查询当天是否有收到转账

if EXISTS(select * from CardTransfer where CardNoIn='6225547858741263'

and convert(varchar(22),getdate(),23)=convert(varchar(22),transferTime,23))

begin

print '有收到转账'

end

else

begin

print '没有收到转账'

end

(6)查询出交易次数(存款取款操作)最多的银行卡账户信息,显示:卡号,身份证,姓名,余额,交易次数。

方案一:

select top 1 BankCard.CardNo 卡号,AccountId 身份证,RealName 姓名,CardMoney 余额,Temp.myCount 交易次数 from BankCard

inner join AccountInfo on BankCard.AccountId=Account.AccountId

inner join

(select CardNo,count(*) myCount from CardExchange group by CardNo) Temp

on BankCard.CardNo=Temp.CardNo

order by Temp.myCount desc

方案二:

select BankCard.CardNo 卡号,AccountId 身份证,RealName 姓名,CardMoney 余额,Temp.myCount 交易次数 from BankCard

inner join AccountInfo on BankCard.AccountId=Account.AccountId

inner join

(select CardNo,count(*) myCount from CardExchange group by CardNo) Temp

on BankCard.CardNo=Temp.CardNo

where Temp.myCount=

(

select max(Temp.myCount) from

(select CardNo,count(*) from CardExchange group by CardNo) Temp

)

(7)查询出没有转账交易记录的银行卡账户信息,显示卡号,身份证,姓名,余额

select CardNo 显示卡号,AccountCode 身份证,RealName姓名,BankMoney 余额

from AccountInfo

inner join BankCard on AccountInfo.AccountId=BankCard.AccountId

where CardNo not in(select CardNoOut from CardTransfer)

and CardNo not in(select CardNoIn from CardTransfer)

7.4分页

假设每页5条数据

-- 查询第一页

select top 5 * from Student

-- 第二页

select top 5 * from Student

where StuId not in(select top 5 StuId from Student)

-- 第三页

select top 5 * from Student

where StuId not in(select top 10 StuId from Student)

-- select top 页码大小 * from Student

-- where StuId not in(select top 页码大小*(当前页-1) StuId from Student)

-- 分页方案一:top方式分页

declare @PageSize int=5

declare @PageIndex int=1

select top (@PageSize) * from Student

where StuId not in(select top @PageSize*(@PageIndex-1) StuId from Student)

-- 方案二:使用row_number分页

-- ROW_NUMBER() 就是生成一个顺序的行号,而他生成顺序的标准,就是后面紧跟的OVER(ORDER BY 字段名)

select * from

(select ROW_NUMBER() over(order by StuId) RowId,* from Student) Temp

where RowId between (当前页-1)*页码大小+1 and 当前页*页码大小

declare @PageSize int=5

declare @PageIndx int=3

select * from

(select ROW_NUMBER() over(order by StuId) RowId,* from Student) Temp

where RowId between (@PageIndx-1)*@PageSize+1 and @PageIndx*@PageSize

7.5事物

简单理解为 相关联的表单操作时需要同步,不然会出现一个表单操作失败,另一个表单成功,导致数据不准确

刘备  420107198905064135   6225125478544587

关羽  420107199507104133   6225547858741263

张飞  420107199302034138   6225547854125656

(1)假设刘备取款6000,(添加check约束,设置账户余额必须>=0),要求:使用事物实现,修改余额和添加取款记录两步操作使用事物

begin transaction -- 使用事务

declare @myError int =0

update BankCard set CardMoney=CardMoney-6000 where CardNo='6225125478544587'

set @myError=@myError+@@ERROR

insert into CardExchange(CardNo,MoneyOutBank,MoneyInBank,ExchangeTime)

values('6225125478544587',0,1,getdate())

set @myError=@myError+@@ERROR

if @myError=0 – 逻辑判断

begin

commit transaction – 成功

print '取款成功'

end

else

begin

rollback transaction – 失败回滚

print '取款失败'

end

*(2)假设刘备向张飞转账1000元,(添加check约束,设置账户余额必须>=0);

-- 分析步骤有三部(1)张飞添加1000元,(2)刘备扣除1000元,(3)生成转账记录

begin transaction

declare @myError int =0

update BankCard set CardMoney=CardMoney-1000 where CardNo='6225125478544587'

set @myError=@Error+@@ERROR

update BankCard set CardMoney=CardMoney+1000 where CardNo='6225547854125656'

set @myError=@Error+@@ERROR

insert into CardTransfer (CardNoOut,CardNoIn,TransferMoney,TransferTime)values('6225125478544587','6225125478544587',1000,getdate())

set @myError=@Error+@@ERROR

if @myError=0

begin

commit transaction

print '转账成功'

end

else

begin

rollback transaction

print '转账失败'

end

注:

commit transaction -- 标志一个成功的隐性事务或显式事务的结束。

rollback transaction -- 将显式事务或隐性事务回滚到事务的起点或事务内的某个保存点。

 *8.索引

8.1索引:

提高检索查询效率

聚集索引:物理存储顺序

非聚集索引:逻辑存储顺序

8.2 创建索引的方式(需要另学)

1.通过显式的Create index命令

2.在创建约束时作为隐含的对象

  • 主键约束
  • 唯一约束

创建索引语法:

create [unique] [clustered | noclustered]

index<index name> on <table or view name>(<column name>[ASC | DESC][,…n])

-- 例:给AccountInfo表中的AccoundCode字段添加索引

create unique noclustered index index_code

on AccountInfo(AccountCode)

-- 索引查看(sys.indexes)

select * from sys.indexes where name='index_code'

-- 删除索引

drop index index_code on AccountInfo

-- 按显示指定索引查询

select * from AccountInfo with(index=index_code)

where AccountCode='420107199507104133'

*9.视图

视图:可以理解为虚拟表,封装SQL语句

-- (1)显示卡号,身份证,姓名,余额

-- 创建视图,实现显示卡号,身份证,姓名,余额

create view View_Account_Card

as

select CardNo 卡号,AccountCode 身份证,RealName 姓名,CardMoney 余额 from BankCard

inner join AccountInfo on BankCard.AccountId=AccountInfo.AccountId

go

如果要进行相应信息查询,不需要编写复杂的SQL语句,直接使用视图,如下:

select * from View_Account_Card

*10.游标

游标:定位到结果集中某一行

游标分类:

(1)静态游标:数据发生变化,游标中数据不变

(2)动态游标:数据发生变化,游标中数据改变,默认值

(3)键集驱动游标:被标识的列发生改变,游标中数据改变,其他列改变,游标中数据不变

-- 创建游标(scroll:滚动游标,没有scroll,只进)

declare mycur cursor scroll

for select MemberAccount from Member

-- 游标打开

open mycur

-- 提取某行数据

fetch first from mycur -- 第一行

fetch last from mycur -- 最后一行

fetch absolute 2 from mycur -- 提取第二行

fetch relative 2 from mycur -- 当前行下移2行

fetch next from mycur -- 下移一行

fetch prior from mycur -- 下移一行

-- 提取游标数据存入变量,进行查询所有列信息

declare @acc varchar(20)

fetch absolute 2 from mycur into @acc

select * from Member where MemberAccount=@acc

-- 遍历游标

fetch absolute 1 from mycur

-- @@fetch_status:0  -- 0-提取成功,1-失败,2-不存在

while @@fetch_status=0

begin

print '提取成功:'+@acc

fetch next from mycur into @acc

end

-- 关闭游标

close mycur

-- 删除游标

deallocate mycur

-- 利用游标进行数据的修改和删除

select * from Member

fetch absolute 2 from mycur

update Member set MemberPwd='654321' where current of mycur

fetch absolute 2 from mycur

delete from Member where current of mycur

select * from Member

-- 创建指向某行多列的游标,循环显示多列数据

declare mycur cursor scroll

for select MemberAccount,MemberPwd,MemberNickName from Member

open mycur

declare @acc varchar(20)

declare @pwd varchar(20)

declare @nickname varchar(20)

fetch absolute 1 from mycur into @acc,@pwd,@nickname

-- @@fetch_status:0  -- 0-提取成功,1-失败,2-不存在

while @@fetch_status=0

begin

print '用户名'+@acc+'密码:'+@pwd+'昵称'+@nickname

fetch next from mycur into @acc,@pwd,@nickname

end

11.函数

函数分为(1)系统函数,(2)自定义函数

自定义函数分为:(1)标量值函数(返回单个值),(2)表值函数()返回查询结果

(1)编写一个函数求该银行的金额总值

create function GetSumMoney() returns money

as

begin

declare @sum money

select @sum =(select sum(CardMoney) from BankCard)

return @sum

end

-- 函数调用

select dbo.GetSumMoney()

(2)传入账号编号,返回账户真实姓名

create function GetRealNameById(@accid int) returns varchar(30)

as

begin

declare @name varchar(30)

select RealName from AccountInfo where AccountId=@accid

return @name

end

select dbo.GetRealNameById(2)

-- (3)传递开始时间和结束时间,返回交易记录(存钱取钱),

-- 交易记录中包含 真实姓名,卡号,存钱金额,取钱金额,交易时间。

-- 方案一:

create function GetRecordByTime(@start varchar(30),@end varchar(30))

returns @result table

(

RealName varchar(20),-- 真实姓名

CardNo varchar(30),-- 银行卡号(与银行卡表形成主外键关系)

MoneyInBank money,-- 存钱金额

MoneyInBank money,-- 存钱金额

ExchangeTime smalldatetime -- 交易时间

)

as

begin

insert into @result

select RealName 真实姓名,CardExchange.CardNo 卡号,MoneyInBank 存钱金额,MoneyOutBank 取钱金额,ExchangeTime 交易时间

from CardExchange

inner join BankCard on CardExchange.CardNo=BankCard.CardNo

inner join AccountInfo on BankCard.AccountId=AccountInfo.AccountId

where ExchangeTime between @start + '00:00:00' and @end +'23:59:59'

return

end

select GetRecordByTime('2020-1-1','2020-12-12')

方案二(函数体内只能有return+sql查询结果):

create function GetRecordByTime(@start varchar(30),@end varchar(30))

returns table

as

return

select RealName 真实姓名,CardExchange.CardNo 卡号,MoneyInBank 存钱金额,MoneyOutBank 取钱金额,ExchangeTime 交易时间

from CardExchange

inner join BankCard on CardExchange.CardNo=BankCard.CardNo

inner join AccountInfo on BankCard.AccountId=AccountInfo.AccountId

where ExchangeTime between @start + '00:00:00' and @end +'23:59:59'

go

select GetRecordByTime('2020-1-1','2020-12-12')

*(4)查询银行卡信息,将银行卡状态1,2,3,4分别转换为汉字“正常,挂失,冻结,注销”,

-- 根据银行卡余额显示银行卡等级30万以下为“普通用户”,30万及以上为“VIP用户”,

-- 分别显示卡号,身份证,姓名,余额,用户等级,银行卡状态。

-- 用户等级函数

create function GetGrade(@cardmoney money) returns varchar(30)

as

begin

declare @result varchar(30)

if @cardmoney>=300000

set @result ='VIP用户'

else

set @result='普通用户'

return @result

end

-- 求银行卡状态函数

create function GetState(@state int)returns varchar(30)

as

begin

declare @result varchar(30)

if @state =1

set @result='正常'

else if @state=2

set @result='挂失'

else if @state=3

set @result='冻结'

else if @state=4

set @result='注销'

else

set @result='异常'

return @result

end

-- 调用查询

select CardNo卡号,AccountCode 身份证号,RealName 姓名,CardMoney 余额,

GetGrade(CardMoney)用户等级,GetState(CardState)银行卡状态

from BankCard

inner join AccountInfo on BankCard.AccountId=AccountInfo.AccountId

(5)编写函数,根据出生日期求年龄(年龄求实岁),例如:

-- 生日为2000-5-5,当前为2018-5-4,年龄为17岁

-- 生日为2000-5-5,当前为2018-5-6,年龄为18岁

create function GetAge(@birth smalldatetime) returns int

as

begin

declare @age int

set @age=year(getdate())-year(@birth)

if month(getdate())<month(@birth)

set @age=@age-1

if month(getdate())<month(@birth) and day(getdate())<day(@birth)

set @age=@age -1

end

select *,dbo.getdate(empBirth)年龄 from Emp

12.触发器

触发器分类:

(1)“Instead of”触发器-在执行操作前被执行(事前触发器)

(2)“After”触发器-在执行操作后被执行(事后触发器)

触发器中后面的案例中所需要用到的表及测试数据如下:

(1)假设有部门表和员工表,在添加员工的时候,该员工的部门编号如果在部门表中找不到,则自动添加部门信息,部门名称为“新部门”

--触发器语法:create trigger 触发器名称 on 表名  after/instead of  行为 as。。。

create trigger tri_InsertPeople on People after insert  -- 事后触发器

as

if not exists(select * from Department where DepartmentId=(select DepartmrntId from inserted))

begin

insert into Department(DepartmentId,DepartmentName)

values((select DepartmentId from insterted),'新部门')

end

go

-- 测试触发器

insert into People(DepartmentId,PeopleName,PeopleSex,PeoplePhone)

values('002','赵云','男','13698547125')

insert into People(DepartmentId,PeopleName,PeopleSex,PeoplePhone)

values('006','马超','男','13698547136')

(2)触发器实现,删除一个部门的时候将部门下的员工全部删除(deleted-数据库中的储存表)

create trigger tri_DeleteDept on Department after delete

as

delete from People where DepartmentId=(select DepartmentId from deleted)

go

select * from Department

select * from People

-- 测试触发器

delete from Department where DepartmentId='006'

(3)创建一个触发器,删除一个部门的时候判断该部门下是否有员工,有则不删除,没有则删除

drop trigger tri_DeleteDept -- 创建触发器前先删除之前同名触发器

create trigger tri_DeleteDept on Department instead of delete

as

if not exists(select * from People where DepartmentId=(select DepartmentId from deleted))

delete from Department where DepartmentId =(select DepartmentId from deleted)

go

-- 测试触发器

select * from Department

select * from People

delete from Department where DepartmentId = '005'

(4)修改一个部门编号之后,将该部门下所有员工的部门编号同步进行修改(deleted、inserted数据库里的储存表)

create trigger tri_UpdateDept on Department after update

as

update People set DepartmentId=(select DepartmentId from inserted)

where DepartmentId=(select DepartmentId from deleted) -- 修改People表中的部门编号

go

update Department set DepartmentId ='005' where DepartmentId='001'

*13.存储过程

存储过程(Procedure)是SQL语句和流程控制语句的预编译集合

(1)没有输入参数,没有输出参数的存储过程

定义存储过程实现查询出账户余额最低的银行卡账户信息,显示银行卡号,姓名,账户余额

-- 方案一(不能兼顾多个并列最低):

drop proc proc_MinMoneyCard -- 删除同名存储

create proc proc_MinMoneyCard

as

select top 1 CardNo卡号,RealName 姓名,CardMoney 余额,

from BankCard

inner join AccountInfo on BankCard.AccountId=AccountInfo.AccountId

order by CardMoney

go

exec proc_MinMoneyCard

-- 方案二(余额最低,多个人并列,都可以查询):

create proc proc_MinMoneyCard

as

select top 1 CardNo卡号,RealName 姓名,CardMoney 余额,

from BankCard

inner join AccountInfo on BankCard.AccountId=AccountInfo.AccountId

where CardMoney =

(select min(CardMoney)from BankCard)

go

exec proc proc_MinMoneyCard

(2)有输入参数,没有输出参数的存储过程

-- 模拟银行卡存钱操作,传入银行卡号,存钱金额,实现存钱操作

create proc proc_Cunqian

@CardNo varchar(30),

@money money

as

update BankCard set CardMoney=CardMoney+@money where CardNo=@CardNo

insert into CardExchange(CardNo,MoneyInBank,MoneyOutBank,ExchangeTime)

values(@CardNo,@money,0,GETDATE())

go

select * from BankCard

select * from CardExchange

exec proc_Cunqian '6225547858741263',1000

(3)有输入参数,没有输出参数,但是有返回值的存储过程(返回值必须整数)

-- 模拟银行卡取钱操作,出入银行卡号,取钱金额,实现取钱操作

-- 取钱成功,返回1,取钱失败返回-1

create proc proc_Quqian

@CardNo varchar(30),

@money money

as

update BankCard set CardMoney=CardMoney-@money where CardNo=@CardNo

if  @@ERROR<>0

return -1

insert into CardExchange(CardNo,MoneyInBank,MoneyOutBank,ExchangeTime)

values(@CardNo,0,@money,GETDATE())

return 1

go

declare @returnValue int

exec @returnValue =proc_Quqian '6225547858741263',2000

select @returnValue

(4)有输入参数,有输出参数的存储过程

-- 查询出某时间段的银行存款信息以及存款总金额,取款总金额

-- 传入开始时间,结束时间,显示存取款交易信息的同时,返回存款总金额,取款总金额。

create proc proc_selectExChange

@start varchar(20),-- 开始时间

@end varchar(20),-- 结束时间

@ sumIn money output, -- 存款的总金额

@sumOut money output, --取款的总金额

as

select @sumIn=(select sum(MoneyInBank) from CardExchange

where ExchangeTime between @start +'00:00:00' and @end +'23:59:59')

select @sumOut=(select sum(MoneyOutBank) from CardExchange

where ExchangeTime between @start +'00:00:00' and @end +'23:59:59')

select * from CardExchange

where ExchangeTime between @start +'00:00:00' and @end +'23:59:59'

go

declare @sumIn money

declare @sumOut money

exec proc_selectExChange '2020-1-1','2020-12-11',@sumIn output,@sumOut output

select @sumIn

select @sumOut

(5)具有同时输入输出参数的存储过程

-- 密码升级,传入卡号密码,如果卡号密码正确,并且密码长度<8,自动升级成8位密码

-- floor(rand()*10)生成1-9随机数

create proc procPwdUpgrade

@CardNo nvarchar(20),-- 卡号

@pwd nvarchar(20) output,-- 密码,output不局限于单纯输出,可先定义值,之后再返回最终的输出值

as

if not exists(select * from BankCard where CardNo=@CardNo and CardPwd=@pwd)

set @pwd=''

else

begin

if len(@pwd)<8

begin

declare @len int=8-len(@pwd)

declare @i int =1

while @i<=@len

begin

set @pwd=@pwd+cast(floor(rand()*10)as varchar(1))

set @i=@i+1

end

update BankCard set CardPwd=@pwd where CardNo=@CardNo

end

end

go

declare @pwd nvarchar(20)='123456'

exec procPwdUpgrade '6225125478544587',@pwd output

select @pwd

实操遇到的问题(更新中):

passward nvarchar(10) collate chinese_prc_ci_as null。
collate chinese_prc_ci_as到底是什么意思呢?

collate关键字是指定SQL server的排序规则。
Chinese_PRC表示简体中文,繁体中文则为Chinese_Taiwan
CI:case-insensitive 指定不区分大小写(A 和a 被看作是一样的),如果要在查询时区分输入的大小写则改为CS
AS:Accent sensitive 指定区分重音,同样如果不需要区分重音,则改为AI

ISNULL()

实例:如果表达式为NULL,则返回指定值,否则返回表达式:

SELECT ISNULL(NULL, 'W3Schools.cn');

ISNULL(expressionvalue)  --

参数

描述

expression

必需。判断是否为NULL的表达式

value

必需。表达式为NULL时返回的值

总结:重要的 SQL 命令

  • SELECT - 从数据库中提取数据
  • UPDATE - 更新数据库中的数据
  • DELETE - 从数据库中删除数据
  • INSERT INTO - 向数据库中插入新数据
  • CREATE DATABASE - 创建新数据库
  • ALTER DATABASE - 修改数据库
  • CREATE TABLE - 创建新表
  • ALTER TABLE - 变更(改变)数据库表
  • DROP TABLE - 删除表
  • CREATE INDEX - 创建索引(搜索键)
  • DROP INDEX - 删除索引

【数据库-汇总】SQL SERVER数据库相关推荐

  1. 转贴 :sql数据库置疑:Sql Server数据库置疑的解决

    sql数据库置疑:Sql Server数据库置疑的解决 办法 原因: 通常这个问题是由于硬盘空间不够或硬盘读写错误造成的. 现象: 数据库后面有"置疑"字样,查看系统事务日记出现以 ...

  2. linux 附加数据库文件,SQL Server 数据库分离与附加图文详解

    SQL Server 数据库分离与附加图文教程,需要的朋友可以参考一下. 一.概述 SQL Server提供了"分离/附加"数据库."备份/还原"数据库.复制数 ...

  3. SQL Server 数据库之SQL Server 数据库的安全设置

    SQL Server 数据库的安全设置 1. 概述 2. 更改登录用户验证方式 3. 创建与删除登录用户 4. 创建与删除数据库用户 5. 设置服务器角色权限 5.1. **查看角色属性** 5.2 ...

  4. 【数据库】SQL Server 数据库、附加数据库时出错。有关详细信息,请单击“消息”列中的超链接

    总结一下附加数据库时出错的几点常见原因 [若有错误,欢迎指正] 原因 一.登陆方式 甲.在登录验证时,选择"Windows 身份验证",而不是"SQL Server 身份 ...

  5. [转载]在SQL Server数据库之间进行数据导入导出,OPENDATASOURCE

    需要在c盘下先建立一个data.txt文件,然后在文件的第一行写上你要导出的列,不如说要导出id和name这两列,就在第一行写上 id,name 然后保存,使用下列SQL就可以了,你如果要保持原有的I ...

  6. 在SQL Server数据库之间进行数据导入导出

    来源:http://kb.cnblogs.com/page/94464/ 在SQL Server数据库之间进行数据导入导出 (1).使用SELECT INTO导出数据 在SQL Server中使用最广 ...

  7. 如何使用Visual Studio创建SQL Server数据库项目

    目录 背景 介绍 创建新的SQL Server数据库项目 发布以在SQL Server中创建新数据库 结论 背景 数据库在任何应用程序中都扮演着最重要的角色,当表.视图.存储过程的数量增加时,项目管理 ...

  8. SQL Server数据库学习总结及T-SQL语法使用实战

    SQL Server数据库及T-SQL实战 声明 名词解释 SQL Server数据库 安装sql server 数据库中的三种完整性 SQL Server数据库基本操作 创建数据库 指定多个数据库文 ...

  9. VS2017操做sql server数据库

    VS2017操做sql server数据库 安装sql server数据库 摸鱼怪在这里就不总结了,相信大家都会,实在不行就去问问度娘吧! 摸鱼怪在这里提醒大家,如果版本太新可能会出现不兼容问题,最开 ...

  10. sql的介绍——SQL Server数据库管理系统

    SQL Server是微软公司推出的关系数据库管理系统,使用客户机/服务器体系结构. ,具有以下特点: 使用方便(可以图形界面操作) 可伸缩性好(做大数据库可以,也可以做小数据库) 与相关软件集成程度 ...

最新文章

  1. Forefront基本知识介绍
  2. 橡皮筋模型不太对呀?!
  3. mysql数据中文乱码_win10 系统解决mysql中文乱码问题
  4. 爬虫必须得会的Web知识
  5. IOS开发之Bug--遇到一个类型不确定的bug
  6. Stack Overflow 2021开发者调查报告 - 数据库篇!
  7. JVM第一讲:为什么需要 JVM?它处在什么位置?
  8. ASP.NET Core默认注入方式下如何注入多个实现(多种方式)
  9. Mybatis的动态sql(五)
  10. python中__new__的用法_python中的__init__ 、__new__、__call__小结及使用
  11. 车间调度建模系列8|扩展析取图之基于时间片段的赋时三维析取图模型
  12. python图像识别与提取_python图像识别与提取
  13. 1024程序员节节日快乐
  14. Unity笔记之切换鼠标图标样式、PSD格式文件导入Unity
  15. 如此优秀的JS轮播图,写完老师都沉默了
  16. python求和1到100_python实现1加到100
  17. EasyPlayer流媒体播放器播放HLS视频,起播速度慢的技术优化
  18. GoPro内存卡里的THM、LRV文件
  19. 领域模型的概念:失血 贫血 充血 胀血
  20. 关于如何免费下载专利、英文文献等?

热门文章

  1. 向iPhone或者ipad导入文件夹或者文件
  2. Net.createConnection is not a function
  3. 电脑卡顿反应慢怎么处理?提升反应速度的方法
  4. EasyExcel导出包含多个sheet的Excel
  5. 几何非线性-屈曲分析
  6. 好看的html登录界面,
  7. AndroidQ 图形系统(9)SurfaceView实现原理之设置透明区域
  8. Qt学习——利用QToolBox实现QQ好友列表
  9. SOA 建模之服务实施
  10. jQuery 效果 - 滑动 slideDown()与slideUp()与slideToggle()