转自:

一、前言  

索引:
在未创建索引之前,数据库里的数据是按照堆来存储的,当我们使用index关键字创建索引时,其在内存中将会变为B树来存储。默认创建的索引类型是非聚焦索引,当使用关键字clustered创建聚焦索引。一个表只能有一个聚焦索引,可以有多个非聚焦索引。
聚集索引决定了表数据的物理存储顺序,也就是说表的物理存储是根据聚集索引结构进行顺序存储的,因此一个表只能有一个聚集索引。
除了聚集索引以外的其他索引,都称之为非聚集索引,非聚集索引一般都是为了优化特定的查询效率而创建的。

摘要:
今天接到一个需求,有一张数据表,记录的是消费明细数据,
现在需要做一个累计结余,记录每次的数据结余合计,
下文将展示一种sql脚本的编写方式
实验环境:sqlserver 2008 R2
如下例所示:

  现在做项目数据访问基本都会选择一种orm框架,它以面向对象的形式屏蔽底层的数据访问形式,让开发人员更集中在业务处理上,而不是和数据库的交互上,帮助我们提高开发效率;例如一些简单的insert、update,我们不需要写insert
into…sql
语句,而是直接new一个实体对象,然后db.Insert(entity),看起来是那么清爽;像EF这样比较完善的orm,支持linq语法对数据库进行访问,写起来就更加爽了,有些人甚至认为开发人员可以不用会写sql语句了…但现实不会让你工作得那么轻松,作为开发人员对数据库这一块的学习还是很有必要的;且不说一些灵活性和效率问题,实际工作中用sql的地方还是非常多的,经常在码代码的时候,突然就传来领导的声音,那个某某某,你赶紧给我出一份报表,那个谁谁谁,你赶紧给我出一份XXX的数据…很急。

索引和主键的区别:1:主键是为了标识数据库记录唯一性,不允许记录重复,且键值不能为空,主键也是一个特殊索引.2:数据表中只允许有一个主键,但是可以有多个索引.3.使用主键,数据库会自动创建主键索引(默认下是聚焦索引),也可以在非主键上创建索引,方便查询效率.
可以在主键上设置为非聚集索引,在其余的列上设置为聚集索引。
唯一索引是指在该列中不能存储重复的值。

detail表 记帐流水表
==========
字段:
qt_srMoney   (money) 收入
qt_zcMoney  (money) 支出
qt_date         (datetime) 操作日期
qt_dkfs         (nvarchar)  打款方式
------------------
需获取一个带结余的数据信息
==========
根据期初表中的日期和金额,查询出记帐表中的结余。
帐面结余 =期初金额+收入-支出
实验环境:sql server 2008 R2
*/ 
create table detail(qt_srMoney   money,
qt_zcMoney  money,
qt_date         datetime,
qt_dkfs         nvarchar(100))
insert into detail values(100,0,'2018-1-2 10:00:00','other')
insert into detail values(0,10,'2018-2-2 10:00:00','other')
insert into detail values(0,20,'2018-3-2 10:00:00','other')
insert into detail values(30,0,'2018-4-2 10:00:00','other')
insert into detail values(10,60,'2018-5-2 10:00:00','other')
go

declare @datestart datetime ---开始计算日期
set @datestart ='2018-2-1'
declare @qcomney money --期初
set @qcomney =100 

select t1.qt_date,t1.qt_dkfs,t1.qt_srMoney,t1.qt_zcMoney,sum(t2.qt_srMoney-t2.qt_zcMoney)+@qcomney
from detail t1,detail t2 
where t1.qt_date>=t2.qt_date 
and t1.qt_date >=@datestart
group by t1.qt_date,t1.qt_dkfs,t1.qt_srMoney,t1.qt_zcMoney
order by t1.qt_date;
go

---避免日期出现两条导致结余数据计算异常-----
declare @datestart datetime ---开始计算日期
set @datestart ='2018-2-1'
declare @qcomney money --期初
set @qcomney =100

with cteName  as 
(
  select qt_srMoney,qt_zcMoney,qt_date,qt_dkfs,  
  row_number() over ( order by qt_date)  as keyID  from detail where qt_date >=@datestart
)  select t1.keyId,t1.qt_date,t1.qt_dkfs,t1.qt_srMoney,t1.qt_zcMoney,sum(t2.qt_srMoney-t2.qt_zcMoney)+@qcomney
from cteName t1,cteName t2 
where t1.keyId>=t2.keyId  
group by t1.qt_date,t1.qt_dkfs,t1.qt_srMoney,t1.qt_zcMoney,t1.keyId
order by t1.keyId;

go
truncate table detail
drop table detail

二、使用CTE统计树形结构

索引就一种特殊的查询表,数据库的搜索引擎可以利用它加速对数据的检索。索引很类似与现实生活中书的目录,不需要查询整本书内容就可以找到想要的数据。缺点是它减慢了数据录入的速度,同时也增加了数据库的尺寸大小。

 

  最近在码代码时,领导就来一句:嘿man,你给我统计一下所有xxx产品的信息,要快,那边在催了…。这里抽象一下,如下,大概就是找出所有家具产品的信息,这个分类表包含树形结构,ParentId为0是某种分类的根,它下面可能有许多种子节点/叶子节点。这里需要要找的实际就是一个以家具为根的树。

事务
事务就是被绑定在一起作为一个逻辑工作单元的SQL语句分组,如果任何一个语句操作失败那么整个操作就被失败,以后操作就会回滚到操作前状态,或者是上个节点。事务的四个属性:ACID。即原子性,一致性,隔离性和持久性。
脏读: update table set X = X + 10 where col = A;
update table set X = X – 10 where col = B;
假设此时执行完了第一个sql语句,此时数据库里面做了更新。用户可以看到效果,但是由于某种原因,第二个sql语句执行失败了,事务回滚此时用户就会看到原来的效果,这就是脏读。
事务隔离级别中的READ
COMMITED可以解决脏读现象(使用的是共享锁),根据其名就可以看得出:提交完读
事务还有其余的三种隔离级别,在这里就不说了。

  图片 1

锁的粒度有哪些?
数据库锁:锁定整个数据库,这通常发生在整个数据库模式改变的时候。
表锁:锁定整个表,这包含了与该表相关联的所有数据相关的对象,包括实际的数据行(每一行)以及与该表相关联的所有索引中的键。
区段锁:锁定整个区段,因为一个区段由8页组成,所以区段锁定是指锁定控制了区段、控制了该区段内8个数据或索引页以及这8页中的所有数据行。
页锁:锁定该页中的所有数据或索引键。
行或行标识符:虽然从技术上将,锁是放在行标识符上的,但是本质上,它锁定了整个数据行。

发表评论

电子邮件地址不会被公开。 必填项已用*标注