Hướng dẫn mysql fetch cursor - con trỏ tìm nạp mysql

13.6.6 Cursors

MySQL supports cursors inside stored programs. The syntax is as in embedded SQL. Cursors have these properties:

  • Asensitive: The server may or may not make a copy of its result table

  • Read only: Not updatable

  • Nonscrollable: Can be traversed only in one direction and cannot skip rows

Cursor declarations must appear before handler declarations and after variable and condition declarations.

Example:

CREATE PROCEDURE curdemo()
BEGIN
  DECLARE done INT DEFAULT FALSE;
  DECLARE a CHAR(16);
  DECLARE b, c INT;
  DECLARE cur1 CURSOR FOR SELECT id,data FROM test.t1;
  DECLARE cur2 CURSOR FOR SELECT i FROM test.t2;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

  OPEN cur1;
  OPEN cur2;

  read_loop: LOOP
    FETCH cur1 INTO a, b;
    FETCH cur2 INTO c;
    IF done THEN
      LEAVE read_loop;
    END IF;
    IF b < c THEN
      INSERT INTO test.t3 VALUES (a,b);
    ELSE
      INSERT INTO test.t3 VALUES (a,c);
    END IF;
  END LOOP;

  CLOSE cur1;
  CLOSE cur2;
END;


Nội dung chính ShowShow

  • 13.6.6 Cursors
  • Khai báo và sử dụng Cursor
  • Tóm tắt lại các câu lệnh
  • 1- Bắt đầu với MySQL Workbench
  • 2- Hàm (Function)
  • 3- Thủ tục (Procedure)
  • 4- Các lệnh cơ bản
  • 4.1- Câu Lệnh rẽ nhánh If-elsif-else
  • 4.2- Câu lệnh rẽ nhánh CASE
  • 4.3- Vòng lặp không định trước (LOOP)
  • 4.4- Vòng lặp REPEAT .. UNTIL
  • 4.5- Vòng lặp WHILE .. DO
  • 5- Điều khiển ngoại lệ
  • 5.1- Ví dụ bắt đầu với ngoại lệ
  • 5.2- Định nghĩa điều khiển ngoại lệ
  • 5.3- Chuẩn đoán lỗi (Get DIAGNOSTICS)
  • 6- Con trỏ (Cursor)
  • 6.1- Con trỏ là gì?
  • 6.2- Ví dụ với Con trỏ

13.6.6 Cursors

Nội dung chính Show

  • Khai báo và sử dụng Cursor

  • Tóm tắt lại các câu lệnh

  • 1- Bắt đầu với MySQL Workbench

2- Hàm (Function)

3- Thủ tục (Procedure)

4- Các lệnh cơ bản

Khai báo và sử dụng Cursor

4.1- Câu Lệnh rẽ nhánh If-elsif-else

4.2- Câu lệnh rẽ nhánh CASE

4.3- Vòng lặp không định trước (LOOP)

4.4- Vòng lặp REPEAT .. UNTIL khai báo con trỏ, trỏ đến một tập dữ liệu (kết quả của

Open cursorProduct
6) bằng lệnh
Open cursorProduct
7

4.5- Vòng lặp WHILE .. DO

SELECT id,name FROM Product

5- Điều khiển ngoại lệ

5.1- Ví dụ bắt đầu với ngoại lệ

5.2- Định nghĩa điều khiển ngoại lệ Khi bắt đầu quá trình đọc các dòng dữ liệu từ Cursor trên, thì phải mở con trỏ, thực hiện như sau:

Open cursorProduct

MySQL supports cursors inside stored programs. The syntax is as in embedded SQL. Cursors have these properties: Cursor được mở, con trỏ sẽ trỏ tới dòng đầu tiên của tập dữ liệu, lúc này có thể đọc nội dung dòng đó bằng lệnh

Open cursorProduct
9

Asensitive: The server may or may not make a copy of its result table Đọc dữ liệu sử dụng lệnh như sau:

FETCH NEXT FROM cursorProduct INTO @id, @title

Read only: Not updatable

Nonscrollable: Can be traversed only in one direction and cannot skip rows

Cursor declarations must appear before handler declarations and after variable and condition declarations.

WHILE @@FETCH_STATUS = 0
BEGIN
    PRINT 'ID:' + CAST(@id as nvarchar)
    PRINT 'TITLE:' @title

    FETCH NEXT FROM cursorProduct INTO @it, @title
END

Example: sau khi không còn dùng đến Cursor, cần đóng lại và giải phóng các tài nguyên nó chiếm giữ

CLOSE cursorProduct
DEALLOCATE cursorProduct

Tóm tắt lại các câu lệnh

1- Bắt đầu với MySQL Workbench

    
--Khai báo biến @id, @title để lưu nội dung đọc
DECLARE @id int
DECLARE @title nvarchar(200)


DECLARE cursorProduct CURSOR FOR  -- khai báo con trỏ cursorProduct
SELECT id, title FROM Product     -- dữ liệu trỏ tới

OPEN cursorProduct                -- Mở con trỏ

FETCH NEXT FROM cursorProduct     -- Đọc dòng đầu tiên
      INTO @id, @title

WHILE @@FETCH_STATUS = 0          --vòng lặp WHILE khi đọc Cursor thành công
BEGIN
                                  --In kết quả hoặc thực hiện bất kỳ truy vấn
                                  --nào dựa trên kết quả đọc được
    PRINT 'ID:' + CAST(@id as nvarchar)
    PRINT 'TITLE:' @title

    FETCH NEXT FROM cursorProduct -- Đọc dòng tiếp
          INTO @id, @title
END

CLOSE cursorProduct              -- Đóng Cursor
DEALLOCATE cursorProduct         -- Giải phóng tài nguyên

2- Hàm (Function)
Là một website được viết trên công nghệ web Flutter vì vậy hỗ trợ rất tốt cho người học, kể cả những người học khó tính nhất.
Hiện tại website đang tiếp tục được cập nhập nội dung cho phong phú và đầy đủ hơn. Mong các bạn nghé thăm và ủng hộ website mới của chúng tôi.

3- Thủ tục (Procedure)

4- Các lệnh cơ bản

4.1- Câu Lệnh rẽ nhánh If-elsif-else

1- Bắt đầu với MySQL Workbench

2- Hàm (Function) MySQL trên công cụ trực quan MySQL Workbench. Nếu bạn sử dụng một công cụ trực quan khác để viết code thì cũng không có nhiều khác biệt gì cả.

Đây là hình ảnh MySQL Workbench trong khi bạn mới mở nó. Click vào vùng khoanh đỏ để chọn SCHEMA bạn muốn làm việc. MySQL Workbench trong khi bạn mới mở nó. Click vào vùng khoanh đỏ để chọn SCHEMA bạn muốn làm việc.

Có một số SCHEMA ví dụ có sẵn khi bạn cài đầy đủ phiên bản MySQL Community. SCHEMA ví dụ có sẵn khi bạn cài đầy đủ phiên bản MySQL Community.

Hoặc bạn có thể tạo SCHEMA learningsql, một SCHEMA ví dụ, được sử dụng trong một vài tài liệu hướng dẫn MySQL trên o7planning.org.  learningsql, một SCHEMA ví dụ, được sử dụng trong một vài tài liệu hướng dẫn MySQL trên o7planning.org

Nhấn phải chuột vào một SCHEMA, chọn "Set as Default Schema" để làm việc với schema này. SCHEMA, chọn "Set as Default Schema" để làm việc với schema này.

Nhấn vào biểu tượng tạo mới một cửa sổ SQL để viết code (1). Nhấn vào vùng khoanh tròn (2) để ẩn một số cửa sổ không cần thiết. SQL để viết code (1). Nhấn vào vùng khoanh tròn (2) để ẩn một số cửa sổ không cần thiết.

2- Hàm (Function)

Giống như thủ tục, hàm (function) là nhóm các lệnh PL/SQL thực hiện chức năng nào đó. Khác với thủ tục, các hàm sẽ trả về một giá trị ngay tại lời gọi của nó. Hàm cũng có thể được lưu giữ ngay trên database dưới dạng Store procedure. function) là nhóm các lệnh PL/SQL thực hiện chức năng nào đó. Khác với thủ tục, các hàm sẽ trả về một giá trị ngay tại lời gọi của nó.
Hàm cũng có thể được lưu giữ ngay trên database dưới dạng Store procedure.

Cú pháp tạo Hàm.


-- function_name:  Tên hàm
-- argument:  Tên tham số
-- mode:  IN hoặc không cần viết.
-- datatype:  Kiểu dữ liệu của tham số

CREATE FUNCTION <function_name>
            (
               [
                [mode1] argument1 datatype1,
                [mode2] argument2  datatype2,
                ...
                ]
             )
            RETURNS  datatype
BEGIN
  -- Khai báo biến sử dụng
  -- Code nội dung của hàm
  -- Trả về giá trị của hàm.
END;

Ví dụ:

CREATE PROCEDURE curdemo()
BEGIN
  DECLARE done INT DEFAULT FALSE;
  DECLARE a CHAR(16);
  DECLARE b, c INT;
  DECLARE cur1 CURSOR FOR SELECT id,data FROM test.t1;
  DECLARE cur2 CURSOR FOR SELECT i FROM test.t2;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

  OPEN cur1;
  OPEN cur2;

  read_loop: LOOP
    FETCH cur1 INTO a, b;
    FETCH cur2 INTO c;
    IF done THEN
      LEAVE read_loop;
    END IF;
    IF b < c THEN
      INSERT INTO test.t3 VALUES (a,b);
    ELSE
      INSERT INTO test.t3 VALUES (a,c);
    END IF;
  END LOOP;

  CLOSE cur1;
  CLOSE cur2;
END;
0

Hủy Function (Drop function):

CREATE PROCEDURE curdemo()
BEGIN
  DECLARE done INT DEFAULT FALSE;
  DECLARE a CHAR(16);
  DECLARE b, c INT;
  DECLARE cur1 CURSOR FOR SELECT id,data FROM test.t1;
  DECLARE cur2 CURSOR FOR SELECT i FROM test.t2;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

  OPEN cur1;
  OPEN cur2;

  read_loop: LOOP
    FETCH cur1 INTO a, b;
    FETCH cur2 INTO c;
    IF done THEN
      LEAVE read_loop;
    END IF;
    IF b < c THEN
      INSERT INTO test.t3 VALUES (a,b);
    ELSE
      INSERT INTO test.t3 VALUES (a,c);
    END IF;
  END LOOP;

  CLOSE cur1;
  CLOSE cur2;
END;
1

Gọi hàm.

CREATE PROCEDURE curdemo()
BEGIN
  DECLARE done INT DEFAULT FALSE;
  DECLARE a CHAR(16);
  DECLARE b, c INT;
  DECLARE cur1 CURSOR FOR SELECT id,data FROM test.t1;
  DECLARE cur2 CURSOR FOR SELECT i FROM test.t2;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

  OPEN cur1;
  OPEN cur2;

  read_loop: LOOP
    FETCH cur1 INTO a, b;
    FETCH cur2 INTO c;
    IF done THEN
      LEAVE read_loop;
    END IF;
    IF b < c THEN
      INSERT INTO test.t3 VALUES (a,b);
    ELSE
      INSERT INTO test.t3 VALUES (a,c);
    END IF;
  END LOOP;

  CLOSE cur1;
  CLOSE cur2;
END;
2

Ví dụ tạo một hàm.

Đây là một ví dụ tạo một hàm đầu tiên của bạn với MySQL:

  1. Tạo một hàm (Function)
  2. Biên dịch hàm này
  3. Chạy hàm

Nếu bạn mới bắt đầu với hàm và thủ tục MySQL bạn hãy xem chi tiết mục này, nó sẽ giúp bạn dễ dàng hiểu các vấn đề tiếp theo được đề cập trong tài liệu. MySQL bạn hãy xem chi tiết mục này, nó sẽ giúp bạn dễ dàng hiểu các vấn đề tiếp theo được đề cập trong tài liệu.

CREATE PROCEDURE curdemo()
BEGIN
  DECLARE done INT DEFAULT FALSE;
  DECLARE a CHAR(16);
  DECLARE b, c INT;
  DECLARE cur1 CURSOR FOR SELECT id,data FROM test.t1;
  DECLARE cur2 CURSOR FOR SELECT i FROM test.t2;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

  OPEN cur1;
  OPEN cur2;

  read_loop: LOOP
    FETCH cur1 INTO a, b;
    FETCH cur2 INTO c;
    IF done THEN
      LEAVE read_loop;
    END IF;
    IF b < c THEN
      INSERT INTO test.t3 VALUES (a,b);
    ELSE
      INSERT INTO test.t3 VALUES (a,c);
    END IF;
  END LOOP;

  CLOSE cur1;
  CLOSE cur2;
END;
3

Nhấn biểu tượng   để biên dịch hàm.

Các hàm có thể tham gia vào trong câu lệnh SELECT. SELECT.

CREATE PROCEDURE curdemo()
BEGIN
  DECLARE done INT DEFAULT FALSE;
  DECLARE a CHAR(16);
  DECLARE b, c INT;
  DECLARE cur1 CURSOR FOR SELECT id,data FROM test.t1;
  DECLARE cur2 CURSOR FOR SELECT i FROM test.t2;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

  OPEN cur1;
  OPEN cur2;

  read_loop: LOOP
    FETCH cur1 INTO a, b;
    FETCH cur2 INTO c;
    IF done THEN
      LEAVE read_loop;
    END IF;
    IF b < c THEN
      INSERT INTO test.t3 VALUES (a,b);
    ELSE
      INSERT INTO test.t3 VALUES (a,c);
    END IF;
  END LOOP;

  CLOSE cur1;
  CLOSE cur2;
END;
4

Kết quả chạy câu lệnh SQL trên:

3- Thủ tục (Procedure)

Một nhóm các lệnh thực hiện chức năng nào đó có thể được gom lại trong một thủ tục (procedure) nhằm làm tăng khả năng xử lý,khả năng sử dụng chung,tăng tính bảo mật và an toàn dữ liệu,tiện ích trong phát triển. Thủ tục có thể được lưu giữ ngay trong database như một đối tượng của database, sẵn sàng cho việc tái sử dụng. Thủ tục lúc này được gọi là Store procedure. Với các Store procedure, ngay khi lưu giữ Store procedure, chúng đã được biên dịch thành dạng p-code vì thế có thể nâng cao khả năng thực hiện.
Thủ tục có thể được lưu giữ ngay trong database như một đối tượng của database, sẵn sàng cho việc tái sử dụng. Thủ tục lúc này được gọi là Store procedure. Với các Store procedure, ngay khi lưu giữ Store procedure, chúng đã được biên dịch thành dạng p-code vì thế có thể nâng cao khả năng thực hiện.

Thủ tục không trả về giá trị trực tiếp như hàm. Nhưng nó có thể có không hoặc nhiều tham số đầu ra.

Cú pháp tạo một thủ tục:

CREATE PROCEDURE curdemo()
BEGIN
  DECLARE done INT DEFAULT FALSE;
  DECLARE a CHAR(16);
  DECLARE b, c INT;
  DECLARE cur1 CURSOR FOR SELECT id,data FROM test.t1;
  DECLARE cur2 CURSOR FOR SELECT i FROM test.t2;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

  OPEN cur1;
  OPEN cur2;

  read_loop: LOOP
    FETCH cur1 INTO a, b;
    FETCH cur2 INTO c;
    IF done THEN
      LEAVE read_loop;
    END IF;
    IF b < c THEN
      INSERT INTO test.t3 VALUES (a,b);
    ELSE
      INSERT INTO test.t3 VALUES (a,c);
    END IF;
  END LOOP;

  CLOSE cur1;
  CLOSE cur2;
END;
5

Ví dụ:

CREATE PROCEDURE curdemo()
BEGIN
  DECLARE done INT DEFAULT FALSE;
  DECLARE a CHAR(16);
  DECLARE b, c INT;
  DECLARE cur1 CURSOR FOR SELECT id,data FROM test.t1;
  DECLARE cur2 CURSOR FOR SELECT i FROM test.t2;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

  OPEN cur1;
  OPEN cur2;

  read_loop: LOOP
    FETCH cur1 INTO a, b;
    FETCH cur2 INTO c;
    IF done THEN
      LEAVE read_loop;
    END IF;
    IF b < c THEN
      INSERT INTO test.t3 VALUES (a,b);
    ELSE
      INSERT INTO test.t3 VALUES (a,c);
    END IF;
  END LOOP;

  CLOSE cur1;
  CLOSE cur2;
END;
6

Hủy Function (Drop function):

Gọi hàm.

Ví dụ tạo một hàm.

Đây là một ví dụ tạo một hàm đầu tiên của bạn với MySQL:

Tạo một hàm (Function)

Get_Employee_Infos

CREATE PROCEDURE curdemo()
BEGIN
  DECLARE done INT DEFAULT FALSE;
  DECLARE a CHAR(16);
  DECLARE b, c INT;
  DECLARE cur1 CURSOR FOR SELECT id,data FROM test.t1;
  DECLARE cur2 CURSOR FOR SELECT i FROM test.t2;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

  OPEN cur1;
  OPEN cur2;

  read_loop: LOOP
    FETCH cur1 INTO a, b;
    FETCH cur2 INTO c;
    IF done THEN
      LEAVE read_loop;
    END IF;
    IF b < c THEN
      INSERT INTO test.t3 VALUES (a,b);
    ELSE
      INSERT INTO test.t3 VALUES (a,c);
    END IF;
  END LOOP;

  CLOSE cur1;
  CLOSE cur2;
END;
8

Biên dịch hàm này

Chạy hàm

Nếu bạn mới bắt đầu với hàm và thủ tục MySQL bạn hãy xem chi tiết mục này, nó sẽ giúp bạn dễ dàng hiểu các vấn đề tiếp theo được đề cập trong tài liệu.

CREATE PROCEDURE curdemo()
BEGIN
  DECLARE done INT DEFAULT FALSE;
  DECLARE a CHAR(16);
  DECLARE b, c INT;
  DECLARE cur1 CURSOR FOR SELECT id,data FROM test.t1;
  DECLARE cur2 CURSOR FOR SELECT i FROM test.t2;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

  OPEN cur1;
  OPEN cur2;

  read_loop: LOOP
    FETCH cur1 INTO a, b;
    FETCH cur2 INTO c;
    IF done THEN
      LEAVE read_loop;
    END IF;
    IF b < c THEN
      INSERT INTO test.t3 VALUES (a,b);
    ELSE
      INSERT INTO test.t3 VALUES (a,c);
    END IF;
  END LOOP;

  CLOSE cur1;
  CLOSE cur2;
END;
9

Nhấn biểu tượng   để biên dịch hàm. @variable_name để lưu trữ các tham số đầu ra.

Các hàm có thể tham gia vào trong câu lệnh SELECT.

Kết quả chạy câu lệnh SQL trên: PL/SQL. Bạn sẽ hiểu hơn về nó thông qua các ví dụ ở các phần tiếp theo.

3- Thủ tục (Procedure)

Một nhóm các lệnh thực hiện chức năng nào đó có thể được gom lại trong một thủ tục (procedure) nhằm làm tăng khả năng xử lý,khả năng sử dụng chung,tăng tính bảo mật và an toàn dữ liệu,tiện ích trong phát triển. Thủ tục có thể được lưu giữ ngay trong database như một đối tượng của database, sẵn sàng cho việc tái sử dụng. Thủ tục lúc này được gọi là Store procedure. Với các Store procedure, ngay khi lưu giữ Store procedure, chúng đã được biên dịch thành dạng p-code vì thế có thể nâng cao khả năng thực hiện.

SELECT id,name FROM Product
0

Ví dụ:

SELECT id,name FROM Product
1

Else_If_Example

SELECT id,name FROM Product
2

Hủy Function (Drop function):

Gọi hàm.

Ví dụ tạo một hàm.

SELECT id,name FROM Product
3

Case_When_Example1

SELECT id,name FROM Product
4

Case_When_Example2

SELECT id,name FROM Product
5

Đây là một ví dụ tạo một hàm đầu tiên của bạn với MySQL:

Một nhóm các lệnh thực hiện chức năng nào đó có thể được gom lại trong một thủ tục (procedure) nhằm làm tăng khả năng xử lý,khả năng sử dụng chung,tăng tính bảo mật và an toàn dữ liệu,tiện ích trong phát triển. Thủ tục có thể được lưu giữ ngay trong database như một đối tượng của database, sẵn sàng cho việc tái sử dụng. Thủ tục lúc này được gọi là Store procedure. Với các Store procedure, ngay khi lưu giữ Store procedure, chúng đã được biên dịch thành dạng p-code vì thế có thể nâng cao khả năng thực hiện.

SELECT id,name FROM Product
6

Thủ tục không trả về giá trị trực tiếp như hàm. Nhưng nó có thể có không hoặc nhiều tham số đầu ra.
Sử dụng lệnh ITERATE để bỏ qua các dòng lệnh trong khối LOOP và ở bên dưới nó, để tiếp tục một vòng lặp mới.

Cú pháp tạo một thủ tục:

Hủy thủ tục:

SELECT id,name FROM Product
7

Loop_Example2

SELECT id,name FROM Product
8

CREATE PROCEDURE curdemo() BEGIN DECLARE done INT DEFAULT FALSE; DECLARE a CHAR(16); DECLARE b, c INT; DECLARE cur1 CURSOR FOR SELECT id,data FROM test.t1; DECLARE cur2 CURSOR FOR SELECT i FROM test.t2; DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; OPEN cur1; OPEN cur2; read_loop: LOOP FETCH cur1 INTO a, b; FETCH cur2 INTO c; IF done THEN LEAVE read_loop; END IF; IF b < c THEN INSERT INTO test.t3 VALUES (a,b); ELSE INSERT INTO test.t3 VALUES (a,c); END IF; END LOOP; CLOSE cur1; CLOSE cur2; END;7

Các bước thực hiện một thủ tục: REPEAT .. UNTIL có nghĩa là lặp .. cho tới khi điều kiện không còn đúng nữa. Nó giống với vòng lặp do .. while trong ngôn ngữ Java, C/C++, C#

Một nhóm các lệnh thực hiện chức năng nào đó có thể được gom lại trong một thủ tục (procedure) nhằm làm tăng khả năng xử lý,khả năng sử dụng chung,tăng tính bảo mật và an toàn dữ liệu,tiện ích trong phát triển. Thủ tục có thể được lưu giữ ngay trong database như một đối tượng của database, sẵn sàng cho việc tái sử dụng. Thủ tục lúc này được gọi là Store procedure. Với các Store procedure, ngay khi lưu giữ Store procedure, chúng đã được biên dịch thành dạng p-code vì thế có thể nâng cao khả năng thực hiện.

SELECT id,name FROM Product
9

Thủ tục không trả về giá trị trực tiếp như hàm. Nhưng nó có thể có không hoặc nhiều tham số đầu ra. REPEAT.. UNTIL bạn cũng có thể sử dụng lệnh LEAVE, và ITERATE và ý nghĩa không có gì thay đổi (Xem thêm trong LOOP).

Repeat_Until_Example

DECLARE cursorProduct CURSOR FOR
SELECT id, title FROM Product
0

Cú pháp tạo một thủ tục:

Một nhóm các lệnh thực hiện chức năng nào đó có thể được gom lại trong một thủ tục (procedure) nhằm làm tăng khả năng xử lý,khả năng sử dụng chung,tăng tính bảo mật và an toàn dữ liệu,tiện ích trong phát triển. Thủ tục có thể được lưu giữ ngay trong database như một đối tượng của database, sẵn sàng cho việc tái sử dụng. Thủ tục lúc này được gọi là Store procedure. Với các Store procedure, ngay khi lưu giữ Store procedure, chúng đã được biên dịch thành dạng p-code vì thế có thể nâng cao khả năng thực hiện.

Thủ tục không trả về giá trị trực tiếp như hàm. Nhưng nó có thể có không hoặc nhiều tham số đầu ra.

Cú pháp tạo một thủ tục:

While_Do_Example

DECLARE cursorProduct CURSOR FOR
SELECT id, title FROM Product
2

Hủy thủ tục:

CREATE PROCEDURE curdemo()
BEGIN
  DECLARE done INT DEFAULT FALSE;
  DECLARE a CHAR(16);
  DECLARE b, c INT;
  DECLARE cur1 CURSOR FOR SELECT id,data FROM test.t1;
  DECLARE cur2 CURSOR FOR SELECT i FROM test.t2;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

  OPEN cur1;
  OPEN cur2;

  read_loop: LOOP
    FETCH cur1 INTO a, b;
    FETCH cur2 INTO c;
    IF done THEN
      LEAVE read_loop;
    END IF;
    IF b < c THEN
      INSERT INTO test.t3 VALUES (a,b);
    ELSE
      INSERT INTO test.t3 VALUES (a,c);
    END IF;
  END LOOP;

  CLOSE cur1;
  CLOSE cur2;
END;
7 MySQL sẽ ném ra một ngoại lệ có mã số tương ứng với nguyên nhân gây lỗi.

Các bước thực hiện một thủ tục: MySQL để sử lý tình huống ngoại lệ bạn định nghĩa ra một biến, và bảo với MySQL sẽ gán một giá trị nào đó vào biến này khi có ngoại lệ phát sinh. Bạn có thể kiểm tra giá trị của biến để biết được lỗi vừa xẩy ra và sử lý nó.

Ví dụ tạo một thủ tục:

Ở đây tôi tạo một thủ tục đơn giản, với tham số truyền vào là p_Emp_ID và có 3 tham số đầu ra, v_First_Name, v_Last_Name, v_Dep_ID.

Handling_Exception_Example1

DECLARE cursorProduct CURSOR FOR
SELECT id, title FROM Product
3

Nhấn vào biểu tượng để biên dịch thủ tục.

  1. Các câu lệnh (1), (2), (3) sẽ chạy mà không có vấn đề gì
  2. Câu lệnh (4) sẽ gây ra lỗi do bạn trèn vào một bản ghi vào bảng Department trùng lặp khóa chính đã có sẵn trong DB, nó thoát ra khỏi thủ tục.
  3. Câu lệnh (5) sẽ không được thực thi.

Chúng ta sửa lại code của thủ tục trên, thêm vào các đoạn code sử lý ngoại lệ.

Handling_Exception_Example1 (2)

DECLARE cursorProduct CURSOR FOR
SELECT id, title FROM Product
4

Hãy xem hình minh họa khi bạn gọi thủ tục ở trên:

Bạn đã khai báo bộ điều khiển lỗi 1062, là loại CONTINUE nghĩa là sau bắt gặp lỗi 1062 chương trình vẫn tiếp tục chạy các dòng code phía dưới.

Khi bạn gọi thủ tục:

  1. Các dòng lệnh (1),(2),(3) chạy mà không có vấn đề gì cả.
  2. Câu lệnh (4) ném ra lỗi 1062 do đã tồn tại bản ghi Department có DEPT_ID = 1. Chương trình sử lý lỗi bằng cách ghi ra một dòng thông báo.
  3. Dòng code (5) vẫn tiếp tục được chạy.

Trong trường hợp bạn muốn chương trình thoát ra khỏi khối lệnh khi gặp lỗi, bạn có thể khai báo bộ điều khiển lỗi là kiểu EXIT.

DECLARE cursorProduct CURSOR FOR
SELECT id, title FROM Product
5

Ví dụ 2:

Handling_Exception_Example2

DECLARE cursorProduct CURSOR FOR
SELECT id, title FROM Product
6

5.2- Định nghĩa điều khiển ngoại lệ

Các ví dụ trên đã minh họa cách thức điều khiển ngoại lệ trong MySQL. Và giờ bạn có thể xem quy tắc tổng quát: MySQL. Và giờ bạn có thể xem quy tắc tổng quát:

Cú pháp:

DECLARE cursorProduct CURSOR FOR
SELECT id, title FROM Product
7

Trong vòng lặp REPEAT.. UNTIL bạn cũng có thể sử dụng lệnh LEAVE, và ITERATE và ý nghĩa không có gì thay đổi (Xem thêm trong LOOP).

Có thể nhận hai giá trị CONTINUE hoặc EXIT. CONTINUE hoặc EXIT.

  • CONTINUE: Nói với chương trình rằng khi lỗi xẩy ra hãy thực thi và tiếp tục. và tiếp tục.
  • EXIT: Nói với chương trình rằng khi lỗi xẩy ra hãy thực thi và thoát khỏi khối lệnh cha. và thoát khỏi khối lệnh cha.

Trong vòng lặp REPEAT.. UNTIL bạn cũng có thể sử dụng lệnh LEAVE, và ITERATE và ý nghĩa không có gì thay đổi (Xem thêm trong LOOP).

Có thể nhận hai giá trị CONTINUE hoặc EXIT.

  1. CONTINUE: Nói với chương trình rằng khi lỗi xẩy ra hãy thực thi và tiếp tục.
    • EXIT: Nói với chương trình rằng khi lỗi xẩy ra hãy thực thi và thoát khỏi khối lệnh cha.
  2. Mô tả các đặc điểm của lỗi mà khi lỗi phát sinh, bộ điều khiển này sẽ được hoạt động. Nó có thể là:
    • Một mã lỗi cụ thể (là một con số), ví dụ:
    • 1062 là lỗi khi trèn thêm một bản ghi mà ID của nó đã tồn tại.
  3. Một chuỗi string có 5 ký tự (Mã SQLSTATE chuẩn), ví dụ:
    • HY000 là mã lỗi nói rằng ổ đĩa bị đầy.
    • HY001 là lỗi do tràn bộ nhớ.
    • Một lớp lỗi thông dụng đã được MySQL đặt tên hoặc có thể do người dùng đặt tên, chẳng hạn:

SQLWARNING: là các cảnh báo mà có mã chuẩn bắt đầu bởi '01'.

  1. NOTFOUND: là lớp các lỗi có mã chuẩn (SQLSTATE) bắt đầu bởi '02'. Thường liên quan tới sử lý con trỏ.SQLEXCEPTION, chương trình thủ tục sẽ bị ngừng tại vị trí lỗi.
  2. SQLEXCEPTION: Là lớp các lỗi mà có mã chuẩn không bắt đầu bởi '00', '01', '02'. Chú ý rằng mã bắt đầu bởi '00' là các thông báo thành công.SQLWARNING hoặc NOTFOUND, chương trình vẫn tiếp tục thực thi, giống như có bộ điều khiển CONTINUE (CONTINUE handler).

Chú ý: Nếu một điều kiện phát sinh, mà bạn không khai báo một bộ điều khiển (handler) nào, chương trình sẽ sử lý theo mặc định, tùy thuộc vào lớp điều kiện:

  1. Với các điều kiện SQLEXCEPTION, chương trình thủ tục sẽ bị ngừng tại vị trí lỗi.MySQL là một con số, hoặc giá trị SQLSTATE là một chuỗi chữ 5 ký tự. Bạn không nên sử dụng mã lỗi 0 hoặc SQLSTATE mà giá trị bắt đầu bởi '00', bởi vì nó thông báo sự thành công chứ không phải một lỗi.
  2. Đối với các điều kiện SQLWARNING hoặc NOTFOUND, chương trình vẫn tiếp tục thực thi, giống như có bộ điều khiển CONTINUE (CONTINUE handler). là viết tắt cho lớp các SQLSTATE có giá trị bắt đầu bởi '01'.
  3. Cụ thể: là viết tắt cho lớp các SQLSTATE có giá trị bắt đầu bởi '02'. Cái này phù hợp trong bối cảnh sử dụng con trỏ (Cursor) và được sử dụng để kiểm soát những gì sẽ xẩy ra khi con trỏ tiến tới cuối của một tập hợp dữ liệu. Khi không còn một bản ghi nào, Điều kiện khi không có dữ liệu sẽ phát sinh, với SQLSTATE có giá trị là '02000'. Để phát hiện điều kiện này, bạn có thể khai báo bộ điều khiển (Handler) cho nó (NOT FOUND). Bạn có thể xem ví dụ ở phần nói về con trỏ (Cursor). Điều kiện này cũng phát sinh cho câu lệnh  SELECT ... INTO var_list statements khi nó không có dòng dữ liệu nào.
  4. Mã lỗi của MySQL là một con số, hoặc giá trị SQLSTATE là một chuỗi chữ 5 ký tự. Bạn không nên sử dụng mã lỗi 0 hoặc SQLSTATE mà giá trị bắt đầu bởi '00', bởi vì nó thông báo sự thành công chứ không phải một lỗi. là viết tắt cho lớp các SQLSTATE mà giá trị không bắt đầu bởi '00', '01', or '02'.

SQLWARNING là viết tắt cho lớp các SQLSTATE có giá trị bắt đầu bởi '01'.

  1. NOT FOUND là viết tắt cho lớp các SQLSTATE có giá trị bắt đầu bởi '02'. Cái này phù hợp trong bối cảnh sử dụng con trỏ (Cursor) và được sử dụng để kiểm soát những gì sẽ xẩy ra khi con trỏ tiến tới cuối của một tập hợp dữ liệu. Khi không còn một bản ghi nào, Điều kiện khi không có dữ liệu sẽ phát sinh, với SQLSTATE có giá trị là '02000'. Để phát hiện điều kiện này, bạn có thể khai báo bộ điều khiển (Handler) cho nó (NOT FOUND). Bạn có thể xem ví dụ ở phần nói về con trỏ (Cursor). Điều kiện này cũng phát sinh cho câu lệnh  SELECT ... INTO var_list statements khi nó không có dòng dữ liệu nào.SQLEXCEPTION, chương trình thủ tục sẽ bị ngừng tại vị trí lệnh phát sinh điều kiện (ngoại lệ).
  2. SQLEXCEPTION là viết tắt cho lớp các SQLSTATE mà giá trị không bắt đầu bởi '00', '01', or '02'.SQLWARNING hoặc NOT FOUND, chương trình vẫn tiếp tục thực thi, giống như có bộ điều khiển CONTINUE (CONTINUE handler).

Nếu một điều kiện phát sinh, mà không có một bộ điều khiển nào khai báo, thì hành động sử lý tùy thuộc vào lớp điều kiện:

Với các điều kiện SQLEXCEPTION, chương trình thủ tục sẽ bị ngừng tại vị trí lệnh phát sinh điều kiện (ngoại lệ).

DECLARE cursorProduct CURSOR FOR
SELECT id, title FROM Product
8

Đối với các điều kiện SQLWARNING hoặc NOT FOUND, chương trình vẫn tiếp tục thực thi, giống như có bộ điều khiển CONTINUE (CONTINUE handler).SQLException:

DECLARE cursorProduct CURSOR FOR
SELECT id, title FROM Product
9

Bạn có thể tra cứu mã lỗi và các thông điệp lỗi tại:

Ví dụ với mã lỗi:

  • Ví dụ với SQLException:

5.3- Chuẩn đoán lỗi (Get DIAGNOSTICS)

Một khi ngoại lệ xẩy ra, bạn muốn lấy các thông tin về lỗi, chẳng hạn mã lỗi, SQLSTATE, và thông điệp lỗi, các thông tin khác...

TODO là kiểu biến có cấu trúc, cho phép bạn xử lý dữ liệu gồm nhiều dòng. Số dòng phụ thuộc vào câu lệnh truy vấn dữ liệu sau nó.Trong quá trình xử lý, bạn có thể thao tác với cursor thông qua từng dòng dữ liệu. Dòng dữ liệu này được định vị bởi một con trỏ. Với việc dịch chuyển con trỏ, bạn có thể lấy được toàn bộ dữ liệu của một dòng hiện tại.

6.2- Ví dụ với Con trỏ

Cursor_Example

Open cursorProduct
0