网站首页 > 技术文章 正文
对于刚刚接触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-04-26 《我的世界》机械动力物流元件合成表与功能详解
- 2025-04-26 BSD、Solaris、Unix 的文件系统: UFS/UFS2、ZFS 及其他存储技术
- 2025-04-26 电商系统购物车模块设计
- 2025-04-26 AI如何将“一篇文章”一键转换成“讲解视频”?
- 2025-04-26 业务对象、数据实体、物理表傻傻分不清楚
- 2025-04-26 Win11学院:如何从Win10(MBR)无损数据升级到Win11(GPT)
- 2025-04-26 电脑存储清理对比:Macbook更强还是Windows老练?
- 2025-04-26 宇宙科幻文明系列:宇宙法则——宇宙构成元素(1)
- 2025-04-26 mysql的逻辑存储
- 2025-04-26 块存储是什么?核心原理和作用是什么?
- 04-27JavaScript注释:单行注释和多行注释详解
- 04-27贼好用的 Java 工具类库
- 04-27一文搞懂,WAF阻止恶意攻击的8种方法
- 04-27详细教你微信公众号正文页SVG交互开发
- 04-27Cookie 和 Session 到底有什么区别?
- 04-27教你一招,给你的店铺,网站,博客等添加“一键分享”功能
- 04-27按DeepSeek AI的规划,自学开发小程序第7天
- 04-27《JAVASCRIPT高级程序设计》第二章
- 最近发表
- 标签列表
-
- cmd/c (64)
- c++中::是什么意思 (83)
- 标签用于 (65)
- sqlset (59)
- ps可以打开pdf格式吗 (58)
- phprequire_once (61)
- localstorage.removeitem (74)
- routermode (59)
- vector线程安全吗 (70)
- & (66)
- java (73)
- org.redisson (64)
- log.warn (60)
- cannotinstantiatethetype (62)
- js数组插入 (83)
- resttemplateokhttp (59)
- gormwherein (64)
- linux删除一个文件夹 (65)
- mac安装java (72)
- reader.onload (61)
- outofmemoryerror是什么意思 (64)
- flask文件上传 (63)
- eacces (67)
- 查看mysql是否启动 (70)
- 无效的列索引 (74)