TSQL存储过程概念与案例实战

存储过程

存储过程由一个或多个 T-SQL 语句或对.NET公共语言运行时 (CLR) 方法的引用所构成的一组程序块。这里的T-SQL语句包括执行DDL、DML语句、应用临时表、动态SQL、定义异常处理等。但是相比于函数,它不能嵌套在查询里,但它可以调用其它的存储过程,即存储过程可以相互调用。

存储过程和常见的程序语言类似,可以指定输入和输出参数。SQL Server通过缓存存储过程的执行计划进而达到节约时间、降低CPU、内存的目的。

存储过程相对于在应用端实现业务逻辑有以下好处:

1 通过封装实现重用性和逻辑复杂性的隐藏。仅需要通过存储过程的修改(alter procedure)就能应用新的逻辑。

2 减少网络的传输,这是因为存储过程即存储在数据库里,而如果是应用程序方式访问数据库识别有网络传输的成本。

3 存储过程可以提供对数据库进行安全的访问,即赋予了执行存储过程的用户不能直接访问底层的数据库对象,这种隔离对数据库提供了保障。

补注:尽管存储过程有这些优点,但实际应用程序封装在Service(服务层),其对应的是某些单独的SQL逻辑,而如果都放在存储过程则会出现灵活性差、代码难维护的情况。

普通存储过程

假设我们有一张tb_user表,有两个字段id,name,如果我想通过传参数的形式给这张表插入数据,那么我们可以通过存储过程来实现。这里id需要沿着tb_user的最大的值往下自增,自增间隔是1。

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[usp_useradd_MS]
(@username VARCHAR(100))
AS
DECLARE @max_id int=0
DECLARE @has int=0
BEGIN
SELECT @max_id=max(id) FROM tb_user  ;
SELECT @has=1 FROM tb_user WHERE name = @username;IF @has =0BEGININSERT INTO tb_user VALUES(@max_id+1,@username);END;END;
GO--调用,可选用下列任一方式执行
exec usp_useradd_MS 'Mike' exec usp_useradd_MS @username='John'
--验证结果
SELECT * FROM tb_user;

存储过程与动态SQL

所谓动态SQL即SQL的内容是灵活的,是通过字符串拼接出来的,可以理解是不固定的。比如有一个需求,我们想通过查询指定表的字段名并以列的形式展示出来,这里就可以通过存储过程结合动态SQL来实现。因为每次传过来的参数即表名是不固定的,所以需要一个字符串变量拿到参数里的值再拼接成最终的sql(相对于翻译一下),再去数据库里执行。

CREATE PROCEDURE [dbo].[usp_getColumnsBycolumn]( @tabname VARCHAR(100))
AS
DECLARE @sql VARCHAR(8000)
DECLARE @STRING VARCHAR(500)
BEGIN   SELECT @sql= ISNULL(@sql+',','')+'['+CAST(COLID AS VARCHAR(12))+']'   FROM SYSCOLUMNS    WHERE ID = OBJECT_ID(@tabname) GROUP BY COLID   SET @STRING='SELECT * FROM (SELECT NAME,COLID FROM SYSCOLUMNS WHERE ID=OBJECT_ID('''+@tabname+'''))A pivot (MAX(NAME) for COLID in('+@sql+'))t'   EXEC(@STRING)
END
GO
--调用及结果
exec usp_getColumnsBycolumn 'tb_user'

存储过程内调用存储过程

存储过程里是可以调用其它存储过程的,有时一些复杂的逻辑需要多个存储过程结合一起才能实现最终效果。

CREATE PROCEDURE [dbo].[usp_getColumnsByonecolumn]( @tabname VARCHAR(100))
AS
DECLARE @tab Table (colid varchar(100),colname varchar(20))
BEGIN INSERT INTO @tab exec usp_getColumnsBycolumn  @tabname SELECT colid FROM @tab
END
--调用
exec usp_getColumnsByonecolumn 'tb_user'
-- 结果

注意:我们不可以把存储过程包裹在子查询里,即如下方式查询存储过程的结果是不支持的。

SELECT * FROM(exec usp_getColumnsBycolumn 'tb_user')A

系统函数查看存储过程的定义

可以通过内置的系统函数sp_helptext查看存储过程的文本定义。

sp_helptext @objname = N'usp_getColumnsByonecolumn'
#结果,存储过程的文本定义见下:
CREATE PROCEDURE [dbo].[usp_getColumnsByonecolumn]( @tabname VARCHAR(100))
AS
DECLARE @tab Table(colid varchar(100), colname varchar(20))
BEGIN
INSERT INTO @tab exec usp_getColumnsBycolumn  @tabname
SELECT colid FROM @tab
END

存储过程的安全性

存储过程跟表、视图一样首先用户和角色,赋予EXECUTE权限后才能执行。特别的,如果过程里用到非dbo的schema(架构)那么在赋予存储过程权限后也要将该架构下表的访问权限赋予用户,否则存储可以执行但是会报底层表访问权限的错误。

CREATE LOGIN db_loginuser WITH PASSWORD = 'D#2$3)5b';
GO CREATE USER db_user FOR LOGIN db_loginuser;
GO  EXECUTE AS LOGIN = 'db_loginuser';
SELECT SUSER_NAME() AS [login], USER_NAME() AS [user];

exec usp_useradd_MS 'Alice'

REVERT;
SELECT SUSER_NAME() AS [login], USER_NAME() AS [user];

GRANT EXEC ON dbo.usp_useradd_MS TO db_user;
EXECUTE AS LOGIN = 'db_loginuser';
SELECT SUSER_NAME() AS [login], USER_NAME() AS [user];
exec usp_useradd_MS 'Alice' 

REVERT;
SELECT * FROM tb_user 

:针对sa、dbo无法执行,即无法通过下列的语句切换到sa用户

EXECUTE AS LOGIN = 'sa';

EXECUTE AS LOGIN = 'dbo';

可通过REVERT;语句切换到上一次的用户执行环境。

存储过程与事务

事务是一个工作整体,它包含一个或多个操作数据(可能还包括数据结构)的活动。比如我们建表的DDL语句就是一个事务,要么建表成功要么失败,不存在中间状态。事务具有ACID性,其中A(atomicity)即原子性、C(consistency)即一致性、I(isolation)隔离性、D(durability)持久性。

SQL Server事务分为隐性事务和显性事务的,如果是隐性的可通过SET IMPLICIT_TRANSACTIONS ON;开关打开该选项,在该模式下只需要在要操作的事务的尾部编写commit或者rollback即可提交或者回滚事务,而不用在事务开头写begin tran。相对的显式事务需要在事务前后定义诸如BEGIN TRAN … COMMIT TRAN(ROLLBACK TRAN)

隐式事务的例子:

SET IMPLICIT_TRANSACTIONS ON
select @@TRANCOUNT
INSERT INTO tb_user VALUES(110,'Philips')
select @@TRANCOUNT
-- 注:以上代码需要一起执行。
-- 查看插入的数据
SELECT * FROM tb_user A WHERE A.name = 'Philips'
--这里如果回滚则数据不存在。
ROLLBACK 

以回滚为例演示在存储过程里如何使用事务。如果传入的参数(用户名)是'Lily'则回滚,其它则插入并提交事务。

CREATE PROCEDURE [dbo].[usp_useradd_MS_trans](@username VARCHAR(100))
AS
BEGIN   print @username;   if @username='Lily'   BEGIN     BEGIN TRAN     exec usp_useradd_MS @username     ROLLBACK TRAN     END   ELSE    BEGIN     exec usp_useradd_MS @username   END
END
GO
-- 执行与结果
EXEC usp_useradd_MS_trans 'Lily'
EXEC usp_useradd_MS_trans 'Tim'

SELECT * FROM tb_user A WHERE A.name = 'Lily'

SELECT * FROM tb_user A WHERE A.name = 'Tim'

数据库工程开发秘籍之TSQL 存储过程user stored procedure的概念与案例实战相关推荐

  1. SQL存储过程(Stored Procedure)

    SQL存储过程(Stored Procedure) 什么是存储过程? 存储过程(procedure)类似于C语言中的函数 用来执行管理任务或应用复杂的业务规则 存储过程可以带参数,也可以返回结果 存储 ...

  2. MySQL 存储过程(Stored Procedure)

    MySQL 5.0 版本开始支持存储过程. 存储过程(Stored Procedure)是一种在数据库中存储复杂程序,以便外部程序调用的一种数据库对象. 存储过程是为了完成特定功能的SQL语句集,经编 ...

  3. t-sql存储过程_使用T-SQL进行存储过程中ORDER BY的精确控制

    t-sql存储过程 介绍 (Introduction) The T-SQL ORDER BY clause sorts SQL Server SELECT statement result sets, ...

  4. 应用程序基础知识:activity和intent——Android开发秘籍

    应用程序基础知识:activity和intent --Android开发秘籍 v\:* {behavior:url(#default#VML);} o\:* {behavior:url(#defaul ...

  5. Android开发秘籍 第2版

    iOS传感器应用开发最佳实践_PDF电子书下载 带书签目录 完整版http://pan.baidu.com/s/1dDtSP2L   Node应用程序构建  使用MongoDB和Backbone_PD ...

  6. 数据库(MySQL)开发技术题库

    数据库(MySQL)开发技术题库 软件工程大二下 选择+填空+简答 选择题 1.SQL语言具有数据操作功能,SQL语言的一次查询的结果是一个___D___ A) 数据项      B) 记录      ...

  7. ORACLE数据库应用开发三十忌

    ☞ ░ 前往老猿Python博文目录 https://blog.csdn.net/LaoYuanPython ░ 引言 笔者及所在团队从2000年开始的CRM等系统开发,一直主要使用ORACLE数据库 ...

  8. ddr传输 pl ps_Vitis ZYNQ开发秘籍 PS 端任意控制 VGA 显示画面最终实现

    上一篇文章,<Vitis ZYNQ开发秘籍>- PS 端任意控制 VGA 显示画面的硬件架构,已经介绍了在 Vivado 中需要调用的 IP 已经各 IP 间的连线.而在实现显示的功能,咱 ...

  9. MySql基础篇---004 其它数据库对象篇:视图,存储过程与函数,变量、流程控制与游标 ,触发器

    第14章_视图 讲师:尚硅谷-宋红康(江湖人称:康师傅) 官网:http://www.atguigu.com 1. 常见的数据库对象 对象 描述 表(TABLE) 表是存储数据的逻辑单元,以行和列的形 ...

最新文章

  1. 你不得不知道的Visual Studio 2012(1)- 每日必用功能
  2. 数据库架构优化的12种组合方式与风险解读
  3. java代码_阿里资深工程师教你如何优化 Java 代码!
  4. 特征选择之嵌入法、嵌入法、排列重要性
  5. 【PC工具】更新:在线智能抠图工具,在线视频、图片、音频等转换工具,绿色免安装抠图神奇抠图工具...
  6. 抽屉效果_宜家靠边,好用不贵的全格收纳抽屉使用感受
  7. jeecms添加站点
  8. redis设置key的有效期
  9. python 迭代器相关知识
  10. 1000道Python题库系列分享20(43道填空与判断题)
  11. Child module pom.xml of pom.xml does not exist @
  12. 浅谈前端是否需要精通JS三大框架,vue,angular,react。
  13. 国科大学习资料--模式识别与机器学习(黄庆明)--期末复习题2(含答案)
  14. 数字信号处理--FFT与蝶形算法--学习笔记
  15. mysql datesub interval_Mysql之INTERVAL与DATE_SUB与EXTRACT函数的使用
  16. 华纳媒体将持有拉美和加勒比海西班牙语地区HBO品牌服务的全部所有权,包括所有HBO、MAX、Cinemax和HBO Go服务
  17. 智能电视是否是一台计算机,误区四 智能电视代替电脑使用_平板电视_液晶电视评测-中关村在线...
  18. 开店经验|如何开一家精品咖啡馆
  19. windows聚焦壁纸不更新_win10系统锁屏壁纸聚焦不更新的解决方法
  20. 图灵机是什么?一起来看看它的工作原理

热门文章

  1. JavaScript实现countSetBits设置位的数量算法(附完整源码)
  2. wxWidgets:启动默认浏览器
  3. boost::smart_ptr模块boost/pointer_to_other.hpp 的测试
  4. boost::regex模块在 cpp 文件中搜索类定义,使用 C++ Builder 闭包作为回调的测试程序
  5. GDCM:gdcm::SOPClassUIDToIOD的测试程序
  6. boost::container模块实现检查相等的容器的测试程序
  7. Boost:boost :: bind相等运算符的测试程序
  8. ITK:Levenberg-Marquardt优化
  9. DCMTK:各种“字符串值”方法的测试程序
  10. OpenCV提供的各种阈值选项的实例(附完整代码)