SQL高级知识:存储过程

存储过程的定义

存储过程其实就是已预编译为可执行过程的一个或多个SQL语句。通过调用和传递参数即可完成该存储过程的功能。

创建存储过程语法

CREATE PROC | PROCEDURE  procedure_name
[{@参数数据类型} [=默认值] [OUTPUT],
{@参数数据类型} [=默认值] [OUTPUT],
....
]
AS
sql_statements
GO

简单示例

CREATE PROC sp_test
@param1 INT,
@param2 VARCHAR(16)
AS
SELECT * FROM test 
WHERE id=@param1
AND t_no=@param2;
GO

上面就是一个简单的示例。

注意:存储过程在创建阶段可以带参数或不带参数,不带参数的一般是执行一些不需要传递参数的语句就可以完成的功能,带参数那就是需要传递参数的SQL语句,就像上面的示例,传递了两个参数给SQL语句。带参数的一定要定义参数类型,是字符型的还要定义长度,给参数加默认值是可选的。

存储过程的优点

提高性能

SQL语句在创建过程时进行分析和编译。存储过程是预编译的,在首次运行一个存储过程时,查询优化器对其进行分析、优化,并给出最终被存在系统表中的存储计划,这样,在执行过程时便可节省此开销。

降低网络开销

存储过程调用时只需用提供存储过程名和必要的参数信息,从而可降低网络的流量。

便于进行代码移植

数据库专业人员可以随时对存储过程进行修改,但对应用程序源代码却毫无影响,从而极大的提高了程序的可移植性。

更强的安全性

系统管理员可以对执行的某一个存储过程进行权限限制,避免非授权用户对数据的访问

在通过网络调用过程时,只有对执行过程的调用是可见的。因此,恶意用户无法看到表和数据库对象名称、嵌入自己的 Transact-SQL 语句或搜索关键数据。

使用过程参数有助于避免 SQL 注入攻击。因为参数输入被视作文字值而非可执行代码,所以,攻击者将命令插入过程内的 Transact-SQL 语句并损害安全性将更为困难。

可以对过程进行加密,这有助于对源代码进行模糊处理。

存储过程的缺点

逻辑处理吃力

SQL本身是一种结构化查询语言,但不是面向对象的的,本质上还是过程化的语言,面对复杂的业务逻辑,过程化的处理会很吃力。同时SQL擅长的是数据查询而非业务逻辑的处理,如果如果把业务逻辑全放在存储过程里面,违背了这一原则。

修改参数复杂

如果需要对输入存储过程的参数进行更改,或者要更改由其返回的数据,则您仍需要更新程序集中的代码以添加参数、更新调用,等等,这时候估计会比较繁琐了。

开发调试复杂

由于IDE的问题,存储过程的开发调试要比一般程序困难。

无法应用缓存

虽然有全局临时表之类的方法可以做缓存,但同样加重了数据库的负担。如果缓存并发严重,经常要加锁,那效率实在堪忧。

不支持群集

数据库服务器无法水平扩展,或者数据库的切割(水平或垂直切割)。数据库切割之后,存储过程并不清楚数据存储在哪个数据库中。

创建不带参数的存储过程

示例:查询订单表中订单总数

--查询存储过程
IF OBJECT_ID (N'PROC_ORDER_COUNT', N'P')
    IS NOT NULL
    DROP PROCEDURE  PROC_ORDER_COUNT;
GO
CREATE PROCEDURE  PROC_ORDER_COUNT
AS 
    SELECT COUNT(OrderID) FROM Orders;
GO

执行上述存储过程:

EXEC PROC_ORDER_COUNT;

创建带参数的存储过程

示例:根据城市查询订单数量

--查询存储过程,根据城市查询总数
IF OBJECT_ID (N'PROC_ORDER_COUNT', N'P')
IS NOT NULL
    DROP PROCEDURE  PROC_ORDER_COUNT;
GO
CREATE PROCEDURE  
PROC_ORDER_COUNT(@city NVARCHAR(50))
AS
    SELECT COUNT(OrderID)
    FROM Orders WHERE City=@city
GO

执行上述存储过程:

EXEC PROC_ORDER_COUNT  N'广州';

参数带通配符

--查询订单编号头两位是LJ的订单信息,含通配符
IF OBJECT_ID (N'PROC_ORDER_INFO', N'P')
    IS NOT NULL
    DROP PROCEDURE  PROC_ORDER_INFO;
GO
CREATE PROCEDURE  PROC_ORDER_INFO
    @OrderID NVARCHAR(50)='LJ%' --默认值
AS 
    SELECT OrderID,City,OrderDate,Price
    FROM Orders
    WHERE OrderID LIKE @OrderID;
GO

执行上述存储过程:

EXEC PROC_ORDER_INFO; EXEC PROC_ORDER_INFO N'LJ%'; EXEC PROC_ORDER_INFO N'%LJ%';

带输出参数

--根据订单查询的信息,返回订单的城市及单价
IF OBJECT_ID (N'PROC_ORDER_INFO ', N'P')
    IS NOT NULL
    DROP PROCEDURE  PROC_ORDER_INFO ;
GO
CREATE PROCEDURE  PROC_ORDER_INFO
    @orderid NVARCHAR(50), --输入参数
    @city NVARCHAR(20) OUT, --输出参数
    @price FLOAT OUTPUT    --输入输出参数
AS 
    SELECT @city=City,@price=Price
    FROM Orders
    WHERE OrderID=@orderid
    AND Price=@price;
GO

执行上述存储过程:

DECLARE @orderid NVARCHAR(50),
@city NVARCHAR(20),
@price  INT;
SET @orderid= N'LJ0001';
SET @price = 35.21;
EXEC PROC_ORDER_INFO @orderid,@city OUT, @price OUTPUT;
SELECT @city, @price;

存储过程中的插入

--新增订单信息
IF OBJECT_ID (N'PROC_INSERT_ORDER', N'P')
    IS NOT NULL
    DROP PROCEDURE  PROC_INSERT_ORDER;
GO
CREATE PROCEDURE  PROC_INSERT_ORDER
    @orderid  NVARCHAR(50),
    @city NVARCHAR(20),
    @price FLOAT 
AS 
    INSERT INTO Orders(OrderID,City,Price)
    VALUES(@orderid,@city,@price)
GO

执行上述存储过程:

EXEC PROC_INSERT_ORDER N'LJ0001',N'广州',35.21;

存储过程中的更新

--修改订单信息
IF OBJECT_ID (N'PROC_UPDATE_ORDER', N'P')
    IS NOT NULL
    DROP PROCEDURE  PROC_UPDATE_ORDER;
GO
CREATE PROCEDURE  PROC_UPDATE_ORDER
    @orderid NVARCHAR(50),
    @city NVARCHAR(20),
    @price FLOAT 
AS 
    UPDATE Orders SET OrderID=@orderid,
    City=@city,
    Price=@price;
GO

执行上述存储过程:

EXEC PROC_UPDATE_ORDER N'LJ0001',N'上海',37.21;

存储过程中的删除

--删除订单信息
IF OBJECT_ID (N'PROC_DELETE_ORDER', N'P')
    IS NOT NULL
    DROP PROCEDURE  PROC_DELETE_ORDER;
GO
CREATE PROCEDURE  PROC_DELETE_ORDER
    @orderid NVARCHAR(50),
 AS 
    DELETE  FROM Orders
    WHERE OrderID=@orderid;
GO

执行上述存储过程:

EXEC PROC_DELETE_ORDER N'LJ0001';

重复编译存储过程

重复编译存储过程的目的是为了提高存储过程的执行效率。

--重复编译
IF OBJECT_ID (N'PROC_ORDER_WITH_RECOMPILE', N'P')
    IS NOT NULL
    DROP PROCEDURE PROC_ORDER_WITH_RECOMPILE;
GO
CREATE PROCEDURE  PROC_ORDER_WITH_RECOMPILE
WITH RECOMPILE --重复编译
AS 
    SELECT * FROM Orders;
GO

加密存储过程

--查询存储过程,进行加密,加密后不能查看和修改源脚本
IF OBJECT_ID (N'PROC_ORDER_WITH_ENCRYPTION',
   N'P') IS NOT NULL
  DROP PROCEDURE PROC_ORDER_WITH_ENCRYPTION;
GO
CREATE PROCEDURE PROC_ORDER_WITH_ENCRYPTION
WITH ENCRYPTION --加密
AS 
    SELECT * FROM Orders;
GO

执行上述存储过程:

EXEC PROC_ORDER_WITH_ENCRYPTION

执行完的效果如图:

图片

  • 15
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值