网站首页 > 技术文章 正文
对于刚刚接触AI领域,代码编程领域的人们来说,数据库是核心,那么数据库的核心又是什么呢?这就是今天给大家带来的内容:SQL Server之存储过程。
“存储过程”又名数据库引擎,用了它会有哪些好处,又会给我们带来什么方面的便捷,我们具体展开来讲解一下;
SQL Server 中的存储过程是由一个或多个 Transact-SQL 语句或对 Microsoft .NET Framework 公共语言运行时 (CLR) 方法的引用构成的一个组。 过程与其他编程语言中的构造相似,这是因为它们都可以:
- 接受输入参数并以输出参数的格式向调用程序返回多个值。
- 包含用于在数据库中执行操作的编程语句。 这包括调用其他过程。
- 向调用程序返回状态值,以指明成功或失败(以及失败的原因)。
总结来说SQL 存储过程 是一组预编译的 SQL 语句,存储在数据库中,可以通过调用来执行。存储过程可以提高代码复用性、性能优化和安全性
一、使用存储过程的好处
减少了服务器/客户端网络流量
过程中的命令作为代码的单个批处理执行。 这可以显著减少服务器和客户端之间的网络流量,因为只有对执行过程的调用才会跨网络发送。 如果没有过程提供的代码封装,每个单独的代码行都不得不跨网络发送。
代码的重复使用
任何重复的数据库操作的代码都非常适合于在过程中进行封装。 这消除了不必要地重复编写相同的代码、降低了代码不一致性,并且允许拥有所需权限的任何用户或应用程序访问和执行代码。
更容易维护
在客户端应用程序调用过程并且将数据库操作保持在数据层中时,对于基础数据库中的任何更改,只有过程是必须更新的。 应用程序层保持独立,并且不必知道对数据库布局、关系或进程的任何更改的情况。
提升了性能
默认情况下,在首次执行过程时将编译过程,并且创建一个执行计划,供以后的执行重复使用。 因为查询处理器不必创建新计划,所以,它通常用更少的时间来处理过程。
如果过程引用的表或数据有显著变化,则预编译的计划可能实际上会导致过程的执行速度减慢。 在此情况下,重新编译过程和强制新的执行计划可提高性能。
二、存储过程的类型
用户定义
用户定义的过程可在用户定义的数据库中创建,或者在除了 Resource 数据库之外的所有系统数据库中创建。 该过程可在 Transact-SQL 中开发,或者作为对 Microsoft .NET Framework 公共语言运行时 (CLR) 方法的引用开发。
临时
临时过程是用户定义过程的一种形式。 临时过程与永久过程类似,唯一的不同点在于它们存储在 tempdb 中。 临时过程有两种类型:本地过程和全局过程。 它们在名称、可见性以及可用性上有区别。 本地临时过程的名称以单个数字符号 (#) 开头;它们仅对当前的用户连接是可见的;当用户关闭连接时被删除。 全局临时过程的名称以两个数字符号 (##) 开头,创建后对任何用户都是可见的,并且在使用该过程的最后一个会话结束时被删除。
系统
系统过程包含数据库引擎。 它们物理上存储在内部隐藏的 Resource 数据库中,但逻辑上出现在每个系统定义和用户定义数据库的 sys 架构中。 此外,msdb 数据库还在 dbo 架构中包含用于计划警报和作业的系统存储过程。 因为系统过程以前缀 sp_ 开头,所以,我们建议你在命名用户定义过程时不要使用此前缀。
SQL Server 支持在 SQL Server 和外部程序之间提供一个接口以实现各种维护活动的系统过程。 这些扩展过程使用 xp_ 前缀。
简单介绍完使用存储过程的好处,以及类型,接下来教大家如何使用 SQL Server Management Studio 和 Transact-SQL CREATE PROCEDURE 语句来创建 SQL Server 存储过程。
一、存储过程的基本语句
1. 创建存储过程
CREATE PROCEDURE ProcedureName
@Parameter1 DataType,
@Parameter2 DataType
AS
BEGIN
-- SQL 语句
SELECT * FROM TableName WHERE ColumnName = @Parameter1;
END;
2. 调用存储过程
EXEC ProcedureName @Parameter1 = Value1, @Parameter2 = Value2;
3. 删除存储过程
DROP PROCEDURE ProcedureName;
二、存储过程的示例
示例 1:简单查询
CREATE PROCEDURE GetEmployeeByID
@EmployeeID INT
AS
BEGIN
SELECT * FROM Employees WHERE EmployeeID = @EmployeeID;
END;
-- 调用
EXEC GetEmployeeByID @EmployeeID = 1;
示例 2:带输出参数
CREATE PROCEDURE GetEmployeeCount
@DepartmentID INT,
@EmployeeCount INT OUTPUT
AS
BEGIN
SELECT @EmployeeCount = COUNT(*)
FROM Employees
WHERE DepartmentID = @DepartmentID;
END;
-- 调用
DECLARE @Count INT;
EXEC GetEmployeeCount @DepartmentID = 2, @EmployeeCount = @Count OUTPUT;
PRINT @Count;
示例 3:插入数据并返回新记录的 ID
CREATE PROCEDURE AddEmployee
@FirstName NVARCHAR(50),
@LastName NVARCHAR(50),
@HireDate DATE,
@NewEmployeeID INT OUTPUT
AS
BEGIN
INSERT INTO Employees (FirstName, LastName, HireDate)
VALUES (@FirstName, @LastName, @HireDate);
SET @NewEmployeeID = SCOPE_IDENTITY(); -- 获取新插入的 ID
END;
-- 调用
DECLARE @NewID INT;
EXEC AddEmployee @FirstName = 'Jane', @LastName = 'Doe', @HireDate = '2023-10-01', @NewEmployeeID = @NewID OUTPUT;
PRINT 'New Employee ID: ' + CAST(@NewID AS NVARCHAR);
三、存储过程的优点
- 性能优化
- 存储过程在首次执行时会被编译并缓存,后续调用速度更快。
- 代码复用
- 将常用的 SQL 逻辑封装在存储过程中,减少重复代码。
- 安全性
- 可以通过存储过程限制用户对底层表的直接访问,只允许通过存储过程操作数据。
- 事务管理
- 可以在存储过程中实现复杂的事务逻辑。
四、存储过程的高级用法
1. 条件逻辑
CREATE PROCEDURE CheckSalary
@EmployeeID INT
AS
BEGIN
DECLARE @Salary DECIMAL(10,2);
SELECT @Salary = Salary FROM Employees WHERE EmployeeID = @EmployeeID;
IF @Salary > 50000
BEGIN
PRINT 'High Salary';
END
ELSE
BEGIN
PRINT 'Low Salary';
END
END;
-- 调用
EXEC CheckSalary @EmployeeID = 1;
2. 循环操作
CREATE PROCEDURE UpdateSalaries
@Percentage DECIMAL(5,2)
AS
BEGIN
DECLARE @EmployeeID INT;
DECLARE EmployeeCursor CURSOR FOR
SELECT EmployeeID FROM Employees;
OPEN EmployeeCursor;
FETCH NEXT FROM EmployeeCursor INTO @EmployeeID;
WHILE @@FETCH_STATUS = 0
BEGIN
UPDATE Employees
SET Salary = Salary * (1 + @Percentage / 100)
WHERE EmployeeID = @EmployeeID;
FETCH NEXT FROM EmployeeCursor INTO @EmployeeID;
END;
CLOSE EmployeeCursor;
DEALLOCATE EmployeeCursor;
END;
-- 调用
EXEC UpdateSalaries @Percentage = 10; -- 给所有员工加薪 10%
3. 错误处理
CREATE PROCEDURE SafeInsert
@FirstName NVARCHAR(50),
@LastName NVARCHAR(50)
AS
BEGIN
BEGIN TRY
INSERT INTO Employees (FirstName, LastName)
VALUES (@FirstName, @LastName);
END TRY
BEGIN CATCH
PRINT 'Error: ' + ERROR_MESSAGE();
END CATCH
END;
-- 调用
EXEC SafeInsert @FirstName = 'John', @LastName = 'Doe';
五、存储过程的最佳实践
- 命名规范
- 使用有意义的名称,如 sp_GetEmployeeByID 或 usp_UpdateSalary。
- 避免过度使用游标
- 游标性能较差,尽量使用集合操作(如 UPDATE、DELETE)。
- 参数验证
- 在存储过程中对输入参数进行验证,避免 SQL 注入或无效数据。
- 注释与文档
- 为存储过程添加注释,说明其功能、参数和返回值。
实践练习
尝试编写存储过程实现以下功能:
- 分页查询
- 数据导入/导出
- 复杂业务逻辑(如订单处理)
通过掌握存储过程,你可以显著提升 SQL Server 的开发效率和性能!
- 上一篇: 业务对象、数据实体、物理表傻傻分不清楚
- 下一篇: AI如何将“一篇文章”一键转换成“讲解视频”?
猜你喜欢
- 2025-07-23 微信读书后台架构演进之路(微信读书是干什么的)
- 2025-07-23 数据字典是什么?和数据库、数据仓库有什么关系?
- 2025-07-23 逻辑学基础常识整理(逻辑学基础知识点)
- 2025-07-23 imec与TEL扩展战略合作伙伴关系,共促后2nm尖端制程发展
- 2025-07-23 WMS系统从入门到精通(六)-原型图设计及逻辑实战-上架管理
- 2025-07-23 银行各系统架构全景解析(银行各系统以及作用)
- 2025-07-23 系分考点笔记:数据库模式三件套(数据库3个模式)
- 2025-07-23 如何在Spring Boot3中实现通用文件存储服务全攻略!
- 2025-07-23 MySQL技术内幕2:从架构五视图角度来看MySQL结构
- 2025-07-23 硅通孔(TSVs)尺寸缩小对微观结构和热力学响应的影响
- 08-06中等生如何学好初二数学函数篇
- 08-06C#构造函数
- 08-06初中数学:一次函数学习要点和方法
- 08-06仓颉编程语言基础-数据类型—结构类型
- 08-06C++实现委托机制
- 08-06初中VS高中三角函数:从"固定镜头"到"360°全景",数学视野升级
- 08-06一文讲透PLC中Static和Temp变量的区别
- 08-06类三剑客:一招修改所有对象!类方法与静态方法的核心区别!
- 1524℃桌面软件开发新体验!用 Blazor Hybrid 打造简洁高效的视频处理工具
- 657℃Dify工具使用全场景:dify-sandbox沙盒的原理(源码篇·第2期)
- 528℃MySQL service启动脚本浅析(r12笔记第59天)
- 494℃启用MySQL查询缓存(mysql8.0查询缓存)
- 493℃服务器异常重启,导致mysql启动失败,问题解决过程记录
- 480℃「赵强老师」MySQL的闪回(赵强iso是哪个大学毕业的)
- 462℃mysql服务怎么启动和关闭?(mysql服务怎么启动和关闭)
- 461℃MySQL server PID file could not be found!失败
- 最近发表
- 标签列表
-
- cmd/c (90)
- c++中::是什么意思 (84)
- 标签用于 (71)
- 主键只能有一个吗 (77)
- c#console.writeline不显示 (95)
- pythoncase语句 (88)
- es6includes (74)
- sqlset (76)
- windowsscripthost (69)
- apt-getinstall-y (100)
- node_modules怎么生成 (87)
- chromepost (71)
- flexdirection (73)
- c++int转char (80)
- mysqlany_value (79)
- static函数和普通函数 (84)
- el-date-picker开始日期早于结束日期 (70)
- asynccallback (71)
- localstorage.removeitem (74)
- vector线程安全吗 (70)
- java (73)
- js数组插入 (83)
- mac安装java (72)
- 查看mysql是否启动 (70)
- 无效的列索引 (74)