背景 一个项目的开发,离不开数据库的相关操作,表/视图设计,存储过程,触发器等等数据库对象的操作是非常频繁的。有时候,我们会查找系统中类似的代码,然后复制/粘贴进行再进行相应的修改。本文的目的在于归纳、总结sqlserver数据库的常用操作,并不断更
背景
一个项目的开发,离不开数据库的相关操作,表/视图设计,存储过程,触发器等等数据库对象的操作是非常频繁的。有时候,我们会查找系统中类似的代码,然后复制/粘贴进行再进行相应的修改。本文的目的在于归纳、总结sqlserver数据库的常用操作,并不断更新。期以备忘!
p1 sql的执行顺序
sql语句是操作数据库的工具,了解sql的执行顺序会极大地帮助我们提高我们编写的sql的执行效率。见以下代码:
(8)select (9)distinct (11)
(1)from [left_table]
(3) join
(2)on
(4)where
(5)group by
(6)with
(7)having
(10)order by
from:对from子句中的前两个表执行笛卡尔积(cartesian product)(交叉联接),生成虚拟表vt1
on:对vt1应用on筛选器。只有那些使为真的行才被插入vt2.
outer(join):如 果指定了outer join(相对于cross join 或(inner join),保留表(preserved table:左外部联接把左表标记为保留表,,右外部联接把右表标记为保留表,完全外部联接把两个表都标记为保留表)中未找到匹配的行将作为外部行添加到 vt2,生成vt3.如果from子句包含两个以上的表,则对上一个联接生成的结果表和下一个表重复执行步骤1到步骤3,直到处理完所有的表为止。
where:对vt3应用where筛选器。只有使为true的行才被插入vt4.
group by:按group by子句中的列列表对vt4中的行分组,生成vt5.
cube|rollup:把超组(suppergroups)插入vt5,生成vt6.
having:对vt6应用having筛选器。只有使为true的组才会被插入vt7.
select:处理select列表,产生vt8.
distinct:将重复的行从vt8中移除,产生vt9.
order by:将vt9中的行按order by 子句中的列列表排序,生成游标(vc10)。
top:从vc10的开始处选择指定数量或比例的行,生成表vt11,并返回调用者。
总的来说,select的列是最后一步被执行的,而from的table是首先被执行的。
p2 创建带try…catch的存储过程模板
copy下面的代码,然后新建查询,就可以写sql语句,执行完后,一个你自己的存储过程就建立好了!
use [db]--设定对应的数据库
go
set ansi_nulls on
go
set quoted_identifier on
go
-- =============================================
-- author:
-- describe:
-- =============================================
create procedure [dbo].[up_insertjhbdata] --存储过程名
(
@customername varchar(50) --参数
)
as
begin
set nocount on --提高性能的,必须要有
declare @now datetime
set @now = getdate() --所有操作保证统一时间
begin try
--在这里写sql
end try
begin catch
declare @errormessage nvarchar(4000) ;
declare @errorseverity int ;
declare @errorstate int ;
select @errormessage = error_message() ,
@errorseverity = error_severity() ,
@errorstate = error_state() ;
print @errormessage
raiserror(@errormessage, -- message text.
@errorseverity, -- severity.
@errorstate -- state.
) ;
return -1 ;
end catch
end
p3 创建带事务的存储过程模板
只是将带try…catch的存储过程的模板中加入了事务的控制,使用类似
use [db]
go
set ansi_nulls on
go
set quoted_identifier on
go
-- =============================================
-- author:
-- describe:
-- =============================================
create procedure [dbo].[up_insertjhbdata]--存储过程名
--参数
(
@customername varchar(50)
)
--参数
as
begin
set nocount on ;--提高性能的,必须要有
declare @now datetime ;
set @now = getdate() ;--所有操作保证统一时间
begin try
begin transaction mytrans ;--开始事务
--在这里写sql
commit transaction mytrans ;--事务提交语句
end try
begin catch
rollback transaction mytrans-- 始终回滚事务
--抛出异常
declare @errormessage nvarchar(4000) ;
declare @errorseverity int ;
declare @errorstate int ;
select @errormessage = error_message() ,
@errorseverity = error_severity() ,
@errorstate = error_state() ;
raiserror(@errormessage, -- message text.
@errorseverity, -- severity.
@errorstate -- state.
) ;
end catch
end
p8 分组数据集并返回每个组的前n条记录
row_number()函数用于生成行号;利用partition by可以将结果集按照指定需求进行分组;最终使用一个简单的子查询就能够获取每组的前3条数据
select *
from ( select row_number() over ( partition by productno order by productno ) as rownum ,
*
from im.dbo.iteminfo
) t
where t.rownum in ( 1, 2, 3 )
p9 【用户自定义表类型】的使用