MySQL Stored Procedure

Збережені процедури для БД MySQL чомусь рідко використовуються. Це дивно, тому що вони:
1. Мають більшу швидкість віиконання, ніж аналогічна послідовність запитів.
2. Роблять код простішим і читабельнішим.
3. Їх можна використовуати на будь-якому нормальному віртуальному хостингу.
Для прикладу наведу процедуру для запису статистики відвідуваності у БД.

DELIMITER $$
DROP PROCEDURE IF EXISTS SetVisitorStat$$
CREATE PROCEDURE SetVisitorStat(
         IN in_ip VARCHAR(15),
                                   in_host VARCHAR(250),
                                   in_referrer VARCHAR(250),
                                   in_agent VARCHAR(250),
                                   in_user_uid MEDIUMINT(8)
        )
BEGIN

DECLARE var_host MEDIUMINT DEFAULT 0;
DECLARE var_referrer MEDIUMINT DEFAULT 0;
DECLARE var_ip MEDIUMINT DEFAULT 0;
DECLARE var_agent MEDIUMINT DEFAULT 0;

SELECT `uid` INTO var_host
FROM `stat_host` WHERE `stat_host`.`host` = in_host;
IF var_host = 0 THEN
INSERT INTO `stat_host` (`host`)
VALUES (in_host);
SELECT LAST_INSERT_ID() INTO var_host;
END IF;

SELECT `uid` INTO var_referrer
FROM `stat_referrer` WHERE `stat_referrer`.`referrer` = in_referrer;
IF var_referrer = 0 THEN
INSERT INTO `stat_referrer` (`referrer`)
VALUES (in_referrer);
SELECT LAST_INSERT_ID() INTO var_referrer;
END IF;

SELECT `uid` INTO var_ip
FROM `stat_ip` WHERE `stat_ip`.`ip` = in_ip;
IF var_ip = 0 THEN
INSERT INTO `stat_ip` (`ip`)
VALUES (in_ip);
SELECT LAST_INSERT_ID() INTO var_ip;
END IF;

SELECT `uid` INTO var_agent
FROM `stat_agent` WHERE `stat_agent`.`agent` = in_agent;
IF var_agent = 0 THEN
INSERT INTO `stat_agent` (`agent`)
VALUES (in_agent);
SELECT LAST_INSERT_ID() INTO var_agent;
END IF;

INSERT INTO `stat_visiting` (`time`, `ip_uid`, `host_uid`,
         `referrer_uid`,  `agent_uid`, `user_uid`)
VALUES (NOW(), var_ip, var_host, var_referrer, var_agent, in_user_uid);

END$$

DELIMITER ;

-- CALL SetVisitorStat('111', '222', '333', '444', '555');




Приклад використання на php:


mysql_connect("localhost", "mysql_user", "mysql_password");
mysql_select_db("mydb");

mysql_query("CALL SetVisitorStat('192.168.19.03', 'www.test.ua', 'www.google.com.ua', 'Google Chrome 2.0', '42');");


p.s. я вже постив це на свому блозі, але особливого зацікавлення тема не викликала :) Якщо тутешні читачі вимагатимуть можу написати маленький туторіал по збережених процедурах.

Коментарі (6)

RSS згорнути / розгорнути
+
0
вимагають! піши іщьо!
+ ще щось по mysql оптимізації якщо є
avatar

lemon

  • 31 липня 2009, 13:10
+
0
М-м-м. ))) Тема далеко не нова. ))) Ще одною дуже важливою особливістю, не зазначеною у топіку, є те, що «сторка» дозволяє приховати реалізацію пакету запитів або навіть звичайного простого запиту, коли він, наприклад, може складатися з одного оператора SELECT з багатьма INNER JOIN, наприклад.

Наскільки мені відомо, MySQL лише з п'ятої версії здобув таку можливість. Мав справу зі «сторками» лише під MS SQL 2000/2005 і задоволений ними страшенно. Свій домашній проект, який зараз розробляю just4fun вирішив взагалі побудувати лише на них. В разі якихось проблем хоч досвіду власного наберусь сам.

До речі, а в «мускульному T-SQL» можна якось повертати значення з процедури? В MS SQL дозволяється повертати значення лише через OUTPUT-параметри, що мені особисто здається незручним (особливо після JavaScript-ового return, наприклад, «foobar» або {foo: true, bar: true}). А, ну, може, хтось доповнить чи виправить моє про результати виконання процедур в MS SQL. ))) Я міг би, в принципі, погуглити, проте, підтримавши тему, підтримаю розмову.
avatar

cyba

  • 31 липня 2009, 13:16
+
+2
2cyba:
Для MySQL — тема нова, сам сказав з 5-ї версії. :) Хоча процедури можна було створювати і раніше але тільки на Сі як розширення до MySQL.

В інших базах, в тому ж InterBase, процедури — це основа роботи. В InterBase, до речі, немає autoincrement, він реалізовується через процедури для кожної таблиці.

Значення вертати можна у вигляді кортежів.

CREATE PROCEDURE my_sum(IN a MEDIUMINT(8), b MEDIUMINT(8))
BEGIN
SELECT a+b AS 'sum';
END$$

на PHP

mysql_query("CALL my_sum(5+7)");
$res = mysql_fetch_array();
echo $res['sum'];   //12


avatar

yura-chaikovsky

  • 31 липня 2009, 13:38
+
+1
Я мав на увазі просто те, що MySQL нарешті спромігся взяти собі на озброєння такий інструмент. ))) Зрештою, студенти спочатку в переважній більшості всі вчаться на MySQL, коли читають вступні книжечки по PHP+MySQL. ))) Тепер ці матеріали явно більшими будуть, що не може не тішити. :) Просто за своїм досвідом можу сказати, яким було моє здивування, коли я вперше в житті побачив T-SQL і те, наскільки воно чудове по своїй суті. :D Я просто хочу сказати, що початківці просто грамотнішими стануть. :)

>> Значення вертати можна у вигляді кортежів.
Ох, бляха-муха, вилетіло з голови… Я чогось впевнено думав, що повертати атомарні значення через SELECT — якось не то. Дякую. :)
avatar

cyba

  • 31 липня 2009, 13:49
+
0
Мають більшу швидкість віиконання, ніж аналогічна послідовність запитів.

Стоп, стоп, а відколи це у процедури MySQL почав залазити оптимізатор? Наскільки я знаю, відсутність такої опції у MySQL 5 якраз і не дозволяє використовувати цю функціональність (тому нею і «чомусь рідко використовуються»).
avatar

nixau

  • 03 серпня 2009, 19:28
+
0
на проекті використовували mysql тригера
до сторед процедур якось не дійшло, але цікаво :)

тому plz пишіть туторіал :)
avatar

zenyk

  • 05 серпня 2009, 16:40

Тільки зареєстровані й авторизовані користувачі можуть залишати коментарі.