03 Jul

Mysql’de Tekrarlayan (Mükerrer) Kayıt Algılama

Bir tabloda , sadece bir adet aynı nitelikte bir kayıt olmasını istediğimizde , ilgili alan veya alanları “unique” yaparak bunu kolaylıkla yapabiliyoruz. Alanı unique yaptıktan sonra, aynı nitelikte kayıt girmeye çalıştığımızda bize hata döndürür. İşte bu hata ve hata kodunu izleyerek, sistemde tekrarlayan bir kayıt olup olmadığını bulabiliriz .

Örnek olarak bir testdb oluşturalım, sonrasında aşağıdaki sorguları çalıştırarak tablomuzu oluşturalım :

CREATE TABLE `kullanici` (
`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`isim` VARCHAR( 32 ) NOT NULL ,
`nick` VARCHAR( 32 ) NOT NULL ,
`sifre` VARCHAR( 32 ) NOT NULL ,
`eposta` VARCHAR( 32 ) NOT NULL ,
`web` VARCHAR( 32 ) NOT NULL
) ENGINE = InnoDB;

ALTER TABLE `kullanici` ADD UNIQUE(`nick`);
ALTER TABLE `kullanici` ADD UNIQUE(`eposta`);

kullanıcı tablosu oluşturarak , nick ve eposta alanlarımızı unique yapıyoruz. Böylece tablomuzda benzer nick ve eposta kaydedildiğinde bize hata döndürecektir.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$pdo =new PDO('mysql:dbname=testdb;host=localhost','root','q1w2e3');
$pdo->setAttribute(Pdo::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
$sql='insert into kullanici values(null,?,?,?,?,?)';

try {
   $stm =$pdo->prepare($sql);
   $stm->execute(array('ersin dogan','ersin','1234','deneme@ersindogan.com','http://ersindogan.com'));
   echo 'Kayıt başarılı';
}catch(PDOException $e) {
   if($e->getCode() ==23000 ) {
      echo 'Bu kullanıcı veya eposta sistemde mevcut<br/>';
   }
   echo '<b>Bir hata oluştu : </b>'. $e->getMessage();
}

Bu kodu ilk çalıştırdığımızda ,bilgiler tabloya kaydedilecek. İkinci defa çalıştırmayı denerseniz, “Bu kullanıcı veya eposta sistemde mevcut” hatasını görürsünüz.

Yukarıdaki koddan da anlaşılabileceği gibi, dönen hata kodu 23000 ise ( bu hata kodu mysql veritabanı ve pdo eklentisine özeldir, başka veritabanlarında bu hata kodu farklı olabilir) , kaydımızın tekrarlayan bir kayıt olduğunu anlayabiliyoruz.

Genelde ilk başladığımız zamanlarda , öncelikle o kaydı veritabanında arar, eğer yoksa kayıt işlemini yapardık. Ama artık daha efektif çözümler mevcut ve bu yöntemleri kullanarak daha kolay çözümler üretebiliriz.

06 Dec

Mysql de triger yönetimi

MySQL de eklemiş olduğunuz trigerı görmek için:

1
2
3
 SELECT * FROM Information_Schema.Trigger
 WHERE Trigger_schema = 'veritabanı_ismi' AND
       Trigger_name = 'trigger_ismi';

Bir veritabanına elediğiniz tüm trigerları görmek için :

1
2
 SELECT * FROM Information_Schema.Trigger
 WHERE Trigger_schema = 'veritabanı_ismi'

Bir tabloya eklediğiniz trigerları görmek için :

1
2
3
SELECT * FROM Information_Schema.Trigger
 WHERE Trigger_schema = 'veritabanı_ismi' AND
       Event_object_table = 'tablo_ismi';

Son olarak da bir tabloya eklediğiniz trigerları da şu komut ile silebilirsiniz :

1
 DROP TRIGGER tablo_ismi.trigger_ismi
24 Sep

MySQL de transaction kullanımı

Bir önceki yazıda bulunan örnek ile devam edeceğim için, ilk önce bu örnekteki kodları edinip çalıştırmanız gerekli.

Transction, kelime anlamı ile işlem demektir. Fakat bu kelime anlamının haricinde, veritabanına doğru gerçekleştirilen işlemlerin, veritabanına kalıcı olarak işlenip işlenmemesini yöneten muazzam bir sistemdir. Ve kullandığınızda göreceksiniz ki çok hayat kurtaran bir sistemdir . MySQL 4.0 ve yukarısı InnoDB ve BDB saklama motorları transaction desteklemektedir.

Örneğimizde bir kullanıcı tablomuz var ve bir de gönderi tablomuz. Şöyle bir senaryo çizelim:
Bir kullanıcımızı silmek istiyoruz ve haliyle bu kullanıcının girdiği bütün gönderileri de silmek istiyoruz. Bunu basit bir sorgu ile kolayca gerçekleştirebiliriz:

baglan();
kullaniciSil($kullaniciId);
baglantiyiKapat();

Durum kabaca bundan ibaret. Ama ya işler ters gittiğinde. Kullanıcıyı sildik, ama bir terslik oldu, tam kullanıcı gönderileri silinirken hata oluştu ve gönderileri silemedik. O zaman ne yapacağız ? Gönderi tablosunda kullanıcısı olmayan gönderileri bulup silmek için bir işlem daha yaptırabiliriz. Ama bu ne performans açısından kabul edilebilir, ne de uygulamanın sağlamlığı ve kararlılığı açısından. İşte burada devreye transaction giriyor , tabi bu yapıyı kullanmanın en iyi yolunun PDO dan geçtiğini söylemek gerekir. Dönelim örneğimize:

try
{
   $veritabani = new PDO ( 'mysql:dbname=testdb;host=127.0.0.1', $kullanici, $sifre );
   $veritabani->setAttribute ( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
   $veritabani->beginTransaction ();
   try
   {
      if ($veritabani->exec ( $sorgu1 ) == 0)
         throw new Exception ( 'birinci
sorgu çalışmadı'
);
      echo 'sorgu 1 çalıştı
<br />
'
;
      if ($veritabani->exec ( $sorgu2 ) == 0)
         throw new Exception ( 'ikinci
sorgu çalışmadı'
);
      echo 'sorgu 2 çalıştı';
      $veritabani->commit ();
   } catch ( Exception $istisna )
   {
      echo $istisna->getMessage ();
      $veritabani->rollBack ();
   }
} catch ( Exception $baglantiIstistisnasi )
{
   echo 'bağlantı sağlanamadı sebep :
<br />
<b>'
. $baglantiIstistisnasi->getMessage () . '</b>
'
;
}

Normal şartlar altında, aksini belirmedikçe PDO bütün sorgularınızı otomatikman veritabanına iletir. beginTransaction () metodu ile PDO ya işlemlerin sonuçlandırılması için bizim onayımızı almasını söylüyoruz. Daha sonra try bloğu sağlıklı çalışır ise commit() metodu ile PDO ya işlemlerimizin istediğimiz gibi gittiğini ve işlemleri sonuçlandırmasını söylüyoruz. Eğer catch bloğuna düşer ise, ters giden birşeyler olduğunu bildiğimiz için rollBack() metodu ile yaptığımız bütün işlemlerin geri alınmasını söylüyoruz.
Bunu en iyi şöyle test edebilirsiniz. Örnekteki veritabanı ve tabloları oluşturun. User tablosuna veri girin ve user_posts tablosuna hiçbirşey girmeyin. $sorgu1 deki yere kullanıcının id sini doğru girin ve $sorgu2 ye dokunmadan örneği çalıştırın, bakın bakalım ne olmuş.
Şimdi normal şartlar altında,kullanıcı olduğu için kullanıcının silinmesi gerekirdi, kullanıcı gönderilerinin silinmesi için verdiğimiz kullanıcı id si yanlış olduğu için silinecek herhangi birşey olmayacaktı. Kullanıcı uçmuş gitmiş ama kullanıcı gönderileri öyle kalacak idi. Ama kalmayacak, sorgu çalıştıktan sonra gidip tabloya baktığınızda şaşırmayın, bir hata yapmadınız. Kullanıcı orda duruyor ,silinmedi.
Çünkü try bloğumuz sonuna kadar çalışmadı, kullanıcı gönderisini silemediği için istisna fırlattı ve bu yüzden catch blokuna düştü, burda da işlem ters gittiği için yapılan işlemler geri alındı. İşte hayat kurtaran bu güzell işlevi kullanmak bu kadar kolay.

Güzel günler dileği ile, hoşça kalın.

23 Jun

MySQL Replication Nedir, Nasıl Yapılır -II

 

2- Slave Konfigürasyonu

 

Slave de öncelikle exampledb veritabanını oluşturmalıyız:

mysql -u root -p

Enter password:

CREATE DATABASE exampledb;

quit;

 

Master da bulunan exampledb nin dökümünü alıp slave e transfer ettiyseniz, şimdi slave de yeni oluşturduğunuz exampledb ye SQL dökümünü aktarmanın tam zamanı.

 

mysql -u root -p<password> exampledb < /path/to/exampledb.sql (<password> yerine kendi şirfenizi girin! Önemli: -p ile <password> arasında boşluk olmamalı!)

 

LOAD DATA FROM MASTER kullamak istiyorsanız şimdilik burada gerçekleştireceğiniz birşye yok.

 

Şimdi slave deki MySQL e kendisinin slave olduğunu, master in 192.168.0.100 ve master veritabanı olarak exampledb yi aramasını söyleyeceğiz. Bunun için aşağıdaki satırları

/etc/mysql/my.conf dosyasına ekleyelim:

 

server-id=2

master-host=192.168.0.100

master-user=slave_user

master-password=secret

master-connect-retry=60

replicate-do-db=exampledb

 

ve sonra MySQL i yeniden başlatın:

 

/etc/init.d/mysql restart

 

Master exampledb yi SQL dökümü yardımı ile aktarmadıysanız ve LOAD DATA FROM MASTER yöntemi ile devam etmek istiyorsanız, master exampledb den verileri almanın tam zamanı:

 

mysql -u root -p

Enter password:

LOAD DATA FROM MASTER;

quit;

 

PhpMyAdmin kullanıyorsanız master exampledb de bulunan tüm tablo ve verilerin slave de bulunan exampledb bulunup bulunmadığını kontrol edebilirsiniz.

 

Son olarak şunu yapmalıyız:

 

mysql -u root -p

Enter Password:

SLAVE STOP;

 

Sonraki yazacağımız komut satırındaki komut değerlerini doğru bir biçimde yazmalısınız:

 

CHANGE MASTER TO MASTER_HOST=’192.168.0.100′, MASTER_USER=’slave_user’, MASTER_PASSWORD='<some_password>’, MASTER_LOG_FILE=’mysql-bin.006′, MASTER_LOG_POS=183;

 

  • MASTER_HOST                  master in IP adresi veya sunucu adıdır (örneğimizde bu 192.168.0.100 dir).

  • MASTER_USER                 master üzerinde Replication haklarını tanımladığımız kullanıcıdır.

  • MASTER_PASSWORD    master da bulunan MASTER_USER in şifresidir

  • MASTER_LOG_FILE      master üzerinde SHOW MASTER STATUS komutu çalıştırıldığında MySQL tarafından verilen dosya

  • MASTER_LOG_POS       master üzerinde SHOW MASTER STATUS komutu çalıştırıldığında MySQL tarafından verilen pozisyon

 

Şimdi komut satırındayken slave i çalıştıralım:

 

START SLAVE;

quit;

 

Hepsi bu kadar! Master daki exampledb güncellendiğinde bütün değişiklikler slave de bulunan exampledb ye uygulanacak. Test edin!

 

23 Jun

MySQL Replication Nedir, Nasıl Yapılır -I

Bu yazı MySql de databse replication (veritabanı kopyası) nasıl ayarlanacağı açıklanacaktır. MySQL replication bir ana sunucudan diğer bir sunucuya(slave) veritabanının bir kopyasının alınmasını sağlar, ve ana sunucudaki veritanabında gerçekleşen bütün güncellemmeler derhal diğer (slaave) sunucuya kopyalanır ve böylece her iki veritabanı senkronize olur. Bu bir yedekleme politikası değildir çünkü kazara kullanılan DELETE komutu diğer (slave) sunucuda da uygulanacaktır; fakat replication dodnanım problemlerine karşı koruma sağar.

Bu yazıda 192.168.0.100 ip adresine sahip bir ana sunucudan diğer (slave) sunucuya nasıl kopyalama(replication) yapılacağını göstereceğim. Her iki sistemde (master ve slave) debian sarge sürümü bulunmaktadır; Ancak konfigürasyon ufak değişikliklerle veya değişikliğe gerek olmadan uygulanabilir.

Her iki sistemde MySQL kurulu, ve exampledb veritabanı tabbloları ve verileriyle master üzerinde kurulu ancak slave üzerinde kurulu değil.

Öncelikle şunu söylemek istiyorum, bu sistemi bu şekilde ayarlamanın tek yolu değil. Bunu başarmak için birçok yol mevcut fakat ben bunu seçtim. Bunun sizin için çalışacağını garanti edemeyeceğim.

1 Master Kofigürasyonu

Öncelikle /etc/mysql/my.cnf dosyasını düzenlememiz gerekiyor. MySQL e ağ desteğini sağlamamız gerekir ve MySQL bütün IP adreslerini dinlemeli, bunun için eğer aşağıdaki satırlar mevcutsa komut satırı haline getireceğiz:

 

#skip-networking

#bind-address = 127.0.0.1

Ayrıca MySQL e hangi veritabanının logları yazacağını (Bu loglar master üzerinde hangi değişikliklerin olduğunu görebilmek için slave tarafından kullanılır), hangi log dosyasının kullanılması gerektiğini ve bu MySql sunucusunun master olduğunu söylemeliyiz. exampledbb veritabanını kopyalatmak istiyoruz bu yüzden aşağıdaki satırları /etc/mysql/my.cnf a ekleyeceğiz:

log-bin = /var/log/mysql/mysql-bin.log

binlog-do-db=exampledb

server-id=1

Ve sonra MySQL i yeniden başlatacağız:

/etc/init.d/mysql restart

Sonra MySQL veritabanına root olarak girerek replication haklarına sahip bir kullanıcı oluşturacağız:

mysql -u root -p

Enter Password:

Şimdi MySQL komut satırındayız.

 

GRANT REPLICATION SLAVE ON *.* TO ‘slave_user’@’%’ IDENTIFIED BY ‘<some_password>’; ( <some_password> yazan yere kendi şifrenizi giriniz!)

FLUSH PRIVILEGES;

 

Sonra (Hala MySQL komut satırındayken) şunu uygulayın:

 

USE exampledb;

FLUSH TABLES WITH READ LOCK;

SHOW MASTER STATUS;

 

Son komut aşağıdakine benzer bir çıktı verecek:

+——————–+————-+——————–+————————–+

| File | Position | Binlog_do_db | Binlog_ignore_db |

+——————–+————-+——————–+————————–+

| mysql-bin.006 | 183 | exampledb | |

+——————–+————+——————–+—————————+

1 row in set (0.00 sec)

 

Bu bilgiyi not edin, sonra slave de ihtiyacımız olacak!

Sonra MySql komut satırından çıkın:

quit;

==================================================================================================================

 

Master veritabanından slave e exampledb de bulunan tabbloları ve verileri aktarmanın iki yolu var. Birincisi veritabanının bir dökümünü (dump) almak, ikincisi slave de LOAD DATA FROM MASTER komutunu kullanmak. İkinci yöntemin dezavantajı bu operasyon sırasında master daki veritabanı kilitlenecek , bu yüzden yoğun trafiğe sahip büyük bir veritabanınız varsa bu yöntem sizin istediğiniz yöntem değil ve bu bağlamda birinci yolu izlemenizi öneririm. Ancak ikinci metod çok hızlıdır bu yüzden her ikisini de burada açıklayacağım.

Birinci yolu izleyecekseniz şunu yapın:

mysqldump -u root -p<password> –opt exampledb > exampledb.sql (<password> yerine kendi şirfenizi girin! Önemli: -p ile <password> arasında boşluk olmamalı!)

Bu exampledb.sql dosyasında exampledb nin SQL dökümünü oluşturur. Bunu slave sunucunuza transfer edin!

 

LOAD DATA FROM MASTER yöntemmini kullanmak istiyorsanız şimdilik uapacağınız birşey yok.

 

Son olarak exampledb deki tabloların kilidini açmamız gerekiyor:

 

mysql -u root -p

Enter password:

UNLOCK TABLES;

quit;

Şimdi master daki konfügirasyou tamamladık. Slave e geçelim…

19 Aug

MySql de Stored Procedure

Öncelikle stored procedure nedir, ona bakalım. Stored procedure nam-ı diğer saklı yordamlar, derlenmiş olarak veritabanında saklanan sql cümlecikleridir. Kabaca bir sql sorgusunun yaşam döngüsünü şöyle ele alabiliriz:

Öncelikle sql sorgunuz istemci vasıtasıyla ağ üzerinden veya localden veritabanı sunucumuza iletilir

-Sunucumuz sql cümleciğimize syntax kontrolü yapar

-Kontrolden geçen sorgu derlenerek çalıştırılır

-Dönen sonuç istemciye geri iletilir

Stored procedure kullandığımızda ise, syntax kontrolü ve derleme aşamaları sadece bir defaya mahsus olarak stored procedure u oluşturduğumuzda gerçekleşir. Daha sonra çağrıldığında ise derlenmeden direkt çalıştırılırlar. Şimdi Mysql ile stored procedure nasıl oluşturulur ona bakalım. Mysql5 ile birlikte Grafik Kullanıcı Arayüzüne sahip bir yönetimime de kavuştuk. Query Browser denen bu araçla Mysql de tablo,veritabanı,trigger,stored procedure vs oluşturabilmekteyiz.

Şimdi Query Browser açarak stored procedure oluşturalım.

Yukarıdaki resimde de görüldüğü gibi veritabanımıza sağ tıklayarak “Create New Procedure/Function” ile bir fonksiyon veya procedure oluşturabilmekteyiz.

Buraya tıkladıktan sonra karşımıza aşağıdaki gibi bir pencere gelecektir :

Bu penceredeki yere procedure/function ismini yazıyoruz ve ne oluşturacaksak (Procedure/Function) ilgili butona tıklıyoruz ve bize aşağıdakine benzer bir kod şablonu çıkarmaktadır.

Burada bizi ilgilendiren kısım BEGIN ve END arasında kalan kısımdır. Sql cümleciklerimizi buraya yazacağız. Burada hem mysqldeki stored procedure mantığını daha iyi kavrayabilmek için hem de stored procedurlere nasıl parametre aktarılacağını göstermek için çok kolay bir procedure(yordam) oluşturacağım :

Yukarıdaki kod bloğunda iki sayı ile dört işlem gerçekleştiren bir procedure yazmış olduk.

Stored procedur oluştururken dikkat etmemiz gereken iki püf nokta var;

Parametrenin yönü (IN,OUT,INOUT) :

IN olarak tanımlanmış parametre sadece giriş yönündedir bu değişkene procedure tarafından değer atanmaz salt okunurdur.

OUT olarak tanımlanmış parametre çıkış yönündedir, bu değişkene procedure tarafından değer atanır, değer alınmaz.

INOUT olarak tanımlanmış parametre hem giriş hem de çıkış yönündedir. Yani bu tipteki bir parametre ile hem procedure içerisine veri gönderilebilir hem de bu parametreye procedure tarafından değer atanmasına olanak sağlayarak veri döndürmesine olanak verir.

İkinci püf noktaysa verilen parametrelerin değer tipleridir. Procedure parametre aktarırken parametrenin hangi veri tipinde olacağı (int,char,text,date vb) belirtilmelidir.

Ve geriye kalan kısım normal SQL cümlecikleri ve veritabanına ait kontrol vb komutlarından oluşmaktadır. Yukarıdaki procedurumuz ile verilen iki sayıyı belirtilen işleme tabi tutarak sonucu görüntülemekteyiz.

Proceduru Query Browser da call dortislem(10,2,4); şeklinde çalıştırarak denediğinizde 5 sonucunu alacağız.

Görüldüğü gibi zamandan tasarruf etmekle kalmayıp, kod karmaşasından da kurtulmuş oluyoruz. Şimdilik bu kadar, kendinize iyi bakın…

27 Jul

Mysql de trigger

Trigger kelime anlamıyla tetikleyiciler, bir tabloya atanan ve o tablodaki istenen olay gerçekleştiğinde (insert,update veya delete)
server tarafında kendiliğinden çalışan bizim oluşturduğumuz
SQL kodlarıdır. MySql in sitesinde verdiği örnek ile açıklamaya çalışayım.
Önce tablolarımızı oluşturalım

CREATE TABLE test1(a1 INT);
CREATE TABLE test2(a2 INT);
CREATE TABLE test3(a3 INT NOT NULL AUTO_INCREMENT PRIMARY KEY);
CREATE TABLE test4(
a4 INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
b4 INT DEFAULT 0
);
bu da triggerimiz

delimiter $$
CREATE TRIGGER testref BEFORE INSERT ON test1
FOR EACH ROW BEGIN
INSERT INTO test2 SET a2 = NEW.a1;
DELETE FROM test3 WHERE a3 = NEW.a1;
UPDATE test4 SET b4 = b4 + 1 WHERE a4 = NEW.a1;
END;$$
delimiter;
verilerimizi eklyelim

INSERT INTO test3 (a3) VALUES
(NULL), (NULL), (NULL), (NULL), (NULL),
(NULL), (NULL), (NULL), (NULL), (NULL);INSERT INTO test4 (a4) VALUES
(0), (0), (0), (0), (0), (0), (0), (0), (0), (0);
INSERT INTO test1 VALUES (1), (3), (1), (7), (1), (8), (4), (4);
ve gidip tablolarımıza bakalım

mysql> SELECT * FROM test1;
+??+
| a1 |
+??+
| 1 |
| 3 |
| 1 |
| 7 |
| 1 |
| 8 |
| 4 |
| 4 |
+??+
8 rows in set (0.00 sec)mysql> SELECT * FROM test2;
+??+
| a2 |
+??+
| 1 |
| 3 |
| 1 |
| 7 |
| 1 |
| 8 |
| 4 |
| 4 |
+??+
8 rows in set (0.00 sec)
mysql> SELECT * FROM test3;
+?-+
| a3 |
+?-+
| 2 |
| 5 |
| 6 |
| 9 |
| 10 |
+?-+
5 rows in set (0.00 sec)
mysql> SELECT * FROM test4;
+?-+??+
| a4 | b4 |
+?-+??+
| 1 | 3 |
| 2 | 0 |
| 3 | 1 |
| 4 | 2 |
| 5 | 0 |
| 6 | 0 |
| 7 | 1 |
| 8 | 1 |
| 9 | 0 |
| 10 | 0 |
+?-+??+
10 rows in set (0.00 sec)
iyide ne oldu ne yaptın şimdi diyorsunuzdur belki. Anlatayım, zaten tablo oluşturma ve tabloya veri ekleme işlemlerini
bildiğinizi varsayarak trigger a geçiyorum.
Burada biz MySql e dedikki:
(Eyyy MySql )
eğer test1 tablosuna veri eklenirse bu eklemeden önce // CREATE TRIGGER testref BEFORE INSERT ON test1
test2 tablosundaki a2 alanını yeni eklenen veriyi ekle // INSERT INTO test2 SET a2 = NEW.a1;
test3 tablosundaki a3 alanınıdan yeni eklenen veriye denk gelen sütunu sil //DELETE FROM test3 WHERE a3 = NEW.a1;
test4 tablosundaki b4 alanına a4 alanının yeni eklenen veriyle eşleşen sütununu bir arttır // UPDATE test4 SET b4 = b4 + 1 WHERE a4 = NEW.a1;
(o da bizi kırmadı sağolsun yapıverdi işlemleri)
Burada bahsi geçen NEW anahtarı üzerinde işlem yapılan tabloya eklenen verilerdir, OLD kullanmış olsaydık o tablo üzerindeki eski verilere
işaret ediyor olacaktık.
Triggerları BEFORE ve AFTER anahtarlarını kullanarak o tablo üzerinde işlem gerçekleşmeden önce veya işlem gerçekleştikten sonra
çalışmasını sağlayabiliriz. Biz yukarıda BEFORE anahtarını kullanarak test1 tablosuna veriler eklenmeden önce işlemlerimizin gerçekleşmesini
istedik.Triggerin syntaxı

DELIMITER $$
CREATE TRIGGER ?trigger_ismi? ?trigger_event|INSERT|UPDATE|DELETE? ON ?tablo_ismi?
FOR EACH ROW BEGINSQL işlemleri
END;$$
DELIMITER;
hepsi bundan ibaret.