Diferència entre revisions de la pàgina «Procediments emmagatzemats. Bàsic»

De wikijoan
Salta a la navegació Salta a la cerca
(Es crea la pàgina amb «__TOC__ =Introducció= Ja hem acabat d'estudiar el llenguatge SQL. Ara toca ampliar el SQL amb nova funcionalitat: programació dins de la base de dades. Veurem declar...».)
 
m
Línia 4: Línia 4:
  
 
=Introducció als procediments emmagatzemats a MySQL=
 
=Introducció als procediments emmagatzemats a MySQL=
 +
Utilitzarem la base de dades '''classicmodels''' amb MySQL.
 +
 +
Per crear un ''stored procedure'':
 +
<pre>
 +
DELIMITER $$
 +
 +
CREATE PROCEDURE GetCustomers()
 +
BEGIN
 +
SELECT customerName, city, state, postalCode, country
 +
FROM customers
 +
ORDER BY customerName;
 +
END$$
 +
 +
DELIMITER ;
 +
</pre>
 +
Fixa't que necessitem canviar el delimitador.
 +
 +
Un cop està emmagatzemat, podem cridar el procediment fent:
 +
<pre>
 +
mysql> CALL GetCustomers();
 +
</pre>
 +
En aquest cas el procediment ''GetCustomers()'' retorna el mateix que una select. Però com veurem, a un procediment li afegirem instruccions de programació (declaracions de variables, condicionals, bucles,...) que el farà molt més potent.
 +
 +
===Avantatges d'utilitzar procediments===
 +
*Reduce network traffic
 +
*Centralize business logic in the database
 +
*Make database more secure
 +
===Desavantatges d'utilitzar procediments===
 +
*Resource usages
 +
*Troubleshooting: It's difficult to debug stored procedures. Unfortunately, MySQL does not provide any facilities to debug stored procedures like other enterprise database products such as Oracle and SQL Server.
 +
*Maintenances
  
 
=Canviar el delimitador per defecte=
 
=Canviar el delimitador per defecte=
 +
A MySQL, el delimitador per defecte és el punt i coma (;). Però ho podem caniviar:
 +
<pre>
 +
DELIMITER //
  
 +
SELECT * FROM customers //
 +
 +
SELECT * FROM products //
 +
</pre>
 +
I en els procediments és necessari canviar-ho, doncs el ''punt i coma'' es fa servir dins la definició del procediment, i per tant hem de distingir entre el fi d'una setència dins del procediment, i la fi del procediment.
 +
<pre>
 +
DELIMITER $$
 +
 +
CREATE PROCEDURE sp_name()
 +
BEGIN
 +
  -- statements
 +
END $$
 +
 +
DELIMITER ;
 +
</pre>
 
=Crear nous procediments emmagatzemats=
 
=Crear nous procediments emmagatzemats=
 +
<pre>
 +
DELIMITER //
  
 +
CREATE PROCEDURE GetAllProducts()
 +
BEGIN
 +
SELECT *  FROM products;
 +
END //
 +
 +
DELIMITER ;
 +
</pre>
 +
<pre>
 +
mysql> CALL GetAllProducts();
 +
</pre>
 +
Des del MySQL Workbench també podem crear i executar els procediments. I també podem veure la llista de procediments emmagatzemats que tenim.
 
=Eliminar procediments emmagatzemats=
 
=Eliminar procediments emmagatzemats=
 +
És molt fàcil:
 +
<pre>
 +
DROP PROCEDURE [IF EXISTS] stored_procedure_name;
  
 +
DROP PROCEDURE  GetAllProducts()
 +
</pre>
 +
També ho podem fer des del workbench.
 
=Variables=
 
=Variables=
  
 
=Parametres=
 
=Parametres=
 +
Aquí comença la part interessant. Tenim paràmetres d'entrada (IN), paràmetres de sortida (OUT), i paràmetres d'entrada i de sortida (INOUT).
 +
 +
Sintaxi bàsica per definir un paràmetre:
 +
<pre>
 +
[IN | OUT | INOUT] parameter_name datatype[(length)]
 +
</pre>
 +
==Paràmetres d'entrada==
 +
<pre>
 +
DELIMITER //
  
 +
CREATE PROCEDURE GetOfficeByCountry(
 +
IN countryName VARCHAR(255)
 +
)
 +
BEGIN
 +
SELECT *
 +
FROM offices
 +
WHERE country = countryName;
 +
END //
 +
 +
DELIMITER ;
 +
</pre>
 +
<pre>
 +
CALL GetOfficeByCountry('USA');
 +
</pre>
 +
Si no passem el paràmetre d'entrada dóna un error:
 +
<pre>
 +
mysql> CALL GetOfficeByCountry();
 +
ERROR 1318 (42000): Incorrect number of arguments for PROCEDURE classicmodels.GetOfficeByCountry; expected 1, got 0
 +
</pre>
 +
==Paràmetres de sortida==
 +
<pre>
 +
DELIMITER $$
 +
 +
CREATE PROCEDURE GetOrderCountByStatus (
 +
IN  orderStatus VARCHAR(25),
 +
OUT total INT
 +
)
 +
BEGIN
 +
SELECT COUNT(orderNumber)
 +
INTO total
 +
FROM orders
 +
WHERE status = orderStatus;
 +
END$$
 +
 +
DELIMITER ;
 +
</pre>
 +
<pre>
 +
mysql> CALL GetOrderCountByStatus('Shipped',@total);
 +
 +
mysql> SELECT @total;
 +
+--------+
 +
| @total |
 +
+--------+
 +
|    303 |
 +
+--------+
 +
 +
mysql> CALL GetOrderCountByStatus('in process',@total);
 +
 +
mysql> SELECT @total AS  total_in_process;
 +
+------------------+
 +
| total_in_process |
 +
+------------------+
 +
|                6 |
 +
+------------------+
 +
</pre>
 +
Veiem com la variable total està disponible després d'haver cridar el procediment.
 +
==Paràmetres d'entrada i de sortida==
 +
Un paràmetre pot ser d'entrada i de sortida al mateix temps:
 +
<pre>
 +
DELIMITER $$
 +
 +
CREATE PROCEDURE SetCounter(INOUT counter INT,IN inc INT)
 +
BEGIN
 +
SET counter = counter + inc;
 +
END$$
 +
 +
DELIMITER ;
 +
</pre>
 +
<pre>
 +
SET @counter = 1;
 +
 +
CALL SetCounter(@counter,1); -- 2
 +
 +
CALL SetCounter(@counter,1); -- 3
 +
 +
CALL SetCounter(@counter,5); -- 8
 +
 +
SELECT @counter; -- 8
 +
+----------+
 +
| @counter |
 +
+----------+
 +
|        8 |
 +
+----------+
 +
</pre>
 
=Modificar procediments emmagatzemats=
 
=Modificar procediments emmagatzemats=
  
Línia 35: Línia 196:
 
         AND routine_schema = 'classicmodels';
 
         AND routine_schema = 'classicmodels';
 
</pre>
 
</pre>
 +
 
També podem veure fàcilment els procediments emmagatzemats amb el MySQL Workbench.
 
També podem veure fàcilment els procediments emmagatzemats amb el MySQL Workbench.
 
{{Autor}}, març 2022
 
{{Autor}}, març 2022

Revisió del 08:40, 16 març 2022

Introducció

Ja hem acabat d'estudiar el llenguatge SQL. Ara toca ampliar el SQL amb nova funcionalitat: programació dins de la base de dades. Veurem declaració de variables, condicionals, bucles, paràmetres d'entrada,...

Introducció als procediments emmagatzemats a MySQL

Utilitzarem la base de dades classicmodels amb MySQL.

Per crear un stored procedure:

DELIMITER $$

CREATE PROCEDURE GetCustomers()
BEGIN
	SELECT customerName, city, state, postalCode, country
	FROM customers
	ORDER BY customerName;
END$$

DELIMITER ;

Fixa't que necessitem canviar el delimitador.

Un cop està emmagatzemat, podem cridar el procediment fent:

mysql> CALL GetCustomers();

En aquest cas el procediment GetCustomers() retorna el mateix que una select. Però com veurem, a un procediment li afegirem instruccions de programació (declaracions de variables, condicionals, bucles,...) que el farà molt més potent.

Avantatges d'utilitzar procediments

  • Reduce network traffic
  • Centralize business logic in the database
  • Make database more secure

Desavantatges d'utilitzar procediments

  • Resource usages
  • Troubleshooting: It's difficult to debug stored procedures. Unfortunately, MySQL does not provide any facilities to debug stored procedures like other enterprise database products such as Oracle and SQL Server.
  • Maintenances

Canviar el delimitador per defecte

A MySQL, el delimitador per defecte és el punt i coma (;). Però ho podem caniviar:

DELIMITER //

SELECT * FROM customers //

SELECT * FROM products //

I en els procediments és necessari canviar-ho, doncs el punt i coma es fa servir dins la definició del procediment, i per tant hem de distingir entre el fi d'una setència dins del procediment, i la fi del procediment.

DELIMITER $$

CREATE PROCEDURE sp_name()
BEGIN
  -- statements
END $$

DELIMITER ;

Crear nous procediments emmagatzemats

DELIMITER //

CREATE PROCEDURE GetAllProducts()
BEGIN
	SELECT *  FROM products;
END //

DELIMITER ;
mysql> CALL GetAllProducts();

Des del MySQL Workbench també podem crear i executar els procediments. I també podem veure la llista de procediments emmagatzemats que tenim.

Eliminar procediments emmagatzemats

És molt fàcil:

DROP PROCEDURE [IF EXISTS] stored_procedure_name;

DROP PROCEDURE  GetAllProducts()

També ho podem fer des del workbench.

Variables

Parametres

Aquí comença la part interessant. Tenim paràmetres d'entrada (IN), paràmetres de sortida (OUT), i paràmetres d'entrada i de sortida (INOUT).

Sintaxi bàsica per definir un paràmetre:

[IN | OUT | INOUT] parameter_name datatype[(length)]

Paràmetres d'entrada

DELIMITER //

CREATE PROCEDURE GetOfficeByCountry(
	IN countryName VARCHAR(255)
)
BEGIN
	SELECT * 
 	FROM offices
	WHERE country = countryName;
END //

DELIMITER ;
CALL GetOfficeByCountry('USA');

Si no passem el paràmetre d'entrada dóna un error:

mysql> CALL GetOfficeByCountry();
ERROR 1318 (42000): Incorrect number of arguments for PROCEDURE classicmodels.GetOfficeByCountry; expected 1, got 0

Paràmetres de sortida

DELIMITER $$

CREATE PROCEDURE GetOrderCountByStatus (
	IN  orderStatus VARCHAR(25),
	OUT total INT
)
BEGIN
	SELECT COUNT(orderNumber)
	INTO total
	FROM orders
	WHERE status = orderStatus;
END$$

DELIMITER ;
mysql> CALL GetOrderCountByStatus('Shipped',@total);

mysql> SELECT @total;
+--------+
| @total |
+--------+
|    303 |
+--------+

mysql> CALL GetOrderCountByStatus('in process',@total);

mysql> SELECT @total AS  total_in_process;
+------------------+
| total_in_process |
+------------------+
|                6 |
+------------------+

Veiem com la variable total està disponible després d'haver cridar el procediment.

Paràmetres d'entrada i de sortida

Un paràmetre pot ser d'entrada i de sortida al mateix temps:

DELIMITER $$

CREATE PROCEDURE SetCounter(INOUT counter INT,IN inc INT)
BEGIN
	SET counter = counter + inc;
END$$

DELIMITER ;
SET @counter = 1;

CALL SetCounter(@counter,1); -- 2

CALL SetCounter(@counter,1); -- 3

CALL SetCounter(@counter,5); -- 8

SELECT @counter; -- 8
+----------+
| @counter |
+----------+
|        8 |
+----------+

Modificar procediments emmagatzemats

Llistar els procediments emmagatzemats

La manera més fàcil:

SHOW PROCEDURE STATUS;
SHOW PROCEDURE STATUS [LIKE 'pattern' | WHERE search_condition]
SHOW PROCEDURE STATUS WHERE db = 'classicmodels';
SHOW PROCEDURE STATUS LIKE '%pattern%'

Llistar els procediments utilitzant el diccionari de dades:

SELECT 
    routine_name
FROM
    information_schema.routines
WHERE
    routine_type = 'PROCEDURE'
        AND routine_schema = 'classicmodels';

També podem veure fàcilment els procediments emmagatzemats amb el MySQL Workbench.


creat per Joan Quintana Compte, març 2022