資料庫儲存過程和SQL PSM


儲存過程對於資料庫管理系統 (DBMS) 至關重要,因為它們可以提高安全性、提升效能並促進程式碼重用。儲存過程是預編譯的資料庫物件,包含一組 SQL 語句。它們儲存在資料庫中,可以被應用程式或其他資料庫物件呼叫。在這篇文章中,我們將深入探討 SQL 持久儲存模組 (PSM) 的細節,這是一種 SQL 的過程化程式語言擴充套件,並考察儲存過程的概念。

瞭解儲存過程

儲存過程是預編譯並存儲在資料庫中的資料庫物件,包含一組 SQL 語句。它們儲存在資料庫中,可以被應用程式或其他資料庫物件呼叫。讓我們來看一個簡單的 SQL Server 儲存過程示例:

CREATE PROCEDURE GetEmployeeById
    @EmployeeId INT
AS
BEGIN
    SELECT * FROM Employees WHERE EmployeeId = @EmployeeId
END

輸入表 - 員工

+------------+--------------+------------+
| EmployeeId | EmployeeName | Department |
+------------+--------------+------------+
| 1          | John Doe     | HR         |
| 2          | Jane Smith   | IT         |
| 3          | Mike Johnson | Sales      |
| 4          | Sarah Adams  | Marketing  |
| 5          | Robert Brown | Finance    |
| 6          | Lisa Davis   | HR         |
| 7          | David Wilson | IT         |
| 8          | Emily Lee    | Sales      |
| 9          | Michael Chen | Marketing  |
| 10         | Olivia Clark | Finance    |
+------------+--------------+------------+

以上程式碼定義了名為 "GetEmployeeById" 的儲存過程,它接受輸入引數 @Employee Id。該過程根據提供的 Employee Id 從 "Employees" 表中提取員工資訊。

可以使用以下程式碼來執行儲存過程:

EXEC GetEmployeeById @EmployeeId = 1

輸出表

+------------+--------------+------------+
| EmployeeId | EmployeeName | Department |
+------------+--------------+------------+
| 1          | John Doe     | HR         |
+------------+--------------+------------+

這將使用 Employee Id 等於 1 來執行儲存過程並獲取員工資訊。

使用儲存過程的好處

  • 效能提升 − 儲存過程是預編譯的,並以編譯形式儲存在資料庫中,從而減少了與解析和編譯相關的開銷。與動態生成的 SQL 語句相比,這導致更快的執行速度。

  • 程式碼重用性 − 儲存過程鼓勵模組化程式設計和程式碼重用。它們可以從多個程式或其他儲存過程中呼叫,從而減少重複並促進一致性。

  • 安全性 − 儲存過程提供額外的安全層,允許在過程級別進行訪問控制。應用程式可以被授權執行特定的操作,同時限制對錶的直接訪問。

  • 資料完整性 − 將複雜的資料修改演算法封裝到儲存過程中可以更有效地確保資料完整性。由於邏輯包含在資料庫中,因此可以提供可靠且一致的結果。

向 SQL 新增過程化功能 (SQL PSM)

SQL 持久儲存模組 (PSM) 是 SQL 過程化程式語言的擴充套件。它允許開發人員在資料庫中建立函式和過程,從而實現高階資料處理和操作。讓我們透過一些實際示例來探討 SQL PSM 的一些主要特性。

  • 過程化結構

  • 過程特定標記語言 (PSM) 提供了過程化構造,包括條件語句 (IF、CASE)、迴圈 (WHILE、FOR) 和異常處理 (TRY-CATCH)。請檢視以下示例,瞭解如何在 PSM 中使用條件語句:

示例

CREATE PROCEDURE GetEmployeeSalaryRange
    @MinSalary DECIMAL(10,2),
    @MaxSalary DECIMAL(10,2)
AS
BEGIN
    IF @MinSalary <= @MaxSalary
    BEGIN
        SELECT * FROM Employees WHERE Salary BETWEEN @MinSalary AND @MaxSalary
    END
    ELSE
    BEGIN
        RAISERROR('Invalid salary range.', 16, 1)
    END
END

輸入表 - 員工

| EmployeeId | EmployeeName | Salary    |
|------------|--------------|-----------|
| 1          | John Doe     | 50000.00  |
| 2          | Jane Smith   | 65000.00  |
| 3          | Mike Johnson | 75000.00  |
| 4          | Lisa Davis   | 45000.00  |
| 5          | Mark Wilson  | 80000.00  |
| 6          | Sarah Brown  | 55000.00  |
| 7          | Alex Lee     | 60000.00  |
| 8          | Emily Clark  | 70000.00  |
| 9          | David Jones  | 40000.00  |
| 10         | Olivia Smith | 90000.00  |

輸出表

結果假設過程 GetEmployeeSalaryRange 被呼叫,輸入引數 @MinSalary = 50000.00 和 @MaxSalary = 70000.00。

| EmployeeId | EmployeeName | Salary    |
|------------|--------------|-----------|
| 1          | John Doe     | 50000.00  |
| 2          | Jane Smith   | 65000.00  |
| 3          | Mike Johnson | 75000.00  |
| 6          | Sarah Brown  | 55000.00  |
| 7          | Alex Lee     | 60000.00  |
| 8          | Emily Clark  | 70000.00  |

此程式碼中的儲存過程 "GetEmployeeSalaryRange" 接受輸入引數 @MinSalary 和 @MaxSalary。它使用 IF 語句有條件地檢索薪資在指定範圍內的員工。如果 @MinSalary 高於 @MaxSalary,則 RAISERROR 語句會引發錯誤。

  • 變數支援

  • PSM 允許定義和使用變數,這些變數可以儲存輸入/輸出值或用於儲存中間結果。讓我們來看一個儲存過程使用變數執行計算的示例:

CREATE PROCEDURE CalculateTotalSalary
    @EmployeeId INT,
    @BonusPercentage DECIMAL(5,2) OUTPUT,
    @TotalSalary DECIMAL(10,2) OUTPUT
AS
BEGIN
    DECLARE @BaseSalary DECIMAL(10,2)

    SELECT @BaseSalary = Salary FROM Employees WHERE EmployeeId = @EmployeeId
    SET @BonusPercentage = 0.1
    SET @TotalSalary = @BaseSalary + (@BaseSalary * @BonusPercentage)
END

此程式碼中的儲存過程 "CalculateTotalSalary" 透過將基本工資乘以獎金百分比來計算員工的總工資。它使用輸入引數 @Employee Id 從 "Employees" 表中檢索員工的基本工資。計算出的獎金百分比和總工資分別儲存在輸出引數 @Bonus Percentage 和 '@Total Salary' 中。

我們可以使用以下程式碼來執行儲存過程並獲取計算值:

DECLARE @Bonus DECIMAL(5,2)
DECLARE @Total DECIMAL(10,2)

EXEC CalculateTotalSalary @EmployeeId = 1, @BonusPercentage = @Bonus OUTPUT, @TotalSalary = @Total OUTPUT

SELECT @Bonus AS BonusPercentage, @Total AS TotalSalary

輸入表 - 員工

| EmployeeId | Salary  |
|------------|---------|
| 1          | 5000.00 |
| 2          | 6000.00 |
| 3          | 4500.00 |
| 4          | 7000.00 |
| 5          | 5500.00 |
| 6          | 8000.00 |
| 7          | 4000.00 |
| 8          | 6500.00 |
| 9          | 7500.00 |
| 10         | 5200.00 |

輸出表

| EmployeeId | BonusPercentage | TotalSalary |
|------------|-----------------|-------------|
| 1          | 0.10            | 5500.00     |
| 2          | 0.10            | 6600.00     |
| 3          | 0.10            | 4950.00     |
| 4          | 0.10            | 7700.00     |
| 5          | 0.10            | 6050.00     |
| 6          | 0.10            | 8800.00     |
| 7          | 0.10            | 4400.00     |
| 8          | 0.10            | 7150.00     |
| 9          | 0.10            | 8250.00     |
| 10         | 0.10            | 5720.00     |


  • 錯誤處理

  • PSM 中的 TRY-CATCH 構造提供了可靠的錯誤處理機制。讓我們來看一個如何在儲存過程中使用 TRY-CATCH 來處理錯誤的示例:

CREATE PROCEDURE DivideNumbers
    @Dividend INT,
    @Divisor INT
AS
BEGIN
    BEGIN TRY
        SELECT @Dividend / @Divisor AS Result
    END TRY
    BEGIN CATCH
        SELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage
    END CATCH
END

此程式碼中的儲存過程 "Divide Numbers" 執行兩個數字 @Dividend 和 @Divisor 的除法。它在 TRY 塊中嘗試除法,如果發生錯誤,則啟用 CATCH 塊,使用 ERROR_NUMBER() 和 ERROR_MESSAGE() 函式檢索和顯示錯誤資訊。

輸入表 - 員工

+----------+---------+
| Dividend | Divisor |
+----------+---------+
|    10    |    2    |
|    20    |    4    |
|    15    |    3    |
|    30    |    5    |
|    12    |    4    |
|    18    |    6    |
|    25    |    5    |
|    16    |    2    |
|    35    |    7    |
|    40    |    8    |
+----------+---------+

可以使用以下程式碼來執行儲存過程並處理任何錯誤:

EXEC DivideNumbers @Dividend = 10, @Divisor = 0

輸出表

+--------------+---------------------------------+
| ErrorNumber  |         ErrorMessage           |
+--------------+---------------------------------+
|    8134      |  Divide by zero error encountered. |
+--------------+---------------------------------+

這將導致除以零錯誤,並且 CATCH 塊將被啟用以顯示錯誤號和訊息。

  • 函式定義 − SQL 持久儲存模組 (PSM) 允許在資料庫中定義函式。函式是可以重用的程式碼塊,它們接受輸入引數,執行某些操作並返回單個值。它們可以像任何其他 SQL 表示式一樣在 SQL 查詢中使用。以下是如何在 SQL PSM 中定義函式的示例:

CREATE FUNCTION GetEmployeeCountByDepartment(departmentId INT)
    RETURNS INT
BEGIN
    DECLARE @Count INT

    SELECT @Count = COUNT(*) FROM Employees WHERE DepartmentId = departmentId

    RETURN @Count
END

以上程式碼定義了名為 "GetEmployeeCountByDepartment" 的函式,它接受輸入引數 departmentId。該函式計算指定部門中的員工數量,並返回一個整數結果。

輸入表 - 員工

+------------+--------------+--------------+
| EmployeeId | EmployeeName | DepartmentId |
+------------+--------------+--------------+
|     1      |   John Doe   |      1       |
|     2      |  Jane Smith  |      1       |
|     3      | Mark Johnson |      2       |
|     4      |  Emily Brown |      3       |
|     5      |  Alex Wilson |      2       |
|     6      |  Sarah Davis |      1       |
|     7      | Mike Thompson|      3       |
|     8      |   Emma Lee   |      2       |
|     9      | James Miller |      1       |
|    10      | Lily Anderson|      3       |
+------------+--------------+--------------+

部門表

+--------------+----------------+
| DepartmentId | DepartmentName |
+--------------+----------------+
|      1       |    Sales       |
|      2       |   Marketing    |
|      3       |    Finance     |
|      4       |      HR        |
|      5       |      IT        |
+--------------+----------------+

可以使用以下程式碼在 SQL 查詢中使用此函式:

SELECT DepartmentId, GetEmployeeCountByDepartment(DepartmentId) AS EmployeeCount
FROM Departments

輸出表

+--------------+---------------+
| DepartmentId | EmployeeCount |
+--------------+---------------+
|      1       |       4       |
|      2       |       3       |
|      3       |       2       |
|      4       |       0       |
|      5       |       0       |
+--------------+---------------+

此查詢從 "Departments" 資料庫中檢索部門 ID,然後對每個部門執行 "Get Employee Count By Department" 函式以獲取相應的員工數量。

SQL PSM 的好處

使用 SQL PSM 在資料庫開發中有很多優勢。

  • 增強功能 − 透過包含過程化結構和變數支援,PSM 擴充套件了 SQL 的功能。這允許開發人員直接在資料庫中執行復雜的業務邏輯和資料轉換,從而消除了將資料傳輸和處理到 DBMS 之外的必要性。

  • 效能提升 − PSM 透過在資料庫中直接執行邏輯來減少資料庫和外部應用程式之間傳輸資料的開銷。這減少了網路延遲並提高了效能。

  • 程式碼重用性和可維護性 − 透過將邏輯封裝在過程和函式中,PSM 鼓勵程式碼重用。開發人員可以建立可供其他應用程式使用的模組化程式碼,從而減少重複並提高可維護性。

  • 資料完整性和安全性 − PSM 透過將資料處理和操作邏輯包含在資料庫中來確保資料一致性和完整性。PSM 還提供細粒度的訪問控制,透過限制對錶的直接訪問並僅嚮應用程式公開必要的過程來提高安全性。

結論

總之,SQL PSM 和儲存過程是強大的工具,可以提高資料庫系統的可用性、可靠性、安全性以及資料完整性。開發人員可以透過利用這些功能來提高應用程式的速度、最佳化程式碼並確保在資料庫中執行可靠且安全的資料操作。無論是管理複雜的資料轉換還是執行業務規則,儲存過程和 SQL PSM 都為高效且可靠的資料庫開發提供了堅實的基礎。

更新於: 2023年8月2日

1K+ 瀏覽量

開啟您的職業生涯

完成課程並獲得認證

立即開始
廣告