青少年编程与数学 02-002 Sql Server 数据库应用 12课题、存储过程编写

青少年编程与数学 02-002 Sql Server 数据库应用 12课题、存储过程编写

本课题讲解了SQL Server中存储过程的编写和操作。存储过程是数据库中预编译的SQL语句集合,能提高性能,确保数据安全性,并通过参数化提高灵活性。它们可以用于数据检索、修改和定义等任务,并可通过EXEC语句调用。

课题摘要:

本课题讲解了SQL Server中存储过程的编写和操作。存储过程是数据库中预编译的SQL语句集合,能提高性能,确保数据安全性,并通过参数化提高灵活性。它们可以用于数据检索、修改和定义等任务,并可通过EXEC语句调用。存储过程的创建使用CREATE PROCEDURE,修改使用ALTER PROCEDURE,删除使用DROP PROCEDURE。SQL Server还提供了多种内置存储过程,如sp_helpdbsp_configure,用于执行各种数据库管理任务。通过一个示例,展示了存储过程在订单处理中的应用,包括插入订单、更新状态和计算总价。


一、存储过程

在SQL Server中,存储过程(Stored Procedure)是一种在数据库中预编译的SQL语句集合,它被保存在数据库中,可以通过一个调用语句来执行。存储过程可以接收输入参数、返回输出参数,以及返回单个结果集或多个结果集。

存储过程的主要特点包括:

  1. 封装性:存储过程将SQL逻辑封装在数据库内部,使得应用程序代码更加简洁,减少了重复的数据库操作代码。

  2. 性能优化:由于存储过程在创建时会进行编译和优化,因此在执行时通常比单独的SQL语句执行得更快。

  3. 重用性:存储过程可以被不同的应用程序和用户重复调用,提高了代码的重用性。

  4. 安全性:通过限制直接对数据库表的访问,存储过程可以作为访问控制的一种手段,只允许执行存储过程中定义的操作。

  5. 事务管理 :存储过程可以包含事务控制语句,如BEGIN TRANSACTIONCOMMITROLLBACK,以确保数据的完整性。

  6. 参数化:存储过程可以接受参数,使得调用更加灵活,可以根据需要传递不同的值来执行不同的操作。

  7. 返回结果 :存储过程可以返回一个或多个结果集,也可以返回值,如通过RETURN语句。

创建存储过程的基本语法如下:

sql 复制代码
CREATE PROCEDURE procedure_name
    [@parameter1 datatype [= default_value]], [@parameter2 datatype [= default_value]]
AS
BEGIN
    -- SQL statements
END

例如,创建一个简单的存储过程来查询员工信息:

sql 复制代码
CREATE PROCEDURE GetEmployeeInfo
    @EmployeeID INT
AS
BEGIN
    SELECT * FROM Employees WHERE EmployeeID = @EmployeeID;
END

然后可以通过以下方式调用这个存储过程:

sql 复制代码
EXEC GetEmployeeInfo @EmployeeID = 123;

这将返回员工ID为123的员工信息。

二、分类

在SQL Server中,存储过程可以根据不同的标准进行分类。以下是几种常见的分类方式:

  1. 按功能分类

    • 数据检索存储过程:用于查询数据库并返回结果集,通常不修改数据。
    • 数据修改存储过程:用于插入、更新或删除数据库中的数据。
    • 数据定义存储过程:用于创建、修改或删除数据库对象,如表、视图、索引等。
  2. 按参数分类

    • 无参数存储过程:不接受任何输入参数。
    • 有参数存储过程:接受一个或多个输入参数,可以是输入参数、输出参数或两者都有。
  3. 按返回结果分类

    • 返回单个结果集的存储过程:执行后返回一个结果集。
    • 返回多个结果集的存储过程 :可以返回多个结果集,通常通过在存储过程内部使用SELECT语句实现。
  4. 按事务处理分类

    • 非事务存储过程:不涉及事务控制,或者事务控制完全由调用者管理。
    • 事务存储过程 :在存储过程内部管理事务,使用BEGIN TRANSACTIONCOMMITROLLBACK等语句。
  5. 按复杂度分类

    • 简单存储过程:只包含一些基本的SQL语句,执行简单的数据库操作。
    • 复杂存储过程:包含复杂的逻辑,可能使用循环、条件语句、临时表、游标等高级SQL特性。
  6. 按调用方式分类

    • 本地存储过程:只能在创建它们的数据库服务器上调用。
    • 远程存储过程:可以在远程服务器上调用,需要适当的网络配置和权限设置。
  7. 按执行环境分类

    • 用户定义存储过程:由数据库用户创建和使用的存储过程。
    • 系统存储过程:由SQL Server提供,用于管理数据库系统的功能和操作。
  8. 按是否可重入分类

    • 可重入存储过程:可以被其他存储过程调用,且不依赖于外部变量的状态。
    • 不可重入存储过程:在执行期间可能会被其他存储过程调用,可能会依赖于外部变量的状态。

这些分类并不是互斥的,一个存储过程可能同时属于多个分类。例如,一个存储过程可以既是数据修改存储过程,又是有参数存储过程,还是事务存储过程。

三、创建

在SQL Server中创建存储过程,你可以使用CREATE PROCEDURE语句。以下是创建存储过程的基本步骤和示例:

基本语法

sql 复制代码
CREATE PROCEDURE procedure_name
    [@parameter1 datatype [= default_value] [OUTPUT | INPUTOUTPUT]],
    [@parameter2 datatype [= default_value] [OUTPUT | INPUTOUTPUT]],
    ...
AS
BEGIN
    -- SQL statements
    -- You can include any number of SQL statements
END

参数说明

  • procedure_name:你想要创建的存储过程的名称。
  • @parameter1, @parameter2, ... :存储过程的参数,使用@前缀。参数可以是输入参数(INPUT)、输出参数(OUTPUT)或两者兼有(INPUTOUTPUT)。
  • datatype:参数的数据类型。
  • default_value:参数的默认值,如果未提供值,则使用此默认值。
  • OUTPUT:指定参数为输出参数,存储过程可以修改其值,并在存储过程执行完毕后返回给调用者。
  • INPUTOUTPUT:指定参数既可以作为输入也可以作为输出。

示例

1. 创建一个无参数的存储过程
sql 复制代码
CREATE PROCEDURE GetEmployeeCount
AS
BEGIN
    SELECT COUNT(*) FROM Employees;
END
2. 创建一个有输入参数的存储过程
sql 复制代码
CREATE PROCEDURE GetEmployeeByDepartment
    @DepartmentID INT
AS
BEGIN
    SELECT * FROM Employees WHERE DepartmentID = @DepartmentID;
END
3. 创建一个有输入输出参数的存储过程
sql 复制代码
CREATE PROCEDURE AddNewEmployee
    @EmployeeName NVARCHAR(100),
    @EmployeeID INT OUTPUT
AS
BEGIN
    INSERT INTO Employees (EmployeeName) VALUES (@EmployeeName);
    SET @EmployeeID = SCOPE_IDENTITY(); -- 获取新插入员工的ID
END

在这个例子中,@EmployeeID是一个输出参数,存储过程在插入新员工记录后,将新生成的员工ID赋值给这个参数。

创建存储过程时,你可以在其中使用各种SQL语句,包括数据查询、数据修改、事务控制等,以实现复杂的数据库操作。

四、调用

在SQL Server中,调用(或执行)存储过程非常简单。你可以使用EXECEXECUTE关键字来执行存储过程。以下是调用存储过程的基本语法和示例。

基本语法

sql 复制代码
EXEC [procedure_name [@parameter1 = value1 [, @parameter2 = value2] ...]];

或者

sql 复制代码
EXECUTE [procedure_name [@parameter1 = value1 [, @parameter2 = value2] ...]];

示例

假设你已经创建了以下存储过程:

  1. 无参数的存储过程
sql 复制代码
CREATE PROCEDURE GetEmployeeCount
AS
BEGIN
    SELECT COUNT(*) FROM Employees;
END

调用这个存储过程:

sql 复制代码
EXEC GetEmployeeCount;

或者

sql 复制代码
EXECUTE GetEmployeeCount;
  1. 有输入参数的存储过程
sql 复制代码
CREATE PROCEDURE GetEmployeeByDepartment
    @DepartmentID INT
AS
BEGIN
    SELECT * FROM Employees WHERE DepartmentID = @DepartmentID;
END

调用这个存储过程,并传递一个部门ID:

sql 复制代码
EXEC GetEmployeeByDepartment @DepartmentID = 10;

或者

sql 复制代码
EXECUTE GetEmployeeByDepartment @DepartmentID = 10;
  1. 有输入输出参数的存储过程
sql 复制代码
CREATE PROCEDURE AddNewEmployee
    @EmployeeName NVARCHAR(100),
    @EmployeeID INT OUTPUT
AS
BEGIN
    INSERT INTO Employees (EmployeeName) VALUES (@EmployeeName);
    SET @EmployeeID = SCOPE_IDENTITY(); -- 获取新插入员工的ID
END

调用这个存储过程,并获取新插入员工的ID:

sql 复制代码
DECLARE @NewEmployeeID INT;
EXEC AddNewEmployee @EmployeeName = N'John Doe', @EmployeeID = @NewEmployeeID OUTPUT;
SELECT @NewEmployeeID;

在这个例子中,@NewEmployeeID是一个输出参数,存储过程执行完毕后,你可以使用SELECT @NewEmployeeID;来查看新插入员工的ID。

注意事项

  • 如果存储过程有返回值(使用RETURN语句),你可以通过SELECT语句来获取这个返回值:
sql 复制代码
DECLARE @ReturnValue INT;
EXEC @ReturnValue = YourStoredProcedure;
SELECT @ReturnValue;
  • 如果存储过程没有参数,你仍然需要使用EXECEXECUTE关键字,即使后面没有跟任何参数。

  • 确保在调用存储过程时,传递的参数类型和顺序与存储过程中定义的参数相匹配。

通过这些基本的调用方法,你可以灵活地执行存储过程,实现各种数据库操作。

五、修改

在SQL Server中,如果你需要修改已经存在的存储过程,你可以使用ALTER PROCEDURE语句。这个语句允许你更改存储过程的参数、逻辑或返回类型等。下面是如何修改存储过程的基本步骤和示例。

基本语法

sql 复制代码
ALTER PROCEDURE procedure_name
    [@parameter1 datatype [= default_value] [READONLY]],
    [@parameter2 datatype [= default_value] [READONLY]],
    ...
AS
BEGIN
    -- SQL statements
    -- You can include any number of SQL statements
END

示例

假设你有一个存储过程GetEmployeeByDepartment,它接受一个部门ID作为参数,并返回该部门的所有员工信息。现在,你想要修改这个存储过程,使其能够接受两个参数:部门ID和员工状态(如在职或离职),并根据这两个参数过滤结果。

原始存储过程
sql 复制代码
CREATE PROCEDURE GetEmployeeByDepartment
    @DepartmentID INT
AS
BEGIN
    SELECT * FROM Employees WHERE DepartmentID = @DepartmentID;
END
修改后的存储过程

使用ALTER PROCEDURE来修改这个存储过程:

sql 复制代码
ALTER PROCEDURE GetEmployeeByDepartment
    @DepartmentID INT,
    @EmployeeStatus NVARCHAR(50) = 'Active' -- 添加一个默认参数
AS
BEGIN
    SELECT * FROM Employees 
    WHERE DepartmentID = @DepartmentID 
    AND EmployeeStatus = @EmployeeStatus;
END

在这个修改中,我们添加了一个新的参数@EmployeeStatus,并在查询中使用了这个参数来过滤结果。同时,我们为这个新参数设置了一个默认值'Active',这意味着如果调用存储过程时没有指定@EmployeeStatus的值,它将默认为'Active'

注意事项

  • 参数顺序 :在ALTER PROCEDURE语句中,参数的顺序很重要。如果原始存储过程已经包含参数,新添加的参数应该放在原始参数之后。
  • 参数默认值:你可以为参数设置默认值,这样在调用存储过程时,如果未提供该参数的值,将使用默认值。
  • 修改逻辑 :在ALTER PROCEDURE中,你可以修改存储过程的逻辑,包括添加、删除或修改SQL语句。
  • 权限问题 :确保你有足够的权限来修改存储过程。通常,你需要有对该数据库的ALTER权限。

使用ALTER PROCEDURE可以灵活地调整存储过程以适应不断变化的需求,而无需删除并重新创建存储过程。这样可以减少对数据库的干扰,并保持数据库的稳定性。

六、删除

在SQL Server中,如果你需要删除一个不再需要的存储过程,你可以使用DROP PROCEDURE语句。这个语句会从数据库中完全移除指定的存储过程。

基本语法

sql 复制代码
DROP PROCEDURE [schema_name.]procedure_name;
  • schema_name :存储过程所属的模式(schema)的名称。如果未指定,默认为dbo
  • procedure_name:要删除的存储过程的名称。

示例

假设你有一个名为GetEmployeeByDepartment的存储过程,现在你想要删除它。

sql 复制代码
DROP PROCEDURE GetEmployeeByDepartment;

如果你的存储过程属于非dbo模式,你需要指定模式名称:

sql 复制代码
DROP PROCEDURE mySchema.GetEmployeeByDepartment;

注意事项

  • 权限 :确保你有足够的权限来删除存储过程。通常,你需要有对该数据库的DROP权限。
  • 依赖性:在删除存储过程之前,确保没有其他数据库对象(如视图、触发器或其他存储过程)依赖于它。否则,删除存储过程可能会破坏这些对象的功能。
  • 备份:在删除存储过程之前,考虑是否需要备份存储过程的代码,特别是如果你不确定未来是否还需要它。
  • 测试:在生产环境中删除存储过程之前,建议在测试环境中进行测试,以确保删除操作不会对数据库的其他部分产生不良影响。

使用DROP PROCEDURE语句可以有效地管理数据库中的存储过程,保持数据库的整洁和高效。

七、应用示例

我们通过一个具体的例子来展示如何编写和使用 SQL Server 中的存储过程。我们将创建一个存储过程,该存储过程用于处理订单,包括插入新的订单、更新订单状态以及计算订单的总价。

步骤 1: 创建必要的表结构

首先,我们需要创建一些基本的表结构。假设我们有一个数据库,其中包含以下表格:

  • Customers: 包含客户信息。
  • Orders: 包含订单信息。
  • OrderDetails: 包含订单详情(每个订单项)。
  • Products: 包含产品信息。
sql 复制代码
CREATE TABLE Customers (
    CustomerID int IDENTITY PRIMARY KEY,
    CustomerName nvarchar(100),
    ContactName nvarchar(50),
    Country nvarchar(50)
);

CREATE TABLE Orders (
    OrderID int IDENTITY PRIMARY KEY,
    CustomerID int,
    OrderDate datetime,
    Status nvarchar(20),
    FOREIGN KEY (CustomerID) REFERENCES Customers(CustomerID)
);

CREATE TABLE OrderDetails (
    OrderDetailID int IDENTITY PRIMARY KEY,
    OrderID int,
    ProductID int,
    Quantity int,
    UnitPrice money,
    FOREIGN KEY (OrderID) REFERENCES Orders(OrderID)
);

CREATE TABLE Products (
    ProductID int IDENTITY PRIMARY KEY,
    ProductName nvarchar(100),
    UnitPrice money
);

步骤 2: 插入一些测试数据

接下来,我们需要向这些表中插入一些测试数据:

sql 复制代码
INSERT INTO Customers (CustomerName, ContactName, Country)
VALUES ('Company A', 'John Doe', 'USA'),
       ('Company B', 'Jane Smith', 'Canada');

INSERT INTO Orders (CustomerID, OrderDate, Status)
VALUES (1, '2024-01-15', 'New'),
       (2, '2024-01-16', 'Processing');

INSERT INTO OrderDetails (OrderID, ProductID, Quantity, UnitPrice)
VALUES (1, 1, 5, 100.00),
       (1, 2, 2, 50.00),
       (2, 3, 3, 150.00);

INSERT INTO Products (ProductName, UnitPrice)
VALUES ('Product X', 100.00),
       ('Product Y', 50.00),
       ('Product Z', 150.00);

步骤 3: 创建存储过程

现在,我们将创建一个存储过程来处理订单的不同方面。这个存储过程将包括以下功能:

  1. 插入新的订单。
  2. 更新订单状态。
  3. 计算订单总价。
sql 复制代码
CREATE PROCEDURE dbo.ProcessOrder
    @CustomerID int,
    @OrderDate datetime,
    @Status nvarchar(20),
    @ProductID int,
    @Quantity int,
    @UnitPrice money,
    @OrderID int = NULL OUTPUT
AS
BEGIN
    -- 插入新的订单
    IF @OrderID IS NULL
    BEGIN
        INSERT INTO Orders (CustomerID, OrderDate, Status)
        VALUES (@CustomerID, @OrderDate, @Status);
        
        -- 获取新插入的订单ID
        SET @OrderID = SCOPE_IDENTITY();
    END

    -- 插入订单详情
    INSERT INTO OrderDetails (OrderID, ProductID, Quantity, UnitPrice)
    VALUES (@OrderID, @ProductID, @Quantity, @UnitPrice);

    -- 更新订单状态
    UPDATE Orders
    SET Status = @Status
    WHERE OrderID = @OrderID;

    -- 计算订单总价
    DECLARE @TotalAmount money;
    SELECT @TotalAmount = SUM(od.Quantity * od.UnitPrice)
    FROM OrderDetails od
    WHERE od.OrderID = @OrderID;

    -- 输出订单总价
    PRINT 'Total Amount for Order ' + CAST(@OrderID AS nvarchar) + ': ' + CAST(@TotalAmount AS nvarchar);
END;

步骤 4: 调用存储过程

最后,我们可以编写一个脚本来调用这个存储过程,并查看输出结果:

sql 复制代码
DECLARE @OrderID int;

-- 插入新订单并获取订单ID
EXEC dbo.ProcessOrder @CustomerID = 1, @OrderDate = '2024-01-17', @Status = 'New', @ProductID = 1, @Quantity = 3, @UnitPrice = 100.00, @OrderID = @OrderID OUTPUT;

-- 输出订单ID
PRINT 'New Order ID: ' + CAST(@OrderID AS nvarchar);

-- 更新订单状态
EXEC dbo.ProcessOrder @OrderID = @OrderID, @Status = 'Processing', @ProductID = 1, @Quantity = 3, @UnitPrice = 100.00;

-- 查看所有订单信息
SELECT o.OrderID, o.OrderDate, o.Status, c.CustomerName, SUM(od.Quantity * od.UnitPrice) AS TotalAmount
FROM Orders o
JOIN Customers c ON o.CustomerID = c.CustomerID
JOIN OrderDetails od ON o.OrderID = od.OrderID
GROUP BY o.OrderID, o.OrderDate, o.Status, c.CustomerName;

这个示例展示了如何使用存储过程来插入新订单、更新订单状态以及计算订单总价。存储过程可以有效地封装复杂的业务逻辑,并且可以在多个地方重用,提高代码的可维护性和可读性。

八、内置存储过程

SQL Server 提供了许多内置存储过程(Stored Procedures),这些存储过程可以用于执行常见的数据库管理任务,如备份、恢复、登录管理等。内置存储过程通常以 sp_ 开头,并且不需要用户显式地创建它们。以下是一些常见的内置存储过程及其用途:

数据库管理

  • sp_helpdb: 获取数据库的帮助信息。
  • sp_helpindex: 获取索引的帮助信息。
  • sp_renamedb: 重命名数据库。

对象管理

  • sp_helptext: 获取存储过程、函数或视图的文本。
  • sp_rename: 重命名数据库对象。
  • sp_tables: 列出数据库中的表。
  • sp_columns: 列出表中的列。

用户和权限管理

  • sp_grantdbaccess: 向用户授予数据库访问权限。
  • sp_grantlogin: 向用户授予登录权限。
  • sp_adduser: 添加数据库用户。
  • sp_addrole: 添加数据库角色。
  • sp_addrolemember: 将用户添加到角色中。
  • sp_denylogin: 拒绝用户的登录权限。

安全管理

  • sp_change_password: 更改用户的密码。
  • sp_dropuser: 删除数据库用户。
  • sp_droprolemember: 从角色中移除用户。

备份和恢复

  • sp_addlinkedserver: 添加链接服务器。
  • sp_dropserver: 删除链接服务器。
  • sp_attach_db: 附加数据库。
  • sp_detach_db: 分离数据库。
  • sp_renamedb: 重命名数据库。
  • sp_helpdevice: 获取物理设备的帮助信息。
  • sp_addumpdevice: 添加备份设备。
  • sp_dropdevice: 删除备份设备。
  • sp_restore: 恢复数据库。
  • sp_addmessage: 添加消息。
  • sp_dropmessage: 删除消息。

诊断和维护

  • sp_configure: 显示或更改配置选项。
  • sp_dbcmptlevel: 设置或显示兼容级别。
  • sp_dbmajorversion: 设置或显示主版本号。
  • sp_dbminorversion: 设置或显示次版本号。
  • sp_dbhelp: 获取数据库的帮助信息。
  • sp_dboption: 设置或显示数据库选项。
  • sp_dbsetting: 设置或显示数据库设置。
  • sp_dbstatus: 获取数据库的状态信息。
  • sp_dbusers: 获取数据库用户列表。
  • sp_dbtables: 获取数据库表列表。
  • sp_dbcolumns: 获取数据库表中的列信息。
  • sp_dbindexes: 获取数据库表中的索引信息。

其他

  • sp_help: 获取数据库对象的帮助信息。
  • sp_lock: 获取锁信息。
  • sp_msforeachtable: 对每个表执行命令。
  • sp_msforeachdb: 对每个数据库执行命令。
  • sp_MSforeachdb: 对每个数据库执行命令(注意大小写区别)。
  • sp_MSforeachfile: 对每个文件执行命令。
  • sp_MSforeachdir: 对每个目录执行命令。

复制相关

  • sp_addarticle: 添加复制文章。
  • sp_addsubscription: 添加订阅。
  • sp_addpushsubscription_agent: 添加推送订阅代理。
  • sp_addpullsubscription: 添加拉取订阅。
  • sp_addlogreader_agent: 添加日志阅读代理。
  • sp_addmerge_agent: 添加合并代理。
  • sp_addsnapshot_agent: 添加快照代理。
  • sp_add_distribution: 添加发布。
  • sp_add_publication: 添加出版物。
  • sp_add_job: 添加作业。

这些存储过程提供了丰富的工具来管理和维护 SQL Server 数据库。使用这些存储过程可以帮助开发者和 DBA 更高效地完成日常任务。当然,SQL Server 的内置存储过程远不止这些,详细的列表和使用方法可以在 Microsoft 的官方文档中找到。

相关推荐
致奋斗的我们7 分钟前
RHCE的学习(7)
linux·服务器·网络·学习·redhat·rhce·rhcsa
petaexpress10 分钟前
云存储的费用是多少?2024年最新价格表
运维·服务器·云存储·云存储的费用是多少·云存储的费用是多少最新·云存储费用
幽兰的天空33 分钟前
python实现excel数据导入数据库
数据库
昨天今天明天好多天44 分钟前
【Linux】ClickHouse 部署
linux·服务器·clickhouse
taolichao3044 分钟前
架设一台NFS服务器,按照要求配置
linux·运维·服务器
程序员yt1 小时前
2025秋招八股文--服务器篇
linux·运维·服务器·c++·后端·面试
2301_810730101 小时前
RHCSA基础命令整理1
linux·运维·服务器
稳重的大王1 小时前
如何使用 NetBak PC Agent 备份和恢复 Windows 计算机或服务器?
运维·服务器
纪伊路上盛名在1 小时前
服务器与服务器之间文件上传下载
运维·服务器
小何学计算机1 小时前
Nginx 配置基于主机名的 Web 服务器
服务器·前端·nginx