关于sql:什么是存储过程?

What is a stored procedure?

什么是存储过程? 他们是如何工作的? 什么是存储过程的组成(每个必须是存储过程的东西)?


存储过程是一批可以以多种方式执行的SQL语句。大多数主要DBM都支持存储过程;然而,并非所有人都这么做您需要使用特定的DBMS帮助文档来验证具体细节。由于我最熟悉SQL Server,我将使用它作为我的样本。

要创建存储过程,语法非常简单:

1
2
3
4
5
6
7
CREATE PROCEDURE <owner>.<PROCEDURE name>

     <Param> <datatype>

AS

     <Body>

例如:

1
2
3
4
5
6
7
8
CREATE PROCEDURE Users_GetUserInfo

    @login nvarchar(30)=NULL

AS

    SELECT * FROM [Users]
    WHERE ISNULL(@login,login)=login

存储过程的一个好处是,您可以将数据访问逻辑集中到一个位置,然后DBA可以轻松进行优化。存储过程还具有安全性优势,因为您可以向存储过程授予执行权限,但用户不需要对基础表具有读/写权限。这是针对SQL注入的良好的第一步。

存储过程确实存在缺点,基本上是与基本CRUD操作相关的维护。假设每个表都有一个Insert,Update,Delete和至少一个基于主键的select,这意味着每个表将有4个过程。现在拿一个体面的400桌的数据库,你有1600个程序!而且假设你没有重复,你可能会。

这是使用ORM或其他方法自动生成基本CRUD操作的地方有很多优点。


存储过程是一组预编译的SQL语句,用于执行特殊任务。

示例:如果我有一个Employee

1
2
3
4
Employee ID  Name       Age  Mobile
---------------------------------------
001          Sidheswar  25   9938885469
002          Pritish    32   9178542436

首先,我正在检索Employee表:

1
2
3
4
5
CREATE PROCEDURE Employee details
AS
BEGIN
    SELECT * FROM Employee
END

要在SQL Server上运行该过程:

1
2
3
EXECUTE   Employee details

--- (Employee details is a user defined name, give a name as you want)

然后,我将值插入Employee表

1
2
3
4
5
6
7
CREATE PROCEDURE employee_insert
    (@EmployeeID INT, @Name VARCHAR(30), @Age INT, @Mobile INT)
AS
BEGIN
    INSERT INTO Employee
    VALUES (@EmployeeID, @Name, @Age, @Mobile)
END

要在SQL Server上运行参数化过程:

1
2
3
EXECUTE employee_insert 003,’xyz’,27,1234567890

  --(Parameter size must be same as declared column size)

示例:@Name Varchar(30)

Employee表中,Name列的大小必须varchar(30)


存储过程是一组已创建并存储在数据库中的SQL语句。存储过程将接受输入参数,以便可以使用不同的输入数据通过网络在网络上使用单个过程。存储过程将减少网络流量并提高性能。如果我们修改存储过程,则所有客户端都将获得更新的存储过程。

创建存储过程的示例

1
2
3
4
5
6
CREATE PROCEDURE test_display
AS
    SELECT FirstName, LastName
    FROM tb_test;

EXEC test_display;

使用存储过程的优点

  • 存储过程允许模块化编程。

    您可以创建一次该过程,将其存储在数据库中,并在程序中多次调用它。

  • 存储过程允许更快的执行。

    如果操作需要重复执行大量SQL代码,则存储过程可以更快。它们在首次执行时被解析和优化,并且存储过程的编译版本保留在内存高速缓存中供以后使用。这意味着存储过程不需要在每次使用时重新分析和重新优化,从而导致更快的执行时间。

  • 存储过程可以减少网络流量。

    需要数百行Transact-SQL代码的操作可以通过执行过程中代码的单个语句来执行,而不是通过网络发送数百行代码。

  • 存储过程为您的数据提供了更好的安全性

    即使用户没有直接执行过程语句的权限,也可以授予用户执行存储过程的权限。

    在SQL Server中,我们有不同类型的存储过程:

    • 系统存储过程
    • 用户定义的存储过程
    • 扩展存储过程
  • 系统存储过程存储在master数据库中,它们以sp_前缀开头。这些过程可用于执行各种任务,以支持系统表中的外部应用程序调用的SQL Server函数

    示例:sp_helptext [StoredProcedure_Name]

  • 用户定义的存储过程通常存储在用户数据库中,通常用于完成用户数据库中的任务。编码这些过程时不使用sp_前缀,因为如果我们首先使用sp_前缀,它将检查master数据库,然后它来到用户定义的数据库。

  • 扩展存储过程是从DLL文件调用函数的过程。现在,不推荐使用扩展存储过程,因为最好避免使用扩展存储过程。


通常,存储过程是"SQL函数"。他们有:

1
2
3
4
5
6
7
8
9
10
-- a name
CREATE PROCEDURE spGetPerson
-- parameters
CREATE PROCEDURE spGetPerson(@PersonID INT)
-- a body
CREATE PROCEDURE spGetPerson(@PersonID INT)
AS
SELECT FirstName, LastName ....
FROM People
WHERE PersonID = @PersonID

这是一个以T-SQL为重点的例子。存储过程可以执行大多数SQL语句,返回标量和基于表的值,并且被认为更安全,因为它们可以防止SQL注入攻击。


想想这样的情况,

  • 你有一个包含数据的数据库。
  • 访问该中央数据库需要许多不同的应用程序,并且将来也会有一些新的应用程序。
  • 如果要插入内联数据库查询以访问中央数据库,在每个应用程序的代码中单独进行,那么可能您必须在不同的应用程序代码中反复复制相同的查询。
  • 在这种情况下,您可以使用存储过程(SP)。使用存储过程,您将编写许多常见查询(过程)并将其与中央数据库一起存储。
  • 现在重复工作将永远不会像以前那样发生,数据访问和维护将集中完成。

注意:

  • 在上面的情况中,您可能想知道"为什么我们不能引入中央数据访问服务器来与所有应用程序交互?是的。这将是一种可能的替代方案。但是,
  • SP与该方法相比的主要优点是,与具有内联查询的数据访问代码不同,SP是预编译语句,因此它们将更快地执行。通信成本(通过网络)将是最小的。
  • 与此相反,SP将为数据库服务器增加一些负载。如果根据情况需要考虑,那么具有内联查询的集中式数据访问服务器将是更好的选择。

存储过程主要用于在数据库上执行某些任务。例如

  • 从数据的某些业务逻辑中获取数据库结果集。
  • 在一次调用中执行多个数据库操作。
  • 用于将数据从一个表迁移到另一个表。
  • 可以调用其他编程语言,如Java。


存储过程用于检索数据,修改数据和删除数据库表中的数据。每次要在SQL数据库中插入,更新或删除数据时,都不需要编写完整的SQL命令。


存储过程只不过是一组编译成单个执行计划的SQL语句。

  • 创建一次并多次调用它
  • 它减少了网络流量
  • 示例:创建存储过程

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    CREATE PROCEDURE GetEmployee
          @EmployeeID INT = 0
    AS
    BEGIN
          SET NOCOUNT ON;

          SELECT FirstName, LastName, BirthDate, City, Country
          FROM Employees
          WHERE EmployeeID = @EmployeeID
    END
    GO

    更改或修改存储过程:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO

    ALTER PROCEDURE GetEmployee
          @EmployeeID INT = 0
    AS
    BEGIN
        SET NOCOUNT ON;

        SELECT FirstName, LastName, BirthDate, City, Country
        FROM Employees
        WHERE EmployeeID = @EmployeeID
    END
    GO

    删除或删除存储过程:

    1
    DROP PROCEDURE GetEmployee

    • 存储过程是执行某些特定任务的一个或多个SQL语句的预编译集。

    • 应使用EXEC单独执行存储过程

    • 存储过程可以返回多个参数

    • 存储过程可用于实现事务处理


    "什么是存储过程"已在此处的其他帖子中得到解答。我将发布的是一种鲜为人知的使用存储过程的方法。它是grouping stored proceduresnumbering stored procedures

    语法参考

    enter image description here

    ; number就此而言

    An optional integer that is used to group procedures of the same name. These grouped procedures can be dropped together by using one DROP PROCEDURE statement

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    CREATE PROCEDURE FirstTest
    (
        @InputA INT
    )
    AS
    BEGIN
        SELECT 'A' + CONVERT(VARCHAR(10),@InputA)
    END
    GO

    CREATE PROCEDURE FirstTest;2
    (
        @InputA INT,
        @InputB INT
    )
    AS
    BEGIN
        SELECT 'A' + CONVERT(VARCHAR(10),@InputA)+ CONVERT(VARCHAR(10),@InputB)
    END
    GO

    使用

    1
    2
    EXEC FirstTest 10
    EXEC FirstTest;2 20,30

    结果

    enter image description here

    另一种尝试

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    CREATE PROCEDURE SecondTest;2
    (
         @InputA INT,
        @InputB INT
    )
    AS
    BEGIN
        SELECT 'A' + CONVERT(VARCHAR(10),@InputA)+ CONVERT(VARCHAR(10),@InputB)
    END
    GO

    结果

    Msg 2730, Level 11, State 1, Procedure SecondTest, Line 1 [Batch Start Line 3]
    Cannot create procedure 'SecondTest' with a group number of 2 because a procedure with the same name and a group number of 1 does not currently exist in the database.
    Must execute CREATE PROCEDURE 'SecondTest';1 first.

    参考文献:

  • 使用数字语法创建过程
  • SQL Server中编号的存储过程 - techie-friendly.blogspot.com
  • 分组存储过程 - sqlmag
  • 警告

  • 对程序进行分组后,不能单独删除它们。
  • 在将来的Microsoft SQL Server版本中可能会删除此功能。

  • 在DBMS中,存储过程是一组具有指定名称的SQL语句,该名称以编译形式存储在数据库中,以便可以由许多程序共享。

    使用存储过程可能会有所帮助

  • 提供对数据的受控访问(最终用户只能输入或更改数据,但不能编写程序)

  • 确保数据完整性(数据将以一致的方式输入)和

  • 提高工作效率(存储过程的语句只需要编写一次)


  • 在存储过程中,语句仅写入一次,并减少客户端和服务器之间的网络流量。
    我们还可以避免Sql注入攻击。

    • 如果您在申请中使用第三方程序,请注意
      处理付款,这里的数据库应该只公开
      它需要的信息和第三方的活动
      通过授权,我们可以通过设置来实现数据机密性
      使用存储过程的权限。
    • 表的更新应仅对其所针对的表进行
      但它不应该更新我们可以实现的任何其他表
      使用事务处理和错误处理的数据完整性。
    • 如果您想要返回一个或多个具有数据类型的项目,那么它就是
      最好使用输出参数。
    • 在存储过程中,我们使用输出参数
      需要退货。如果您只想返回一个项目
      整数数据类型然后更好地使用返回值。实际上是
      返回值仅用于通知存储的成功或失败
      程序。

    为了简单,

    存储过程是存储程序,存储在数据库中的程序/功能。

    每个存储的程序都包含一个由SQL语句组成的主体。此语句可能是由以分号(;)字符分隔的多个语句组成的复合语句。

    1
    2
    3
    4
    5
    CREATE PROCEDURE dorepeat(p1 INT)
    BEGIN
      SET @x = 0;
      REPEAT SET @x = @x + 1; UNTIL @x > p1 END REPEAT;
    END;

    存储过程是SQL语句和过程逻辑的命名集合,即编译,验证并存储在服务器数据库中。存储过程通常像其他数据库对象一样对待,并通过服务器安全机制进行控制。


    SQL Server中的存储过程可以接受输入参数并返回多个输出参数值;在SQL Server中,存储过程程序语句用于在数据库中执行操作并将状态值返回给调用过程或批处理。

    在SQL Server中使用存储过程的好处

    它们允许模块化编程。
    它们允许更快的执行。
    他们可以减少网络流量。
    它们可以用作安全机制。

    下面是一个存储过程的示例,它接受参数,执行查询并返回结果。具体来说,存储过程接受BusinessEntityID作为参数,并使用它来匹配HumanResources.Employee表的主键以返回请求的员工。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    > CREATE PROCEDURE HumanResources.uspFindEmployee    `*<<<---Store procedure name`*
    @businessEntityID                                     `<<<----parameter`
    AS
    BEGIN
    SET NOCOUNT ON;
    SELECT businessEntityId,              <<<----select statement to return one employee row
    NationalIdNumber,
    LoginID,
    JobTitle,
    HireData,
    FROM HumanResources.Employee
    WHERE businessEntityId =@businessEntityId     <<<---parameter used as criteria
    END

    我从essential.com了解到这一点......它非常有用。


    存储过程将帮助您在服务器中创建代码。您可以传递参数并查找输出。

    1
    2
    3
    CREATE procedure_name (para1 INT,para2 DECIMAL)
    AS
    SELECT * FROM TableName