PHP Excel Remove Row

Sunday, September 25, 2016

Remove row.

Contoh di bawah, jika nak remove row nombor 6 sebanyak 4 kali.


<?php
for($i=0; $i<4; $i++){
 $objPHPExcel->getActiveSheet()->removeRow(6);
}
?>

PHP Excel Karekter Enter

Masukkan key Enter ke dalam field Excel guna PHPExcel. Gunakan str_replace(). Replace coma kepada \n

<?php 
$objPHPExcel->getActiveSheet()->SetCellValue('O'.$bil, strtoupper(str_replace(',',"\n",c($row['kriteria']))));
setCenterOnEmpty($row['kriteria'], 'O'.$bil, $objPHPExcel);


if(!function_exists("setCenterOnEmpty")){
function setCenterOnEmpty($data, $index, $objPHPExcel){
 if($data==' - ' || $data=='-' || $data=='')$objPHPExcel->getActiveSheet()->getStyle($index)->getAlignment()->setHorizontal(PHPExcel_Style_Alignment::HORIZONTAL_CENTER);
}}
?>

Javascript Papar Textarea Value Newline

Thursday, July 07, 2016

var addrs = $("#alamat").val();
var lines = addrs.split(/\n/);
var texts = []
for (var i=0; i < lines.length; i++) {
  if (/\S/.test(lines[i])) {
    texts.push($.trim(lines[i])+'<br>');
  }
}

alert(JSON.stringify(texts));

$("#dispAlamat").html(texts);

Semak Key di Dalam Array

Friday, February 19, 2016

Apabila telah disetkan key dan value bagi sesuatu array, value array tersebut boleh dipanggil menggunakan key yang telah dikenalpasti.

Sekiranya key yang diberikan tidak dikenali, akan mendatangkan error pada coding.

Jadi, bagi mengatasi masalah ini, setiap key yang dimasukkan, perlu disemak terlebih dahulu adakah ia wujud. Gunakan fungsi in_array yang PHP sediakan.

Dilihat pada contoh di bawah, pada satu table, terdapat senarai PTJ untuk dirujuk.


+------------+--------------------------------+
| kod_ptj    | nama_ptj                       |
+------------+--------------------------------+
| 123456789  | SEKTOR PENJAGAAN KULIT         |
| 987654321  | BAHAGIAN PENGURUSAN KEWANGAN   |
| 121212312  | BAHAGIAN PENGURUSAN MAKANAN    |
| 345345345  | BAHAGIAN PENGURUSAN PERJALANAN |
| 678678678  | BAHAGIAN PENGURUSAN TANGISAN   |
+------------+--------------------------------+


Select yang pertama untuk dapatkan data tersebut dan dimasukkan ke dalam array.

Kemudian, select senarai data yang dimahukan beserta kod PTJ. Kod tersebut boleh digunakan untuk memaparkan nama PTJ.

Masalah timbul sekiranya dalam senarai tersebut, ada beberapa kod yang tiada di dalam table rujukan di atas. Jadi, array tidak dapat mengesan apa-apa data dan menganggap ianya adalah error.

Apa yang boleh dibuat, sebelum memaparkannya, sila semak terlebih dahulu menggunakan in_array.


<?php 
$sqlptj = "SELECT untuk dapatkan kod PTJ dan nama PTJ";
$resultptj = mysql_query($sqlptj);
while($rowptj = mysql_fetch_array($resultptj))
{
 $kodptj = $rowptj["pt_kod_ptj"];
 $namaptj["$kodptj"] = $rowptj["pt_nama_ptj"];
}

$sql3 = "SELECT semua data dan salah satu data tersebut ada kod PTJ";
$result3 = mysql_query($sql3);
while($row3 = mysql_fetch_array($result3))
{
 $kodptjp = $row3["kr_ptj"];
 $displayptj = "";
 
 if (in_array($namaptj["$kodptjp"], $namaptj)) {
  $displayptj = $namaptj["$kodptjp"];
 } 
 else { 
  $displayptj = "<span class=\"label label-sm label-warning\">".$kodptjp."</span>";
 }
?>
<tr>
 <td><?php echo $row3["xxx"]; ?></td>
 <td><?php echo $row3["xxy"]; ?></td>
 <td><?php echo $row3["$xxz"]; ?></td>
 <td><?php echo $displayptj; ?></td>
</tr>
<?php 
}
?>

Selain menggunakan in_array, boleh juga menggunakan array_key_exists. Cara menggunakannya juga sama. Jika menggunakan contoh code di atas, berikut adalah cara menggunakannya.


<?php
//copy code di atas
//code asal guna in_array
if (in_array($namaptj["$kodptjp"], $namaptj)) {
  $displayptj = $namaptj["$kodptjp"];
} 

//code checking guna key exist. Terus check key, bukan check value
if (array_key_exists($row3["kr_ptj"], $namaptj)) {
    echo "Key untuk array ini telah wujud";
}

Bezanya in_array lebih kepada semakan terhadap value, manakala array_key_exists menyemak key atau index di dalam satu array.

Rollback Restore Last Data

Nota: logid = history ID untuk table history atau table log yang digunakan dalam post ini.

Sambungan post sebelum ini, Rollback Backup Data Secara Manual

Sebelum ini kita membuat rollback merujuk kepada ID backup data (logid) di mana ID itu sudah di pilih siap-siap.

Kali ini, kita lihat bagaimana untuk rollback data yang terakhir sahaja di mana logid tidak diketahui yang mana satu. Bagi mendapatkan logid terakhir, gunakan carian pada timestamp.

Pada contoh ini, kita menganggap ID untuk original data telah diberikan. Dapatkan logid menggunakan SQL.


<?php 
$pkid = $_GET['pkid'];
$logid="";

$sql3 = "SELECT a.logid, a.id, a.timestamp FROM data_log a 
   WHERE a.id='$pkid' 
   AND a.timestamp=(SELECT MAX(a1.timestamp) 
   FROM data_log a1 
   WHERE a1.id='$pkid')";
$result3 = mysql_query($sql3);
while($row3 = mysql_fetch_array($result3))
{
 $logid = $row3["logid"];
}
?>

Setelah logid diperoleh, lakuan arahan seperti yang ditunjukkan pada post sebelum ini.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<?php 
$result = mysql_query("SELECT * FROM data_log limit 1");
if (!$result) {
    die("Query to show fields from table failed");
}

$sql_rollback = "UPDATE data SET ";

$fields_num = mysql_num_fields($result);
//echo "fields_num=".$fields_num;
for($i=3;  $i<$fields_num; $i++)
{
    $field = mysql_fetch_field($result, $i);
//    echo "{$field->name}".$i."<br>";    
}

$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);
//0 = running LogID 
//1 = Activity log 
//2 = ID for ori table
//3 ~ n = data
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]."', ";
 }
 //echo $row2[$i]; 
}
$field_id = mysql_fetch_field($result, 2);
$sql_rollback .=" WHERE {$field_id->name} = '".$row2[2]."'";
$resultrb = mysql_query($sql_rollback);
?> 

Membandingkan Antara Data Semasa dan Sebelum

Wednesday, February 17, 2016

Paparkan senarai data, di mana baris data di atas, adakah sama dengan data di bawahnya.

Dalam contoh di bawah, jika data di bawah adalah sama seperti di atas, table tidak perlu diwarnakan.

Jika sebaliknya, letakkan warna supaya pengguna perasan akan perubahan data yang berlaku.

Caranya, jalankan satu SQL untuk satu table yang hendak dipantau akan perubahannya.
Sebelum data tu dikeluarkan menggunakan while(), declare siap-siap color code html untuk table.
Declare juga data untuk $current dan $previous.

Kemudian, setiap kali panggil data di dalam while(), buat perbandingan antara $current dan $previous.

Setelah dapat hasilnya, dan sebelum tutup while() {}, berikan nilai $previous sama seperti nilai $current. Kerana ia akan digunakan apabila membuat semakan data yang seterusnya.

<?php
$sql3 = "SELECT bla bla bla";
$result3 = mysql_query($sql3);
$previousd1 = ""; 
$currentd1="";
$bgwarnad1 = "bgcolor=\"#F7FE2E\"";

while($row3 = mysql_fetch_array($result3))
{
 $currentd1 = $row3["data1"];
 if ($currentd1 === $previousd1) {
   $bgwarnad1 = "";
 }
?>
<tr>
 <td><?php echo $row3["id"]; ?></td>
 <td><?php echo $row3["timestamp"]; ?></td>
 <td <?php echo $bgwarnad1; ?>><?php echo $row3["data1"]; ?></td>
 <td><?php echo $row3["data2"]; ?></td>
 <td><?php echo $aktiviti["$akt"]; ?></td>
 <td><a href="rollback_item.php?logid=<?php echo $row3["logid"]; ?>" class="btn btn-success btn-sm mlm mrm"><i class="fa fa-history"></i>&nbsp;Rollback</a></td>
</tr>
<?php 
$previousd1 = $currentd1;
$bgwarnad1 = "bgcolor=\"#F7FE2E\"";
}
?>
 </tbody>
</table>  

 Hasilnya akan dapat seperti ini



Rollback Backup Data Secara Manual

Tuesday, February 16, 2016

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:
  1. Dapatkan nama field yang mahu diupdate dari table data_log
  2. Sediakan SQL query untuk UPDATE table data
  3. Dapatkan nilai setiap data terlibat pada table data_log guna logid=6
  4. Cantumkan dapatan di langkah (1) dan (3) ke dalam SQL query di langkah (2) menjadi SQL yang lengkap.
  5. Jalankan SQL query tersebut untuk membuat kemaskini.
Secara programmingnya begini,

<?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.

Loading PHP-Ajax Progress Bar

Monday, February 15, 2016

Biasanya, untuk loading proses, kita akan gunakan ajax $(document).ajaxStart(function() dan form post seperti sebelum ini. Selagi proses sedang berjalan, kita akan tunggu dengan dipaparkan animated gif sahaja.

Tetapi sekiranya kita mahu melihat status proses yang sedang berlaku dalam bentuk persen, kita perlu semak status selang beberapa masa. Mungkin setiap 1 saat. Kaedah ini diolah dari post asal di sini.

Bagi menjalankan proses ini, beberapa file perlu diwujudkan.

1. Database table untuk status.
2. File index.php untuk paparan utama.
3. File javascript jQuery terkini.
4. File config.php untuk connect ke database.
5. File process.php bagi menjalankan proses.
6. File checker.php bagi menyemak status setiap selang masa.

Secara ringkasnya begini,

1. Database table untuk status.

Bina satu table di mana table tersebut akan menyimpan jumlah keseluruhan data yang berkaitan, jumlah data yang sedang di proses, dan status proses itu sendiri. Table ini akan selalu dikemaskini oleh process.php dan disemak dengan kerap oleh checker.php.

CREATE TABLE `main_issue` (
  `issue_id` int(11) NOT NULL,
  `issue_title` varchar(120) NOT NULL,
  `issue_operating` int(1) NOT NULL DEFAULT '0' COMMENT '0=free, 1=operating',
  `issue_opscurr` int(11) NOT NULL COMMENT 'current operation',
  `issue_total` int(11) NOT NULL COMMENT 'total operation'
);

ALTER TABLE `main_issue`
  ADD PRIMARY KEY (`issue_id`);

issue_operating : Jika nilainya 0, process telah selesai. Jika nilainya 1, proses sedang berjalan. Ini bagus bagi mengawal perintah proses baru ketika proses sediada sedang berjalan.

issue_opscurr : Nilai ini akan ditambah setiap masa. Bermula dengan 0, sehinggalah cukup kesemuanya. process.php akan update setiapkali gelung selesai berpusing dan checker.php akan semak nilai di sini pada setiap selang masa.

issue_total : Nilai ini akan diupdate kali pertama oleh process.php setelah dikenalpasti jumlah data yang hendak di process. Jadi, dengan nilai jumlah keseluruhan ini, mudahlah mahu buat kiraan dalam persen nanti.

 

2. File index.php paparan utama

Disinilah kita akan paparkan progress-bar, suruh process dibelakang buat kerja, dan check status setiap sela masa (untuk contoh ini, setiap 1 saat).
<?php
session_start();
?>
<!DOCTYPE html>
<html>
<head>
  <title>Progress Bar</title>
  <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
  <style>
    #progress {
      width: 500px;
      border: 1px solid #aaa;
      height: 20px;
    }
    #progress .bar {
      background-color: #ccc;
      height: 20px;
    }
  </style>
</head>
<body>
  <div id="progress"></div>
  <div id="information"></div>
  
  <script>
    var timer;

    function refreshProgress() {
      $.ajax({
        url: "checker.php",
        success:function(data){
          $("#progress").html('<div class="bar" style="width:' + data.percent + '%"></div>');
    //$("#progress").html('<progress max="100" value="' + data.percent + '"></progress>');
    $("#information").html("[ " + data.percent + "% ] " + data.message);
          if (data.percent == 100) {
            window.clearInterval(timer);
            timer = window.setInterval(completed, 1000);
          }
        }
      });
    }

    function completed() {
      $("#message").html("Completed");
    //$("#progress").hide();
    window.clearInterval(timer);
    }

    // Apabila page di buka. Sama seperti onload
    $(document).ready(function(){
      // Trigger proses di web server.
      $.ajax({url: "process.php"});
      // Refresh setiap 1 saat, dan panggil function refreshProgress di atas.
      timer = window.setInterval(refreshProgress, 1000);
    });
  </script>
</body>
</html>

 

3. File jquery

File jquery boleh dipanggil terus melalui web, atau download siap-siap dan panggil pada folder sahaja.

<head>
  <title>Progress Bar</title>
  <!-- Dapatkan jquery dari google -->
  <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
  <!-- ATAU, dapatkan dari local sendiri. Tapi pastikan filenya ada. -->
  <script src="jquery-1.11.2.min.js"></script>
  

 

Jangan guna kedua-dua sekaligus. Pilih salah satu.

 

4. File config.php connect database

File config.php ini cuma setting database connection. Jika tak ada pun, boleh sahaja gunakan code connection terus pada file PHP yang memerlukannya. File config ini sekadar memudahkan code connection sahaja. Cuma include jika memerlukan.

<?php
$con = mysql_connect("localhost", "root", "", true);  
if (!$con)
{
  die('Could not connect MySQL-Internal : ' . mysql_error());
}
mysql_select_db("midataclean", $con);

?>

 

5. File process.php

Bagi menjalankan proses php di background. Ajax cuma akan beri arahan untuk process.php buat kerja.

<?php
include('config.php');
session_start();

$sqla = "SELECT issue_operating FROM main_issue WHERE issue_id = 1";
$resa = mysql_query($sqla, $con) or trigger_error("Query failed!: ".$sqla);
while ($row = mysql_fetch_array($resa, MYSQL_ASSOC))
{
 $iss_operating = $row['issue_operating'];
}

if($iss_operating == '0') {
 $sql ="SELECT * FROM table WHERE 1";
 $result = mysql_query($sql,$con);
 $total = mysql_num_rows($result);
 // The example total processes. Dapatkan $total dari database.
 //$total = 20;

 //Update status database. Jumlah dan status sedang beroperasi
 $sql ="UPDATE main_issue SET issue_total='".$total."', issue_operating='1' WHERE issue_id='1'";
 $result = mysql_query($sql,$con);
  
 // Pusingan loop
 for($i=1; $i<=$total; $i++){
   // Calculate the percentation
   $percent = intval($i/$total * 100);
   
   //UPDATE/DELETE/INSERT database jika mahu buat sesuatu
   //atau sekadar SELECT satu persatu data.
   $sqlb ="UPDATE pengguna SET pengguna_level ='5' WHERE pengguna_id ='".$i."'";
   $resultb = mysql_query($sqlb,$con);
      
   //Nilai semasa yang sedang looping, update counter terkini ke dalam field
   $sqla ="UPDATE main_issue SET issue_opscurr = '".$i."' WHERE issue_id='1'";
   $resulta = mysql_query($sqla,$con);

   // Jika kiraan nilai semasa sudah sama banyak dengan total, bolehlah update status operasi = 0. Iaitu status dah selesai.
  if($i==$total) {
     //update database sekali
     $sqlu ="UPDATE main_issue SET issue_operating='0' WHERE issue_id='1'";
     $resultu = mysql_query($sqlu,$con);
  }
  
   // Sleep one second so we can see the delay
   // Jika data banyak, tak perlu sleep. 
   // Sleep sekadar nak visualize di index.php sebab data sikit, progress bolehlah nampak berjalan perlahan.
   sleep(1); //1 second
   //usleep(100000); //0.1 second 
 }
}
?>

 

6. File checker.php

Checker.. data dalam bentuk JSON.

<?php
// The file has JSON type.
header('Content-Type: application/json');

include('config.php');

$sql = "SELECT issue_operating, issue_opscurr, issue_total FROM main_issue WHERE issue_id = 1";
$res = mysql_query($sql, $con) or trigger_error("Query failed!: ".$sql);
while ($row = mysql_fetch_array($res, MYSQL_ASSOC))
{
 $iss_operating = $row['issue_operating'];
 $iss_opscurr = $row['issue_opscurr'];
 $iss_total = $row['issue_total'];
}

$percent = intval($iss_opscurr/$iss_total * 100);
$msg = $iss_opscurr."/".$iss_total." rekod sedang diproses.";
echo json_encode(array("percent" => $percent, "message" => $msg));

?>

MySQL Trigger Mudah

Bagi table yang kita mahu pantau setiap data yang berubah, kita boleh menggunakan fungsi TRIGGER yang disediakan oleh database.

Kita ambil contoh,
Table: data
Fields: data1 dan data2.

Jadi, setiap perubahan pada table data dan field yang ada di dalamnya, akan kita rekodkan ke satu table lagi, iaitu table log atau history.

Cipta table Data

 CREATE TABLE data (  
       id  INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,  
       timestamp  TIMESTAMP,  
       data1 VARCHAR(255) NOT NULL,  
       data2 DECIMAL(5,2) NOT NULL   
 );  

Cipta table data_log
 CREATE TABLE data_log (  
       histroyid INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,  
       action ENUM('I','U','D'),  
       id INT UNSIGNED NOT NULL,  
       timestamp TIMESTAMP,  
       data1 VARCHAR(255) NOT NULL,  
       data2 DECIMAL(5,2) NOT NULL   
 );  
Table data_log ini ada sedikit penambahan field iaitu:-
historyid = running number untuk table data_log itu sendiri
action = yang hanya akan menyimpan nilai I, U dan D. Insert, Update dan Delete.
timestamp = menyimpan rekod bila aktiviti tersebut dilakukan.

Selebihnya, duplikasi dari table asal.

Buat 3 jenis trigger untuk INSERT, UPDATE dan DELETE.

 DELIMITER $$  
 CREATE TRIGGER ai_data AFTER INSERT ON data  
      FOR EACH ROW  
      BEGIN  
       INSERT INTO data_log (action,id,timestamp,data1,data2)  
       VALUES('I',NEW.id,NOW(),NEW.data1,NEW.data2);  
      END$$  
 CREATE TRIGGER au_data AFTER UPDATE ON data  
      FOR EACH ROW  
      BEGIN  
       INSERT INTO data_log (action,id,timestamp,data1,data2)  
       VALUES('U',NEW.id,NOW(),NEW.data1,NEW.data2);  
 END$$  
 CREATE TRIGGER ad_data AFTER DELETE ON data  
      FOR EACH ROW  
      BEGIN  
       INSERT INTO data_log (action,id,timestamp,data1,data2)  
       VALUES('D',OLD.id,NOW(),OLD.data1,OLD.data2);  
 END$$  


Pada trigger INSERT dan UPDATE, kita masih boleh panggil data baru dan lama (NEW.xxx atau OLD.xxx). Tetapi pada trigger DELETE, cuma panggil data lama sahaja, kerana tiada sebarang data baru di sini.

Jika jalankan arahan menggunakan PhpMyAdmin, pada input Delimeter tu (yang berada di input bawah sekali selepas field SQL), setkan siap-siap untuk guna simbol $$. Ia bertujuan untuk kita running serentak arahan create trigger tadi.



Sekarang, dah boleh mula membuat sebarang aktiviti pada table data, sama ada nak insert, update dan delete. Dan lihat hasilnya pada table data_log.

-----------------------------

Sekiranya terlalu banyak column/field, agak leceh untuk buat table log. Kena taip satu-persatu field tiru yang sedia ada. Apa yang boleh di buat,
  1. Create table serupa dengan table asal
  2. tambah kemudian field untuk pantauan seperti logid, timestamp dan action.
  3. susun semula kedudukan setiap field yang baru ditambah, letak di tempat pertama.


//1. Create table history serupa dengan table asal.
//Cara ini akan duplicate table asal beserta dengan datanya sekali (jika ada).
CREATE TABLE data_log AS SELECT * FROM data;

//2. Tambah field asas untuk table history
//Bagi field yang disetkan AUTO_INCREMENT, data akan masuk secara automatik sekiranya sudah ada baris data yang asal.
ALTER TABLE data_log ADD logid INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY;
ALTER TABLE data_log ADD timestamp TIMESTAMP;
ALTER TABLE data_log ADD action ENUM('I','U','D');

//3. Susun semula kedudukan field
//Untuk history ID, letakkan di tempat pertama
ALTER TABLE `data_log` CHANGE `logid` `logid` INT(15) UNSIGNED NOT NULL AUTO_INCREMENT FIRST;

//Untuk lagi dua field, letakkannya selepas itu.
ALTER TABLE `data_log` CHANGE `timestamp` `timestamp` TIMESTAMP on update CURRENT_TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP AFTER `logid`;
ALTER TABLE `data_log` CHANGE `action` `action` ENUM('I','U','D') CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL AFTER `timestamp`;

//Update nilai 'I' pada data yang sudah sediada.
UPDATE `data_log` SET `action` = 'I';

Nota: Penggunaan nama `timestamp` dan `action` tidak sesuai digunakan. Jika ada perkataan yang lain, gunakanlah. Mungkin boleh guna `actiontime` dan `operation` atau `process`. Cari perkataan yang tidak digunakan secara standard dalam MySQL.