存储过程和视图有什么区别?

207
我对以下几个问题感到困惑:
  1. 存储过程和视图有什么区别?

  2. 在 SQL Server 中,何时应该使用存储过程,何时应该使用视图?

  3. 视图是否允许创建动态查询,以便我们可以传递参数?

  4. 哪一个更快,并且基于什么理由一个比另一个更快?

  5. 视图或存储过程是否会永久分配内存?

  6. 如果有人说视图创建了虚拟表,而存储过程则创建了物料表,这是什么意思?

如有其他需要,请告知。


我想问什么时候应该使用视图而不是存储过程。 - Siavoshkc
10个回答

209

视图代表一个虚拟的表格。您可以在视图中连接多个表格,并使用该视图将数据呈现为来自单个表格的数据。

存储过程使用参数执行函数...无论是更新和插入数据,还是返回单个值或数据集。

创建视图和存储过程 - Microsoft提供了一些有关何时以及为什么要使用它们的信息。

如果我有两个表:

  • tbl_user ,具有列:user_iduser_nameuser_pw
  • tbl_profile,具有列:profile_iduser_idprofile_description

如果我发现自己经常查询这些表格...而不是在每个SQL语句中都进行连接,我会定义一个像这样的视图:

CREATE VIEW vw_user_profile
AS
  SELECT A.user_id, B.profile_description
  FROM tbl_user A LEFT JOIN tbl_profile B ON A.user_id = b.user_id
GO

因此,如果我未来想要通过user_id查询 profile_description,我所需做的就是:

SELECT profile_description FROM vw_user_profile WHERE user_id = @ID

这个代码可以在存储过程中使用,例如:

CREATE PROCEDURE dbo.getDesc
    @ID int
AS
BEGIN
    SELECT profile_description FROM vw_user_profile WHERE user_id = @ID
END
GO

所以,稍后我可以调用:

dbo.getDesc 25

我将获取user_id为25的描述,其中25是您的参数。

显然还有许多细节,这只是基本思路。


2
但是我也可以在存储过程中连接多个表,而无需提供参数。 - NoviceToDotNet
9
但是,你为什么要那样做?你想要达到什么目的?你可以将视图作为表来使用......存储过程用于执行操作......视图则是为了让你的生活更轻松。 - Patrick
2
把视图看作是一个存储的查询,因此如果你发现需要经常连接两个表才能完成工作,你可以创建一个视图来进行操作,这样就不必每次都连接它们了。 - Patrick
好的,如果创建了视图,则只能从视图中获取数据,但无论如何它都必须引用实际表来获取数据,那么存储过程和视图有何区别呢? - NoviceToDotNet
2
正确,但它会存储您的视图...这样您就可以像单个表格一样调用它。这样,您只需创建一次连接,以后任何使用都可以直接引用该视图,该视图将调用底层 SQL,就好像它是一个表格一样。 - Patrick
显示剩余3条评论

164

这里有大量的信息(点击此处)

以下是一个好的总结:

存储过程:

  • 接受参数
  • 不能作为更大查询中的构建块
  • 可以包含多个语句、循环、IF ELSE等
  • 可以对一个或多个表进行修改
  • 不能用作INSERT、UPDATE或DELETE语句的目标。

视图:

  • 不接受参数
  • 可以作为更大查询的构建块
  • 只能包含一个SELECT查询
  • 不能对任何表执行修改操作
  • 但有时可以用作INSERT、UPDATE或DELETE语句的目标。

8
观点中不应包含任何“order by”或“top”子句。 - sksallaj
4
“can NOT be used as the target of an INSERT, UPDATE or DELETE statement”是什么意思?我们不能在存储过程中使用INSERT,DELETE或UPDATE吗? - Arsman Ahmad
“视图不接受参数”这种说法是不正确的吗?例如,视频链接:https://www.youtube.com/watch?v=zK-mWjUxKpw - xayer
视图可以对基本表/表进行修改: https://csharp-video-tutorials.blogspot.com/2012/09/updateable-views-part-40.html - Khurram W. Malik
2
@ArsmanAhmad 为了澄清:您可以在存储过程中使用INSERT、UPDATE和DELETE。但是,存储过程不能成为INSERT、UPDATE或DELETE语句的目标。例如:您不能将数据插入到存储过程中。存储过程不是任何类型的表,因此您不能向其中插入数据、更新其中的数据或删除其中的数据。 - Martijn

16

SQL视图是一种虚拟表,它基于SQL SELECT查询。视图引用一个或多个现有的数据库表或其他视图。它是数据库的快照,而存储过程是编译成单个执行计划的Transact-SQL语句组。

视图简单地展示存储在数据库表中的数据,而存储过程是可以执行的语句组。

由于视图显示来自所引用表的数据,因此更快,而存储过程则执行sql语句。

请查看本文:视图与存储过程。正是您所寻找的。


提到的链接“View vs Stored Procedures”仅涉及存储过程相关页面,没有关于视图的信息! - Terradon

11

首先需要理解的是,这两个东西是不同的。 存储过程 最适合用于 INSERT-UPDATE-DELETE 语句。而 视图 则用于 SELECT 语句。你应该同时使用它们。

在视图中您无法更改数据。 一些数据库具有可更新的视图,您可以在 视图 上使用 INSERT-UPDATE-DELETE


3
使用视图可以修改底层表中的数据。视图是可更新的。 - Dot Net developer
视图是可更新的,但有一定条件:您可以在视图的FROM子句中的一个基本表中更新/插入数据。 - Seb

7
除了以上评论,我想再补充一些关于视图的要点。
1. 视图可以用来隐藏复杂性。想象一个场景,5个人正在一个项目上工作,但只有其中一个人擅长数据库操作,比如复杂的连接。在这种情况下,他可以创建视图,其他团队成员可以像查询单个表一样轻松地查询它们。
2. 通过视图可以轻松实现安全性。假设我们有一个名为"Employee"的表,其中包含诸如"Salary"、"SSN number"等敏感列。这些列不应该对没有授权查看它们的用户可见。在这种情况下,我们可以创建一个视图,选择表中不需要任何授权的列,例如"Name"、"Age"等,而不会暴露敏感列(如前面提到的"Salary"等)。现在,我们可以删除直接查询"Employee"表的权限,只保留对视图的读取权限。通过使用视图,我们可以实现安全性。

6

视图是在数据库中保存复杂SELECT语句的简单方法。

存储过程用于当简单SQL不足以满足需求时。存储过程包含变量、循环和对其他存储过程的调用。它是一种编程语言,而不是查询语言。

  1. 视图是静态的。将其视为具有特定布局的新表,其中的数据是使用创建视图时的查询动态生成的。与任何SQL表一样,可以使用WHERE、GROUP BY和ORDER BY进行排序和筛选。

  2. 这取决于你要做什么。

  3. 这取决于数据库。简单视图只运行查询并过滤结果。但像Oracle这样的数据库允许创建“物化”视图,这基本上是一个表,在视图的基础数据发生更改时会自动更新。

    物化视图允许您在视图的列上创建索引(尤其是计算列,在数据库中不存在)。

  4. 我不明白你在说什么。


6
当Mahesh表示您无法更改视图中的数据时,他并不完全正确。因此,对于Patrick的视图而言,是可以更改其中的数据的。
CREATE View vw_user_profile AS 
Select A.user_id, B.profile_description
FROM tbl_user A left join tbl_profile B on A.user_id = b.user_id

我可以更新数据,例如,我可以执行以下任一操作...

Update vw_user_profile Set profile_description='Manager' where user_id=4

或者

Update tbl_profile Set profile_description='Manager' where user_id=4

由于并不是所有表格中的字段都存在,并且我假设PROFILE_ID是主键且不能为空,因此您无法向此视图中插入内容。 但有时您可以向视图中插入数据...

我使用...在现有表格上创建了一个视图。

Create View Junk as SELECT * from [TableName]

然后

Insert into junk (Code,name) values 
('glyn','Glyn Roberts'),
('Mary','Maryann Roberts')

并且

DELETE from Junk Where ID>4

在这种情况下,INSERT和DELETE都起作用了。

显然,您无法更新任何聚合或计算的字段,但是任何仅为直接视图的视图都应该是可更新的。

如果视图包含多个表,则无法插入或删除,但如果视图仅是一个表的子集,则通常可以。


4
  1. 视图是一种动态查询,您可以在其中使用"WHERE"子句。
  2. 存储过程是一个固定的数据选择,返回预定义的结果。
  3. 既不是视图,也不是存储过程分配内存。只有材料化视图。
  4. 表只是一个实体,视图可以从不同的实体或表中收集数据。

1
这不正确。视图是一个存储的SELECT语句,不能接受参数。存储过程是动态的,可以接受参数。你可以在两者中都使用WHERE子句,并且可以从多个表中查询数据。 - Dave Black

3

主要区别在于当您查询视图时,它的定义会被粘贴到您的查询中。存储过程也可以提供查询结果,但它是经过编译的,因此速度更快。另一个选项是索引视图。


2
@Patrick所说的是正确的,但是为了回答你的其他问题,一个视图会在内存中自行创建,根据联接类型、数据和是否有聚合操作,它可能需要占用相当多的内存。
存储过程会使用临时哈希表(例如#tmpTable1)或者在内存中使用@tmpTable1来完成所有处理,具体取决于你想让它做什么。
存储过程类似于函数,但是可以直接通过名称调用,而不是像函数一样在查询内部使用。
显然,大多数情况下,如果你没有检索大量数据,内存表会更快。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接