MySQL lưu thủ tục vs chức năng, tôi sẽ sử dụng khi nào?


160

Tôi đang xem xét các thủ tục và chức năng lưu trữ của MySQL. Sự khác biệt thực sự là gì?

Chúng có vẻ giống nhau, nhưng một chức năng có nhiều hạn chế hơn.

Tôi có thể sai, nhưng có vẻ như một thủ tục được lưu trữ có thể làm mọi thứ và hơn nữa một chức năng được lưu trữ có thể. Tại sao / khi nào tôi sẽ sử dụng thủ tục so với hàm?

Câu trả lời:


101

Bạn không thể trộn các thủ tục được lưu trữ với SQL thông thường, trong khi với chức năng được lưu trữ bạn có thể.

ví dụ SELECT get_foo(myColumn) FROM mytablekhông hợp lệ nếu get_foo()là một thủ tục, nhưng bạn có thể làm điều đó nếu get_foo()là một hàm. Giá là các chức năng có nhiều hạn chế hơn một thủ tục.


18
Những loại hạn chế làm chức năng có?
Fantius

11
À, tôi đã tìm thấy một số thông tin tốt ở đây: dev.mysql.com/doc/refman/5.0/en/ Kẻ
Fantius

262

Sự khác biệt chung nhất giữa các thủ tục và chức năng là chúng được gọi khác nhau và cho các mục đích khác nhau:

  1. Một thủ tục không trả về một giá trị. Thay vào đó, nó được gọi bằng câu lệnh CALL để thực hiện một thao tác như sửa đổi bảng hoặc xử lý các bản ghi đã truy xuất.
  2. Một hàm được gọi trong một biểu thức và trả về một giá trị trực tiếp cho người gọi sẽ được sử dụng trong biểu thức.
  3. Bạn không thể gọi hàm bằng câu lệnh CALL, cũng như không thể gọi thủ tục trong biểu thức.

Cú pháp để tạo thường trình khác nhau một chút cho các thủ tục và chức năng:

  1. Các tham số thủ tục có thể được định nghĩa là chỉ đầu vào, chỉ đầu ra hoặc cả hai. Điều này có nghĩa là một thủ tục có thể chuyển các giá trị trở lại cho người gọi bằng cách sử dụng các tham số đầu ra. Các giá trị này có thể được truy cập trong các câu lệnh tuân theo câu lệnh CALL. Các chức năng chỉ có các tham số đầu vào. Kết quả là, mặc dù cả hai thủ tục và hàm có thể có các tham số, khai báo tham số thủ tục khác với các hàm.
  2. Hàm trả về giá trị, do đó phải có mệnh đề RETURNS trong định nghĩa hàm để chỉ ra kiểu dữ liệu của giá trị trả về. Ngoài ra, phải có ít nhất một câu lệnh RETURN trong thân hàm để trả về giá trị cho người gọi. TRẢ LẠI và TRẢ LẠI không xuất hiện trong định nghĩa thủ tục.

    • Để gọi một thủ tục được lưu trữ, sử dụng CALL statement. Để gọi một hàm được lưu trữ, hãy tham khảo nó trong một biểu thức. Hàm trả về một giá trị trong quá trình đánh giá biểu thức.

    • Một thủ tục được gọi bằng cách sử dụng câu lệnh CALL và chỉ có thể trả lại các giá trị bằng các biến đầu ra. Một hàm có thể được gọi từ bên trong một câu lệnh giống như bất kỳ hàm nào khác (nghĩa là bằng cách gọi tên của hàm) và có thể trả về giá trị vô hướng.

    • Chỉ định tham số là IN, OUT hoặc INOUT chỉ hợp lệ cho THỦ TỤC. Đối với CHỨC NĂNG, các tham số luôn được coi là tham số IN.

    Nếu không có từ khóa nào được đưa ra trước một tên tham số, thì đó là tham số IN theo mặc định. Các tham số cho các chức năng được lưu trữ không đi trước IN, OUT hoặc INOUT. Tất cả các tham số chức năng được coi là tham số IN.

Để xác định một thủ tục hoặc hàm được lưu trữ, hãy sử dụng TẠO QUY TRÌNH hoặc TẠO CHỨC NĂNG tương ứng:

CREATE PROCEDURE proc_name ([parameters])
 [characteristics]
 routine_body


CREATE FUNCTION func_name ([parameters])
 RETURNS data_type       // diffrent
 [characteristics]
 routine_body

Một phần mở rộng MySQL cho thủ tục được lưu trữ (không phải các hàm) là một thủ tục có thể tạo ra một tập kết quả hoặc thậm chí nhiều tập kết quả mà người gọi xử lý theo cách tương tự như kết quả của câu lệnh SELECT. Tuy nhiên, nội dung của các tập kết quả như vậy không thể được sử dụng trực tiếp trong biểu thức.

Các thói quen được lưu trữ (tham khảo cả các thủ tục được lưu trữ và các chức năng được lưu trữ) được liên kết với một cơ sở dữ liệu cụ thể, giống như các bảng hoặc dạng xem. Khi bạn thả cơ sở dữ liệu, mọi thói quen được lưu trữ trong cơ sở dữ liệu cũng sẽ bị hủy.

Các thủ tục và hàm được lưu trữ không chia sẻ cùng một không gian tên. Có thể có một thủ tục và một hàm có cùng tên trong cơ sở dữ liệu.

Trong thủ tục lưu trữ, SQL động có thể được sử dụng nhưng không phải trong các hàm hoặc trình kích hoạt.

Các câu lệnh được chuẩn bị SQL (PREPARE, EXECUTE, DEALLOCATE PREPARE) có thể được sử dụng trong các thủ tục được lưu trữ, nhưng không được lưu trữ các hàm hoặc trình kích hoạt. Do đó, các hàm và trình kích hoạt được lưu trữ không thể sử dụng SQL động (nơi bạn xây dựng các câu lệnh dưới dạng chuỗi và sau đó thực thi chúng). (SQL động trong các thói quen lưu trữ MySQL)

Một số khác biệt thú vị hơn giữa THỦ TỤC CHỨC NĂNG và BẢO QUẢN:

  1. ( Điểm này được sao chép từ một blogpost . ) Thủ tục được lưu trữ được biên dịch trước kế hoạch thực hiện trong khi chức năng thì không. Chức năng Phân tích cú pháp và biên dịch trong thời gian chạy. Thủ tục lưu trữ, Được lưu trữ dưới dạng mã giả trong cơ sở dữ liệu tức là biểu mẫu được biên dịch.

  2. ( Tôi không chắc chắn về điểm này. )
    Thủ tục lưu trữ có bảo mật và giảm lưu lượng mạng và chúng tôi cũng có thể gọi thủ tục được lưu trữ trong bất kỳ không. của các ứng dụng tại một thời điểm. tài liệu tham khảo

  3. Các hàm thường được sử dụng để tính toán trong đó các thủ tục thường được sử dụng để thực hiện logic nghiệp vụ.

  4. Chức năng không thể ảnh hưởng đến trạng thái của cơ sở dữ liệu (báo cáo rằng làm rõ ràng hoặc ngầm cam kết hoặc rollback là không được phép trong chức năng) Trong khi đó, các thủ tục lưu trữ có thể ảnh hưởng đến trạng thái của cơ sở dữ liệu sử dụng cam kết, vv
    refrence: J.1. Hạn chế về các thói quen và kích hoạt được lưu trữ

  5. Các hàm không thể sử dụng các câu lệnh FLUSH trong khi các thủ tục được lưu có thể làm.

  6. Các chức năng được lưu trữ không thể được đệ quy trong khi các thủ tục được lưu trữ có thể được. Lưu ý: Các thủ tục lưu trữ đệ quy bị tắt theo mặc định, nhưng có thể được bật trên máy chủ bằng cách đặt biến hệ thống máy chủ max_sp_recursion_depth thành giá trị khác không. Xem Phần 5.2.3, Hệ thống Biến Biến , để biết thêm thông tin.

  7. Trong một chức năng được lưu trữ hoặc kích hoạt, không được phép sửa đổi một bảng đã được sử dụng (để đọc hoặc viết) bởi câu lệnh đã gọi hàm hoặc kích hoạt. Ví dụ hay: Làm thế nào để cập nhật cùng một bảng về xóa trong MYSQL?

Lưu ý : mặc dù một số hạn chế thường áp dụng cho các chức năng và trình kích hoạt được lưu trữ nhưng không áp dụng cho các quy trình được lưu trữ, những hạn chế đó sẽ áp dụng cho các quy trình được lưu trữ nếu chúng được gọi từ bên trong một chức năng hoặc trình kích hoạt được lưu trữ. Ví dụ: mặc dù bạn có thể sử dụng FLUSH trong một thủ tục được lưu trữ, nhưng một thủ tục được lưu trữ như vậy có thể được gọi từ một hàm hoặc trình kích hoạt được lưu trữ.


2
@GrijeshChauhan, Ý bạn là gì khi bạn nói rằng "Hàm được phân tích cú pháp và được biên dịch khi chạy" ?
Pacerier

@Pacerier có nghĩa là các hàm trong MySQL là một cái gì đó giống như các tập lệnh biên dịch và thực thi nhanh chóng. Tôi đã sao chép nó từ một số bài đăng trên blog , nhưng không thực hiện bất kỳ thực tế nào để kiểm tra hành vi này.
Grijesh Chauhan

Trong các thủ tục, bạn có thể truyền một biến ra làm tham số, sau đó gọi nó bằng một câu lệnh chọn
LTroya 7/07/2016

1
gạch đầu dòng số 4 trong phần dưới cùng của câu trả lời này, theo tôi, cốt lõi của sự khác biệt giữa các thủ tục và chức năng. thủ tục có thể thay đổi cơ sở dữ liệu, chức năng không thể. tất cả những khác biệt khác chỉ là để phục vụ mục đích đó hiệu quả hơn.
Woodrow Barlow

51

Một sự khác biệt đáng kể là bạn có thể bao gồm một hàm trong các truy vấn SQL của mình, nhưng các thủ tục được lưu trữ chỉ có thể được gọi với CALLcâu lệnh:

Ví dụ UDF:

CREATE FUNCTION hello (s CHAR(20))
   RETURNS CHAR(50) DETERMINISTIC
   RETURN CONCAT('Hello, ',s,'!');
Query OK, 0 rows affected (0.00 sec)

CREATE TABLE names (id int, name varchar(20));
INSERT INTO names VALUES (1, 'Bob');
INSERT INTO names VALUES (2, 'John');
INSERT INTO names VALUES (3, 'Paul');

SELECT hello(name) FROM names;
+--------------+
| hello(name)  |
+--------------+
| Hello, Bob!  |
| Hello, John! |
| Hello, Paul! |
+--------------+
3 rows in set (0.00 sec)

Ví dụ về Sproc:

delimiter //

CREATE PROCEDURE simpleproc (IN s CHAR(100))
BEGIN
   SELECT CONCAT('Hello, ', s, '!');
END//
Query OK, 0 rows affected (0.00 sec)

delimiter ;

CALL simpleproc('World');
+---------------------------+
| CONCAT('Hello, ', s, '!') |
+---------------------------+
| Hello, World!             |
+---------------------------+
1 row in set (0.00 sec)

1
Chức năng của bạn có hai lợi nhuận ? Ý tôi là dòng này là gì? RETURNS CHAR(50) DETERMINISTIC?
Martin AJ

Các RETURNS CHAR(50)tiểu bang loại dữ liệu sẽ được trả lại. Các RETURN CONCAT(...dữ liệu đang được trả lại. Cả hai đều cần thiết. Điều DETERMINISTICcần thiết là để nói rằng dữ liệu cơ bản sẽ không được sửa đổi.
lemming622

8

Một chức năng được lưu trữ có thể được sử dụng trong một truy vấn. Sau đó, bạn có thể áp dụng nó cho mọi hàng hoặc trong mệnh đề WHERE.

Một thủ tục được thực hiện bằng truy vấn CALL.


0

Thủ tục lưu trữ có thể được gọi đệ quy nhưng chức năng lưu trữ không thể

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.