Panoramica sui Cursori

Spiegazione

I cursori sono strutture che permettono di scorrere i risultati in modo sequenziale ed effettuare operazioni sui risultati.

MariaDB permette l'uso dei cursori negli Stored Program. I cursori di MariaDB sono non-riavvolgibili, di sola lettura e asensitive.

  • Non-riavvolgibili significa che i risultati possono essere letti solo nell'ordine determinato dall'istruzione SELECT. Non è possibile saltare delle righe, né spostarsi a una data posizione, né estrarre le righe in ordine inverso.
  • Sola lettura significa che i dati non possono essere modificati tramite il cursore.
  • Asensitive significa che il cursore punta ai dati che si trovano effettivamente nelle tabelle. I cursori di questo genere sono più veloci rispetto all'alternativa, i cursori insensitive, perché i dati non vengono copiati in una tabella temporanea. Tuttavia modificando questi dati si modificano anche i dati letti dal cursore.

I cursori possono essere dichiarati con l'istruzione DECLARE CURSOR e aperti con OPEN. Le righe possono essere lette con FETCH. Infine il cursore si chiude con l'istruzione CLOSE.

When FETCH is issued and there are no more rows to extract, the following error is produced:

ERROR 1329 (02000): No data - zero rows fetched, selected, or processed

To avoid problems, a DECLARE HANDLER statement is generally used. The HANDLER should handler the 1329 error, or the '02000' SQLSTATE, or the NOT FOUND error class.

Only SELECT statements are allowed for cursors, and they cannot be contained in a variable - so, they cannot be composed dynamically. However, it is possible to SELECT from a view. Since the CREATE VIEW statement can be executed as a prepared statement, it is possible to dynamically create the view that is queried by the cursor.

Example

CREATE TABLE c1(i INT);

CREATE TABLE c2(i INT);

CREATE TABLE c3(i INT);

DELIMITER //

CREATE PROCEDURE p1()
BEGIN
  DECLARE done INT DEFAULT FALSE;
  DECLARE x, y INT;
  DECLARE cur1 CURSOR FOR SELECT i FROM test.c1;
  DECLARE cur2 CURSOR FOR SELECT i FROM test.c2;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

  OPEN cur1;
  OPEN cur2;

  read_loop: LOOP
    FETCH cur1 INTO x;
    FETCH cur2 INTO y;
    IF done THEN
      LEAVE read_loop;
    END IF;
    IF x < y THEN
      INSERT INTO test.c3 VALUES (x);
    ELSE
      INSERT INTO test.c3 VALUES (y);
    END IF;
  END LOOP;

  CLOSE cur1;
  CLOSE cur2;
END; //

DELIMITER ;

INSERT INTO c1 VALUES(5),(50),(500);

INSERT INTO c2 VALUES(10),(20),(30);

CALL p1;

SELECT * FROM c3;
+------+
| i    |
+------+
|    5 |
|   20 |
|   30 |
+------+

Commenti

Sto caricando i commenti......