Diferència entre revisions de la pàgina «Procediments emmagatzemats. Continuació»

De wikijoan
Salta a la navegació Salta a la cerca
Línia 169: Línia 169:
 
=Bucles WHILE LOOP=
 
=Bucles WHILE LOOP=
 
*https://www.mysqltutorial.org/mysql-stored-procedure/mysql-while-loop/
 
*https://www.mysqltutorial.org/mysql-stored-procedure/mysql-while-loop/
 +
<pre>
 +
[begin_label:] WHILE search_condition DO
 +
    statement_list
 +
END WHILE [end_label]
 +
</pre>
 +
Per exemple, creem la taula ''calendars'':
 +
<pre>
 +
CREATE TABLE calendars(
 +
    id INT AUTO_INCREMENT,
 +
    fulldate DATE UNIQUE,
 +
    day TINYINT NOT NULL,
 +
    month TINYINT NOT NULL,
 +
    quarter TINYINT NOT NULL,
 +
    year INT NOT NULL,
 +
    PRIMARY KEY(id)
 +
);
 +
</pre>
 +
I creem dos procediments:
 +
<pre>
 +
DELIMITER $$
 +
 +
CREATE PROCEDURE InsertCalendar(dt DATE)
 +
BEGIN
 +
    INSERT INTO calendars(
 +
        fulldate,
 +
        day,
 +
        month,
 +
        quarter,
 +
        year
 +
    )
 +
    VALUES(
 +
        dt,
 +
        EXTRACT(DAY FROM dt),
 +
        EXTRACT(MONTH FROM dt),
 +
        EXTRACT(QUARTER FROM dt),
 +
        EXTRACT(YEAR FROM dt)
 +
    );
 +
END$$
 +
 +
DELIMITER ;
 +
</pre>
 +
<pre>
 +
DELIMITER $$
 +
 +
CREATE PROCEDURE LoadCalendars(
 +
    startDate DATE,
 +
    day INT
 +
)
 +
BEGIN
 +
   
 +
    DECLARE counter INT DEFAULT 1;
 +
    DECLARE dt DATE DEFAULT startDate;
 +
 +
    WHILE counter <= day DO
 +
        CALL InsertCalendar(dt);
 +
        SET counter = counter + 1;
 +
        SET dt = DATE_ADD(dt,INTERVAL 1 day);
 +
    END WHILE;
 +
 +
END$$
 +
 +
DELIMITER ;
 +
</pre>
 +
Amb aquest procediment fem insercions a la taula ''calendars'':
 +
<pre>
 +
CALL LoadCalendars('2019-01-01',31);
 +
</pre>
 +
Si et fixes bé en el codi, el procediment ''LoadCalendars()'' executa els ''InsertCalendar()'' a dins dels bucle.
 +
 
=Bucles REPEAT LOOP=
 
=Bucles REPEAT LOOP=
 
*https://www.mysqltutorial.org/mysql-stored-procedure/mysql-repeat-loop/
 
*https://www.mysqltutorial.org/mysql-stored-procedure/mysql-repeat-loop/

Revisió del 16:17, 4 abr 2022

IF. Condicionals

Ús del IF-ELSEIF-ELSE:

DELIMITER $$

CREATE PROCEDURE GetCustomerLevel(
    IN  pCustomerNumber INT, 
    OUT pCustomerLevel  VARCHAR(20))
BEGIN
    DECLARE credit DECIMAL DEFAULT 0;

    SELECT creditLimit 
    INTO credit
    FROM customers
    WHERE customerNumber = pCustomerNumber;

    IF credit > 50000 THEN
        SET pCustomerLevel = 'PLATINUM';
    ELSEIF credit <= 50000 AND credit > 10000 THEN
        SET pCustomerLevel = 'GOLD';
    ELSE
        SET pCustomerLevel = 'SILVER';
    END IF;
END $$

DELIMITER ;

I per provar el procediment:

CALL GetCustomerLevel(447, @level);
SELECT @level;

CALL GetCustomerLevel(447, @level); 
SELECT @level;

sentència CASE

La sintaxi de la clàusula CASE és com es mostra a continuació:

DELIMITER $$

CREATE PROCEDURE GetCustomerShipping(
	IN  pCustomerNUmber INT, 
	OUT pShipping       VARCHAR(50)
)
BEGIN
    DECLARE customerCountry VARCHAR(100);

SELECT 
    country
INTO customerCountry FROM
    customers
WHERE
    customerNumber = pCustomerNUmber;

    CASE customerCountry
		WHEN  'USA' THEN
		   SET pShipping = '2-day Shipping';
		WHEN 'Canada' THEN
		   SET pShipping = '3-day Shipping';
		ELSE
		   SET pShipping = '5-day Shipping';
	END CASE;
END$$

DELIMITER ;

Per provar-ho:

CALL GetCustomerShipping(112,@shipping);

SELECT @shipping;

Mirem també aquest altre exemple:

DELIMITER $$

CREATE PROCEDURE GetDeliveryStatus(
	IN pOrderNumber INT,
    OUT pDeliveryStatus VARCHAR(100)
)
BEGIN
	DECLARE waitingDay INT DEFAULT 0;
    SELECT 
		DATEDIFF(requiredDate, shippedDate)
	INTO waitingDay
	FROM orders
    WHERE orderNumber = pOrderNumber;
    
    CASE 
		WHEN waitingDay = 0 THEN 
			SET pDeliveryStatus = 'On Time';
        WHEN waitingDay >= 1 AND waitingDay < 5 THEN
			SET pDeliveryStatus = 'Late';
		WHEN waitingDay >= 5 THEN
			SET pDeliveryStatus = 'Very Late';
		ELSE
			SET pDeliveryStatus = 'No Information';
	END CASE;	
END$$
DELIMITER ;
CALL GetDeliveryStatus(10100,@delivery);

Bulces LOOP

Exemple bàsic:

DROP PROCEDURE LoopDemo;

DELIMITER $$
CREATE PROCEDURE LoopDemo()
BEGIN
	DECLARE x  INT;
	DECLARE str  VARCHAR(255);
        
	SET x = 1;
	SET str =  '';
        
	loop_label:  LOOP
		IF  x > 10 THEN 
			LEAVE  loop_label;
		END  IF;
            
		SET  x = x + 1;
		IF  (x mod 2) THEN
			ITERATE  loop_label;
		ELSE
			SET  str = CONCAT(str,x,',');
		END  IF;
	END LOOP;
	SELECT str;
END$$

DELIMITER ;

Quan executem aquest bucle, la resposta que obtenim és:

CALL LoopDemo();

+-------------+
| str         |
+-------------+
| 2,4,6,8,10, |
+-------------+

Fixem-nos què fa aquest codi:

  • Declarem dues variables. x és un comptador que comença per 1 i es va incrementant d'un en un; str és una cadena que anirà acumulant el resultat que volem visualitzar com a resposta.
  • loop_label és una etiqueta, per donar un nom al bucle.
  • Entrem al bucle, i hi ha un condicional que ens diu que si x>10 sortim del bucle.
  • Dins del bucle hi ha un altre condicional que diu que si x és un nombre parell, aleshores concatenem el valor a la cadena str, afegint una coma (,). I si és senar ens saltem una iteració del bucle.
  • Finalment fem SELECT str, és a dir, visualitzar la cadena.

La funció MOD, que significa mòdul, és el residu de la divisió. Per exemple:

25 MOD 7 = 4

doncs al dividir 25 entre 7 dóna 3, i la resta (residu) val 4, és a dir, en sobren 4. Per tant, fent el mòdul 2 d'un número ens serveix per saber si és parell o senar.

6 MOD 2 = 0
7 MOD 2 = 1

I si el resultat (0 o 1) el posem dins del IF, recordem que 0 és equivalent a FALSE, i 1 és equivalent a TRUE.

Bucles WHILE LOOP

[begin_label:] WHILE search_condition DO
    statement_list
END WHILE [end_label]

Per exemple, creem la taula calendars:

CREATE TABLE calendars(
    id INT AUTO_INCREMENT,
    fulldate DATE UNIQUE,
    day TINYINT NOT NULL,
    month TINYINT NOT NULL,
    quarter TINYINT NOT NULL,
    year INT NOT NULL,
    PRIMARY KEY(id)
);

I creem dos procediments:

DELIMITER $$

CREATE PROCEDURE InsertCalendar(dt DATE)
BEGIN
    INSERT INTO calendars(
        fulldate,
        day,
        month,
        quarter,
        year
    )
    VALUES(
        dt, 
        EXTRACT(DAY FROM dt),
        EXTRACT(MONTH FROM dt),
        EXTRACT(QUARTER FROM dt),
        EXTRACT(YEAR FROM dt)
    );
END$$

DELIMITER ;
DELIMITER $$

CREATE PROCEDURE LoadCalendars(
    startDate DATE, 
    day INT
)
BEGIN
    
    DECLARE counter INT DEFAULT 1;
    DECLARE dt DATE DEFAULT startDate;

    WHILE counter <= day DO
        CALL InsertCalendar(dt);
        SET counter = counter + 1;
        SET dt = DATE_ADD(dt,INTERVAL 1 day);
    END WHILE;

END$$

DELIMITER ;

Amb aquest procediment fem insercions a la taula calendars:

CALL LoadCalendars('2019-01-01',31);

Si et fixes bé en el codi, el procediment LoadCalendars() executa els InsertCalendar() a dins dels bucle.

Bucles REPEAT LOOP

Sentència LEAVE


creat per Joan Quintana Compte, març 2022