数据库
第二章
1 执行顺序
from-->on-->where-->group by-->having-->select(over,distinct,top)-->order by
2 from
在逻辑处理阶段第一个要处理的查询子句
  where
过滤from阶段返回的行,只有能让逻辑表达式,从而过滤由from阶段返回给后续查询处理阶段,
3 group by
逻辑查询处理阶段返回的行按组进行组合,在group by阶段包括(having,select,order by)的操作对象将是组,而不是单独的行,每个组最终也表示为查询结果集中的一行,这意味着在group by阶段处理的子句中的所有表达式务必保证为每个组只返回一个标量(单值)
一个元素如果不在group by列表中出现,就只能作为聚合函数(count,sum,avg,min,max)
4 having
过滤group by 分组以后,返回逻辑表达式为True的组
5 select
尽量不要使用星号
6
order by

排序
当指定了distinct以后,order by子句就被限制为只能在select列表中出现的那些元素,这一限制背后的原因是,当指定distinct时候,一个结果行可能代表多个原始行,所以无法清楚的知道应该使用 order by 列表值中多个可能值中的哪一个
7
top
是 T-Sql特有的,用来限制返回的行数和百分比,当查询指定了order by 子句时候,top将依赖该子句定义行的逻辑优先顺序
top(1) percent-百分之一
top(5) with ties 表示要增加与orderby子句中条件相同的其他所有行
8
over

over没有条件说明包含所有的记录

select custid,val,sum(val) over() as orderTotalVal,100.*val/sum(val)over()
from sales.ordervalues

 

select custid ,val ,sum(val) over(partition by custid) as myordertotalval,100.*val/sum(val) over(partition by custid)
from sales,ordervalues

partition by 分区


为行定义了一个窗口,称为开窗函数,
聚合函数和排名函数都支持over子句的运算类型
partition by 分区
排名函数中必须得有orderby子句
列入
row_number(order by val)as rownum
rank 表示之前有多少行具有更低的排序值,表示(1,1,1,1,4 表示五个学生前四个成绩一样)
dense_rank 表示之前有多少个更低的排序值(1,1,1,1,2 表示排名连续
ntile装桶

ntile(2),分了两个组


9
case
简单表达式:将一个值与一个组可能的取值进行比较,并返回第一个匹配的结果,如果列表没有值等于测试值,则case表达式就返回else子句中列出的值
case categoryid
when 1(就是说当categorid=1时候) then '...'
else'...'
end as ...
fromy
搜索表达式
case
when val<1000(直接写字段与要求的数做比较) then
'less then 1000'
else'...'
end as ...
from ...

10
null

三值逻辑
true false unknow
where 字段<>...
or 字段 is null
聚合函数会忽略空
尤其是count数数时候

 

 

11
字符串提取

可以将 concat_null_yields_null 的会话选项设置为off
就可以改变SQl server 处理串联的方式
substring(string,(自己指定的字符串位置)start,(指定所去字符串的长度)length)
取字符串
select substring('abcde',2,3)
返回'bcd'
left 和(string,n)
指的是字符串左数起n个字符
left('abcde',3)
返回cde
len和datalength
select len('abcde')
返回5(字符)
select datalength('abcde')
返回10(字节)
charindex(substring,string,[start_pas])
select charindex(' ',' avx csdf',2)
返回5(表示第二个格的位置是在字符串第五个)
patindex(pattern,string)
patindex('%[0-9]%','affsaf123df')
返回7(表示在字符串中第一次出现数字的位置)
replace(string,substring1,substring2)
replace('a-a b-3','-',':')
返回的结果是(a:a b:3)
replicate('abc',3)
将字符串'abc'复制3次
返回'abcabcabc'
select supplierid,
right(replicate('0'9)+cast(supplierid as varvhar(10)) ,10) as strsupplierid
from production.suppliers;
stuff
删除插入
stuff(string,pas,delete_length,indertstring)
select stuff('xyz',2,1,'abc')
返回'xabcz'
指的是把y删除用'abc'替换
upper 大写 和 lower 小写

11
like 谓词
%表示任意多个任意字符
_表示任意一个任意字符
where lastname like'_d%'
表示第二个字符为d的所有雇员姓名

12
日期函数
dateadd
为输入的时间值增加指定的数量
select dateadd(year,4,'20060404')
返回
2010-04-04 00:00:00
datediff
返回两个日期和时间值之间相差的指定部分的计数
select
dateadd(month,datediff(month,2010-1-31,orderdate),2010-1-31)
表示查询每月最后一个天的订单情况

datepart
select datepart(month,'20090201')
返回2(代表月份,但是返回的是数字)

datename
select datename(month,'20090201')
返回(取决于当前会话的语言,如果是英语,则返回
February)

isdate
select isdate('20090201')
表示如果能把括号中的字符串转换成日期,则返回1
如果不能则返回0

getdate
是获取系统当前时间
在T-sql中才能用

标准是
current_timestamp

12
数据字典
元数据
描述数据的数据
通常以表的方式提供
查询特殊的表,数据字典来完成
oracle 提供一些系统的表或者视图
有的提供一些特殊命令查询

查询架构
select schema_name(schema_id)as sc
hemaname,name
from sys.tables

查询表的结构
select *
from sys.columns
查询指定表的列
where object_id=Object_id(N'sales.order','U')
--用标准方法查询

查询表
select TABLE_SCHEMA ,TABLE_NAME
from INFORMATION_SCHEMA .TABLES
where TABLE_TYPE =N'base table'


第三章
连接查询
1
交叉连接


2内链接
第一步,交叉连接,第二步过滤
inner join

3外连接
第一步,交叉连接,第二步过滤,第三部增加外部行
left join,right join,full join

4
不等连接
一般在自连接中使用
表示去掉了不与本身做连接的行
select e1.empid ,e1.firstname,e2.empid,e2.firstname
from HR.Employees e1 inner join HR.Employees e2
on e1.empid <>e2.empid
但是还存在左行和右行交换重复
比如 1,2和2,1
所以应该改为
select e1.empid ,e1.firstname,e2.empid,e2.firstname
from HR.Employees e1 inner join HR.Employees e2
on e1.empid < e2.empid

5
null
--2007年1月一号以后的
--如果增加的外部行为 null 不能做运算 要在写个or条件
select companyname ,orderid ,orderdate
from Sales.Customers c left join Sales.Orders o
on c.custid =o.custid
where orderdate >'20070101' or orderdate is null

6--
2007年1月一号以后的订单总记(子查询)

select
DATEADD(DAY,n.number-1,CAST('20070701'as datetime)) as orderdate,
isnull((o.total),0) as total
from
(select top(31) orderdate ,day(orderdate) as k,
SUM (od.qty *od.unitprice) as total
from Sales.Orders o
inner join
Sales.OrderDetails od
on o.orderid =od.orderid
where year(orderdate) =2007 and MONTH (orderdate )=7
group by orderdate
order by orderdate
) o  right join (select top(31) p.productid number
from Production.Products p
order by number
) n on o.k =n.number


第四章

-独立子查询
1 必须放在圆括号里
单值子查询可以写在任何地方,只需当个值来运算,
select,where,from,having,
多值只需改个运算符来个
多值子查询中 in ontin
distinct可以省略
-相关子查询
查询每个顾客订单号最大的那个订单

第五章

表表达式

1
派生表
写在from中子句中的命名子查询
查询每个顾客的参与的活动的最后一天下过的所有订单
--1不保证顺序
--2列有别名
--3列名唯一
select o.custid,o.orderid,o.orderdate,o.empid
from sales.orders o inner join
(select custid, Max(orderdate) as maxorder
from sales.orders
group by custid
) oc
on o.custid =  oc.custid
and
o.orderdate=oc.orderdate

2 cte 公共表表达式 都是一次性的
查询订单最后一天的订单

with custlasday
as
(
select custid, Max(orderdate) as maxorder
from sales.orders
group by custid
)
select o.custid,o.orderid,o.orderdate,o.empid
from sales.orderd o inner join
custlasday c
on o.custid =c.custid
and orderdate = oc.ordredate

查询客户订单最多的客户

with custorderNum
as
(
  select custid ,COUNT (*) as ordernum
  from Sales.orders
  group by custid
 
),
custMaxorderNum
as
(
select top(1) custid
from custorderNum
order by ordernum desc
)
select o.custid ,orderid ,orderdate,empid
from Sales.Orders o
inner join custMaxorderNum
on o.custid =custMaxorderNum .custid

递归cte

查询管理员工
--cte递归
with eMpscte as
(
     select firstname ,empid ,mgrid
     from HR.Employees
     where mgrid =2
     union all
     select e.firstname ,e.empid,e.mgrid
     from eMpscte  inner join  HR.Employees e
  on e.mgrid =eMpscte .empid   
)
select *
from eMpscte

 

3 视图 允许保存的 还有就是对查询进行抽象

保存的只是查询语句,而不是数据

在视图上做增删改
很有问题
当删除视图中的行时
当这个视图只涉及到很简单的查询的时候(没有集合函数,没有连接,很简单的那种)会删除到基
表中的数据
插入也是如此
会影响基表中的数据
但是又不满足视图的
查询条件
为了防止冲突视图的查询语句末尾加上
with check option

--表函数
不能单独使用,只能用在表达式中

 

4表函数--单值函数,聚合函数

 

第六章
集合运算
union
则隐含的加了distinct关键字去掉两个表中重复的字段
结果是一个真正的集合
 
union all
表示将两个表的查询结果相加,所有结果并不是一个真正的集合,而是一个多集

intersect
交集
表示既属于A集合也属于B集合的集合
但是里面默认有distinct去重

要想都留着但是交集没有all关键字所以用以下方法


with intersect_all
as
(
select
Row_number()
 over(partition by country,region,city
order by (select 0)) as rownum,country,regiom
city
from hr.employees

intrrsect

Row_number()
 over(partition by country,region,city
order by (select 0)) as rownum,country,regiom
city
from sales.customers;)
select country,region,city
from intersect_all

用来代替生成intersect all
表示返回没有生成标题列的行


第七章
1
透视
要解决透视
先要标识转换涉及的元素:分组元素,拓展元素,聚合元素和聚合函数

例子(为每个雇员返回一行数据,为为每个订单年份返回一列数据,计算每个雇员在每个订单年份处理过的订单数)

select orderid ,empid,
from


select empid,[2007] as net2007,[2008] as net2008,[2009] as net2009
from (select empid ,YEAR(orderdate)as orderdate
from c) as s
pivot (count(orderdate) for orderdate in([2007],[2008],[2009]))as o

第一步;empid是分组元素,year(orderdate)是拓展元素,个数count是聚合函数,聚合元素不好找,因为count
不会忽略null值,除非找到不是null的列,在这个例子中找到了year(orderdate)没有null的值
因为求个数,所有尽量使用拓展元素使用的列
其他列也可以,只有不为null就可以


select 分组元素 ,要求显示的字段
透视中没有使用的字段就默认分组了

from(select 分组元素,拓展元素 ,聚合元素
from 源表)as ..
pivot (聚合函数(聚合元素)for 拓展元素 in(拓展元素字段))as..


--另个方法
select 分组元素,拓展元素,聚合函数(聚合元素),
聚合元素(case when 拓展元素 = 。。then '聚合元素 ' end )as '',
聚合元素(case when 拓展元素 = 。。then '聚合元素 ' end )as '',
聚合元素(case when 拓展元素 = 。。then '聚合元素 ' end )as ''
......
from 源表
group by 分组元素,拓展元素
2
逆透视

用unpivot
select 提取的元素字段
from 源表
unpivot (聚合元素for 拓展元素in(源表的列表名))as

3
分组集
group by
   grouping sets
(
(a,b),
(a),
(b),
()
)

--cube
group by
   cube(a,b)
--rollup 卷集 增加合计
--函数 grouping,group_id

八章
修改
update 表名
set

--一定要指定哪一行作为条件
where

delect from
删除行
九章

特征
原则性
一致性
隔离性
持久性
--隐式事务 ,数据库中每条语句中就是一个事务单位
delect from HR.Employees where empid = 12;
--显示事务 ,只有指定了显示事务才能保证事务一致性
一般都是显示事务
begin transaction
 
delete from HR.Employees where =13;
delete from HR.Employees where =14;

结束事务的方式1-- roll back;回滚
当执行到回滚时候删除的数据又回来了
结束事务的方式2--commit 提交

就是说在显示事务中要么两条都在,要不都不在

隐式事务由系统管理,一条语句就是提交一次

并发
判断并发

乐观并发

有个时间戳的字段timestamp 但是并不是取时间的字段
而是系统生成的一个二进制数字,每次变化都会变化

悲观并发

效率会降低但是可靠性会提高

--加锁

1 共享锁

加个共享锁可以读,但是不可以改了

2 独占锁

 

3查看系统锁
select
from
 sys.dm_tran_locks;

隔离级别

1.读未提交,允许读取还没有提交的数据,读取不需要共享锁
 要显示设置
set transaction isolation level read uncommitted
设置后就可以读取未提交的数据
不需要共享锁
所有不能保证数据的一致性
不一定是正确的
‘脏读’
 
2.读提交,读取提交之后的数据,默认的隔离级别
但是必须获取共享锁
要吗是提交前的,要么是提交后的
数据是正确的

3
可重复读
repeatable read
必须显示设置

set transaction isolation level repeatable read;

begin transaction
会给查询数据加了共享锁
(你的操作不会影响别人就是共享锁影响了别人的操作就是独占锁)
但是前提都是在开始事务这个范围内

4序列读 ,幻影读
在事务中影响更深
显示设置
就是虽然可以防止这个行不受影响,但是不能给插入新的记录加锁,所有就要使用序列读
set transaction isolation leve serializable

 -----快照级别
提交之前读取的是原始数据
提交之后读取的是提交后的数据
这样两个会话不会阻塞
以上的级别都会产生阻塞

要提前启用数据库的快照级别
alter database TSQLFundamentals2008
set allow_snapshot_isolation on;

显示设置快照级别 set transaction isolation level snapshot

一般快照都会保存到临时数据库 tempdb中

------快照带提交级别

要提前修改数据库提交级别


alter database TSQLFundamentals2008
set read_committed_snapshot on;

显示设置读提交
set transaction isolation leval read commited

--死锁

--基本原则解决死锁
更新多个记录,按照相同的顺序进行更新


10
索引
创建索引
create index +名称 on + 表(字段)

范式
一级范式
只要能把表存到数据库中肯定就满足一级范式
二级范式
解决部分依赖
三级范式
解决传递依赖


 

posted on 2013-06-09 14:16  baocheng  阅读(242)  评论(0编辑  收藏  举报