Insert procedure with incremental session variable
Bu MySQL prosedur daxilinde biz 1 сədvəldən cursor vasitəsilə məlumatı çəkib digər bir cədvələ session variable increment etməklə insert edirik.
Şəxsi task-ım olan bu prosedur kodunu paylaşıram:
DELIMITER $$ CREATE PROCEDURE insert_it() BEGIN declare var_match int; declare v_last_row_fetched int default 0; declare cursor1 cursor for select id from wd_matches; declare continue handler for not found set v_last_row_fetched=1; set v_last_row_fetched=0; open cursor1; cursor_loop: loop fetch cursor1 into var_match; if v_last_row_fetched=1 then leave cursor_loop; end if; set @matcher = var_match; set @counter=0; inserting: loop if @counter > 17 then leave inserting; end if; set @counter = @counter+1; insert into wd_squads(`match`,player,ord,`status`) values(@matcher,0,@counter,'0'); end loop inserting; end loop cursor_loop; close cursor1; set v_last_row_fetched=0; end $$
Təşəkkürlər 😉
MySQL Stored function\SQL imkanları ilə text parsing(Advance Usage)
Bugünkü mövzu bir xeyli maraqlı olduğu üçün təcili olaraq qeyd etməkdən zövq alıram.
Əlimizdə olan cədvəlimiz:
CREATE TABLE `wd_universities` ( `id` smallint(5) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(150) NOT NULL, `country` tinyint(3) unsigned NOT NULL, `city` smallint(5) unsigned NOT NULL, `status` tinyint(1) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=128 DEFAULT CHARSET=utf8
Və içindəki məlumatlardan bir qismi:
*************************** 119. row *************************** id: 119 name: <!--az>9 N-li orta məktəb</az--><!--en>9 N-li orta məktəb</en--><!--ru>9 N-li orta məktəb</ru--> country: 0 city: 0 status: 0 *************************** 120. row *************************** id: 120 name: <!--az>Azerbaycan muellimler inisitutu</az--><!--en>Azerbaycan muellimler inisitutu</en--><!--ru>Azerbaycan muellimler inisitutu</ru--> country: 0 city: 0 status: 0
Gördüyümüz kimi 1 row daxilində
<!--az></az--> , <!--en></en-->, <!--ru></ru-->
tag-ləri arasında məlumatlar var. Bizə lazımdır ki,
<!--en></en-->
tag-ləri arasında olan məlumatı İD-ni verməklə götürək.
İlk öncə
<!--en></en-->
tag-lərinin yer aldığı row-ları match etməliyik. Burda regexp bizə yardım edir:
mysql> select id,name from wd_universities where name regexp '<\!--en>.*</en-->'; . . | 107 | <!--az>koopirasiya kolleci</az--><!--en>koopirasiya kolleci</en--><!--ru>koopirasiya kolleci</ru--> | | 108 | <!--az>Gəncə Dövlət Universiteti</az--><!--en>Gəncə Dövlət Universiteti</en--><!--ru>Gəncə Dövlət Universiteti</ru--> | | 109 | <!--az>Qafqaz Universiteti</az--><!--en>Qafqaz Universiteti</en--><!--ru>Qafqaz Universiteti</ru--> | | 110 | <!--az>Azerbaycan malliya iqtisad kolleci</az--><!--en>Azerbaycan malliya iqtisad kolleci</en--><!--ru>Azerbaycan malliya iqtisad kolleci</ru--> | | 111 | <!--az>QERB UNIVERSITETI</az--><!--en>QERB UNIVERSITETI</en--><!--ru>QERB UNIVERSITETI</ru-->
İkinci olaraq bizə bu row-lar daxilində
<!--en>
-li məlumatı çıxarmaq lazımdır. Onu da aşağıdakı sorğu ilə müəyyən edirik:
select substring((select name from wd_universities where name regexp '<!--en>.*</en-->' and id = 108), locate('<!--en>', (select name from wd_universities where name regexp '<!--en>.*</en-->' and id = 108)), (locate('</en-->', (select name from wd_universities where name regexp '<!--en>.*</en-->' and id = 108))) - (locate('<!--en>', (select name from wd_universities where name regexp '<!--en>.*</en-->' and id = 108))));
Nümunə Output:
<!--en>Gəncə Dövlət Universiteti
Daha sonra bizə lazımdır ki tag-ləri əvvəldən və sondan silən bir funksiyamız olsun.Funksiya:
delimiter $$ CREATE FUNCTION fnStripTags( Dirty varchar(200) ) RETURNS varchar(200) DETERMINISTIC BEGIN DECLARE iStart, iEnd, iLength int; WHILE Locate( '<', Dirty ) > 0 And Locate( '>', Dirty, Locate( '<', Dirty )) > 0 DO BEGIN SET iStart = Locate( '<', Dirty ), iEnd = Locate( '>', Dirty, Locate('<', Dirty )); SET iLength = ( iEnd - iStart) + 1; IF iLength > 0 THEN BEGIN SET Dirty = Insert( Dirty, iStart, iLength, ''); END; END IF; END; END WHILE; RETURN Dirty; END $$
Funksiya istifadəsi:
mysql> select fnStripTags('<!--en>Gəncə Dövlət Universiteti'); +-----------------------------------------------------+ | fnStripTags('<!--en>Gəncə Dövlət Universiteti') | +-----------------------------------------------------+ | Gəncə Dövlət Universiteti | +-----------------------------------------------------+ 1 row in set (0.00 sec)
Son olaraq və ən əsas olaraq bizim məntiqi sonluq yaradan funksiyamız. Funksiya parametr olaraq İD-ni qəbul edir. Bu İD-yə uyğun olan
<!--en-->
-li məlumatı tapır. Tag-ləri silir və bizə təmiz lazım olan məlumatı çıxardır:
DELIMITER $$ CREATE function exclude_tags_en(u_id int) RETURNS varchar(150) charset utf8 DETERMINISTIC BEGIN declare v_name varchar(150) charset utf8; declare v_last_row_fetched int default 0; declare v_result varchar(150) charset utf8; declare cursor1 cursor for select name from wd_universities where name regexp '<\!--en>.*</en-->' and id=u_id; declare continue handler for not found set v_last_row_fetched=1; set v_last_row_fetched=0; open cursor1; cursor_loop: loop fetch cursor1 into v_name; if v_last_row_fetched=1 then leave cursor_loop; end if; set @query_parse=(select substring((v_name), locate('<!--en>',(v_name)), (locate('</en-->',(v_name)))-(locate('<!--en>',(v_name))))); set v_result=(SELECT fnStripTags(@query_parse)); return v_result; end loop cursor_loop; close cursor1; set v_last_row_fetched=0; END$$
Istifadəsi:
mysql> select exclude_tags_en(108); +-------------------------------+ | exclude_tags_en(108) | +-------------------------------+ | Gəncə Dövlət Universiteti | +-------------------------------+ 1 row in set (0.00 sec) mysql> select exclude_tags_en(109); +----------------------+ | exclude_tags_en(109) | +----------------------+ | Qafqaz Universiteti | +----------------------+ 1 row in set (0.00 sec)
Beləliklə tapşırıq yerinə yetirilmişdir.
Təşəkkürlər 😉
Fibonacci ardıcıllığı
Biraz da maraq qataq işimizə ))
Bu procedure input olaraq verilən rəqəmin sayı qədər fibonacci sequence ardıcıllığı generate edir.
delimiter $$ create procedure fibonacci(n int) begin declare n1 int default not null; declare n2 int default not null; declare n3 int default 0; declare seq text; declare count int default 0; set count=0; set n1=1; set n2=0; set n3=null; set seq=''; while count<n do set count=count+1; set n3 = n1 + n2; set n1=n2; set n2 = n3; set seq = (select CONCAT(seq,n3,', ') from dual); end while; SELECT seq AS fibonacci_numbers; end $$
Və məsələn ilk 5 Fibonacci rəqəmləri:
mysql> call fibonacci(5); +-------------------+ | fibonacci_numbers | +-------------------+ | 1, 1, 2, 3, 5, | +-------------------+ 1 row in set (0.00 sec) Query OK, 0 rows affected (0.00 sec)
İlk 10:
mysql> call fibonacci(10); +------------------------------------+ | fibonacci_numbers | +------------------------------------+ | 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, | +------------------------------------+ 1 row in set (0.00 sec) Query OK, 0 rows affected (0.00 sec)
Təşəkkürlər 😉
Müəyyən həcmdən böyük cədvəllər üçün EVENT
Delimiter $$ CREATE EVENT event_huge_table_ ON SCHEDULE EVERY 20 second COMMENT "Mueyyen hecmden boyuk cedveller uzerinde is" DO BEGIN DECLARE v_total_mb FLOAT(10,4); declare v_last_row_fetched int default 0; DECLARE cursor1 CURSOR FOR SELECT sum(TRUNCATE((data_length+index_length)/1024/1024,4)) as total_mb FROM information_schema.`TABLES` where table_schema='mysqlspp' group by table_name; declare continue handler for not found set v_last_row_fetched=1; set v_last_row_fetched=0; OPEN cursor1; cursor_loop: LOOP FETCH cursor1 INTO v_total_mb; IF v_last_row_fetched=1 THEN leave cursor_loop; END IF; if v_total_mb>20 then insert into test_zerofill(name) values('dusen var?'); end if; end loop cursor_loop; close cursor1; set v_last_row_fetched=0; END $$
Alter Table Charset and Collation
DELIMITER $$ CREATE DEFINER=`root`@`127.0.0.1` PROCEDURE `multiple_alter_table_charset`() BEGIN declare v_table_name varchar(30); declare v_last_row_fetched int default 0; declare v_table_schema varchar(30); declare cursor1 cursor for select table_schema,table_name from information_schema.tables where table_schema not in ('mysql' , 'performance_schema', 'information_schema') and table_type = 'base table' and table_collation = 'latin1_swedish_ci'; declare continue handler for not found set v_last_row_fetched=1; set v_last_row_fetched=0; open cursor1; cursor_loop: loop fetch cursor1 into v_table_schema,v_table_name; if v_last_row_fetched=1 then leave cursor_loop; end if; set @sql_v=concat('alter table ',v_table_schema,'.',v_table_name,' CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci'); prepare stmt from @sql_v; EXECUTE stmt; deallocate prepare stmt; end loop cursor_loop; close cursor1; set v_last_row_fetched=0; END$$
Procedure bütün latin1-ləri tapır və hamısını UTF8-ə çevirir
*Diqqət!!! Production-da istifadə etməzdən əvvəl hər hansı bir ERROR əleyhinə test-də sınamaq məsləhətdir.*
Alter Table Engine procedure
delimiter $$ CREATE PROCEDURE `multiple_alter`() begin declare v_table_schema varchar(30); declare v_table_name varchar(30); declare v_last_row_fetched int default 0; declare cursor1 cursor for select a.table_schema, a.table_name from information_schema.tables as a where a.engine = 'MyISAM' and a.table_schema not in ('mysql' , 'information_schema','performance_schema'); declare continue handler for not found set v_last_row_fetched=1; set v_last_row_fetched=0; open cursor1; cursor_loop: loop fetch cursor1 into v_table_schema,v_table_name; if v_last_row_fetched=1 then leave cursor_loop; end if; set @sql_v=concat('alter table ',v_table_schema,'.',v_table_name,' engine=innodb'); prepare stmt from @sql_v; EXECUTE stmt; deallocate prepare stmt; end loop cursor_loop; close cursor1; set v_last_row_fetched=0; end$$
Yuxarıdakı procedure database-də olan bütün MyİSAM cədvəlləri tapır və hamısını İnnoDB-yə çevirir.
Diqqət!!! Production-da istifadə etməzdən əvvəl hər hansı bir ERROR əleyhinə test-də sınamaq məsləhətdir.