Merujuk kepada post sebelum ini, terdapat dua table. Satu untuk data original, kedua adalah data backup. Di mana table backup tersebut berjalan menggunakan TRIGGER.
Table Original mysql> select * from data; +----+---------------------+-----------------------+-------+ | id | timestamp | data1 | data2 | +----+---------------------+-----------------------+-------+ | 1 | 2016-02-15 23:11:34 | masukkan satu manual | 2.44 | | 2 | 2016-02-15 14:40:22 | data kedua berubah | 0.00 | | 3 | 2016-02-15 13:58:08 | data pertama | 2.20 | | 4 | 2016-02-15 13:58:08 | data kedua | 4.50 | | 5 | 2016-02-15 23:12:09 | ini baris yang kelima | 5.40 | +----+---------------------+-----------------------+-------+
Table Backup menggunakan trigger mysql> select * from data_log; +-------+--------+----+---------------------+-------------------------+-------+ | logid | action | id | timestamp | data1 | data2 | +-------+--------+----+---------------------+-------------------------+-------+ | 1 | I | 1 | 2016-02-15 14:03:46 | data pertama edit | 0.00 | | 2 | I | 2 | 2016-02-15 13:57:21 | data kedua | 0.00 | | 3 | I | 3 | 2016-02-15 13:58:08 | data pertama | 2.20 | | 4 | I | 4 | 2016-02-15 13:58:08 | data kedua | 4.50 | | 5 | U | 1 | 2016-02-15 14:06:44 | data pertama tidak edit | 2.00 | | 6 | D | 1 | 2016-02-15 14:07:43 | data pertama tidak edit | 2.00 | | 7 | U | 2 | 2016-02-15 14:40:22 | data kedua berubah | 0.00 | | 8 | I | 1 | 2016-02-15 23:11:34 | masukkan satu manual | 2.44 | | 9 | I | 5 | 2016-02-15 23:12:09 | ini baris yang kelima | 5.40 | +-------+--------+----+---------------------+-------------------------+-------+
Sekarang kita mahu membuat rollback (memberikan semula data yang telah diubah kepada table original) untuk satu data.
Kita ambil contoh, table: data, id:1, data1: "masukkan satu manual". Data ini mahu ditukar ke data sebelumnya.
Data yang dirujuk untuk aktiviti rollback adalah, table:data_log, logid:6, id:1, data1:"data pertama tidak edit". Kita akan pulangkan semula data ini ke table:data.
Biasanya, kita boleh membuat rollback dengan satu arahan SQL sahaja. Sebagai contoh,
/* Contoh #1 */ UPDATE data SET timestamp = (SELECT timestamp FROM data_log WHERE logid='6' AND data.id=data_log.id), data1=(SELECT data1 FROM data_log WHERE logid='6' AND data.id=data_log.id), data2=(SELECT data2 FROM data_log WHERE logid='6' AND data.id=data_log.id); /* Contoh #2 */ UPDATE data a SET (a.timestamp, a.data1, a.data2) = (SELECT b.timestamp, b.data1, b.data2 FROM data_log b WHERE b.id = a.id AND b.logid='6'); /* Contoh #3 */ UPDATE data_log INNER JOIN data ON data.id = data_log.id SET data.timestamp = data_log.timestamp, data.data1 = data_log.data1, data.data2 = data_log.data2 WHERE data_log.logid='6' /* dan pelbagai cara lagi */
Tetapi dalam situasi ini, ia tidak dibenarkan. SQL akan error. Kerana table:data_log merupakan table yang sentiasa di INSERT oleh TRIGGER, manakala table:data sentiasa dikawal oleh TRIGGER.
Apabila kedua-dua table ini diakses dengan serentak, malah mahu mengemaskini juga dalam masa yang sama, SQL tidak benarkan perkara ini berlaku. SELECT + COMPARE + UPDATE dalam satu arahan.
Apa yang boleh dibantu adalah dengan membuat programming. Contoh di sini kita menggunakan PHP.
Apa yang akan kita buat adalah:
- Dapatkan nama field yang mahu diupdate dari table data_log
- Sediakan SQL query untuk UPDATE table data
- Dapatkan nilai setiap data terlibat pada table data_log guna logid=6
- Cantumkan dapatan di langkah (1) dan (3) ke dalam SQL query di langkah (2) menjadi SQL yang lengkap.
- Jalankan SQL query tersebut untuk membuat kemaskini.
<?php $logid = $_GET['logid']; //output = 6 //1. Dapatkan nama field. Limit =1 bertujuan untuk ambil data terkecil, query tidak makan masa. $result = mysql_query("SELECT * FROM data_log limit 1"); if (!$result) { die("Query to show fields from table failed"); } // Jumlah field dari arahan di atas. // fields_num = 5 $fields_num = mysql_num_fields($result); // Sekadar nak lihat nama field. // Bermula dengan nilai $i=3, kerana: // 0 = running ID log // 1 = Activity log // 2 = ID for original table // 3 ~ n = data yang dimahukan. for($i=3; $i<$fields_num; $i++) { $field = mysql_fetch_field($result, $i); echo "{$field->name}".$i."<br>"; } // Di sini kita menggunakan mysql_fetch_field($result, $i) // Supaya namafield yang dipaparkan bermula dengan field data-data. // Jika sekadar guna mysql_fetch_field($result) tanpa $i, // Ia akan memaparkan field bermula dari 0 // Walaupun telah diberitahu, for($i=3..) //2. SQL query untuk UPDATE table:data $sql_rollback = "UPDATE data SET "; //3. Dapatkan nilai setiap data yang terlibat. // masukkan ke dalam row2[]; $result2 = mysql_query("SELECT * FROM data_log WHERE logid = '$logid'"); if (!$result2) { echo 'Could not run query: ' . mysql_error(); exit; } $row2 = mysql_fetch_row($result2); //4. Cantumkan dapatan di atas menjadi SQL yang lengkap. // Setiap nama field ({$field->name}) dan data ($row[]) digabungkan // Pastikan tiada tanda ',' pada nama field yang terakhir. Guna if($i == ($fields_num - 1)) for($i=3; $i<$fields_num; $i++) { $field = mysql_fetch_field($result, $i); if($i == ($fields_num - 1)){ $sql_rollback .= "{$field->name} = '".$row2[$i]."'"; } else { $sql_rollback .= "{$field->name} = '".$row2[$i]."', "; } } // Dapatkan field ID untuk table:data. $field_id = mysql_fetch_field($result, 2); // Lengkapkan SQL Query // Gunakan field ID tadi untuk WHERE // Dan running SQL Query guna mysql_query() $sql_rollback .=" WHERE {$field_id->name} = '".$row2[2]."'"; $resultrb = mysql_query($sql_rollback); ?>
Lihat hasilnya di database. Data telah dikemaskini, dan data_log juga sudah bertambah satu lagi baris data.
0 comments:
Post a Comment