|
PHP ตรวจสอบโครงสร้างฐานข้อมูล MySQL กรณีอัพเดตเวอร์ชั่นของโปรแกรมที่พัฒนา |
PHP ตรวจสอบโครงสร้างฐานข้อมูล MySQL กรณีอัพเดตเวอร์ชั่นของโปรแกรมที่พัฒนา หลายครั้งที่อัพเดตเวอร์ชั่น มักจะลืมแก้ไขบางฟิลด์ หรือหากเวอร์ชั่นใหม่ ต้องแก้ฟิลด์จำนวนมาก จะเสียเวลามานั่งไล่แก้โครงสร้างตามที่บันทึกไว้
ครั้นจะใช้โครงสร้างใหม่ แล้ว dump ข้อมูลเดิมใส่ ก็ทำได้ยาก เพราะทำผ่านเน็ตจะช้ามากๆ กรณีข้อมูลเป็น GB จะนั่งรอกันเป็นวัน ^^"
ด้วยเหตุนี้เลยนั่งเขียนสคริปต์ PHP ที่ใช้อัพเดตโครงสร้างฐานข้อมูลขึ้นมาใช้งาน ไหนๆ ก็ต้องนั่งรอ dump ข้อมูลใหม่ หรือนั่งไล่แก้ทีละฟิลด์อยู่แล้ว
ลองนำไปประยุกต์ใช้ดูนะครับ
Download
ตัวอย่างโค๊ดหลัก
Code (PHP)
<?php
/*------------------------------------------------------------------------------
** File : check_database.php
** Description : ตรวจสอบฐานข้อมูล เพื่อเปรียบเทียบฟิลด์ที่ต่างกันของฐานข้อมูลที่ใช้จริง กับโครงสร้างฐานข้อมูลใหม่ (ฐานข้อมูลที่พัฒนาต่อเนื่อง)
** Author : Songchai Saetern
** Email: [email protected]
** Homepage : http://sunzandesign.blogspot.com
** Modify : 2013-04-27
**
** Rev History
**------------------------------------------------------------------------------
** 2011-08-22 สร้างครั้งแรก
** 2013-04-27 อัพเดตหน้าล็อกอิน
**
*/
session_start();
header("Content-type: text/html; charset=utf-8");
require_once 'function/general.php';
$pageview = true;//แสดงผลแบบแบ่งหน้า
$selfpage = $_SERVER['PHP_SELF'];
//แหล่งข้อมูล
$num_check = 3;//จำนวนฐานข้อมูลที่จะเช็ก
$title = 'ตรวจสอบฐานข้อมูลเปรียบเทียบข้อแตกต่าง ก่อนการอัพเดตเวอร์ชั่นของโปรแกรม';
//COMMENT NOT DISPLAY ON INDEX PAGE
$howto = <<<HOWTO
1. เลือกฐานข้อมูลที่ต้องการเปรียบเทียบโครงสร้าง ด้านซ้ายคือโครงสร้างฐานข้อมูลเวอร์ชั่นใหม่ ด้านขวาให้เลือกฐานข้อมูลจริงที่ใช้อยู่ปัจจุบัน
2. เมื่อคลิกปุ่ม "Start" จะทำการดึงข้อมูลตารางทั้งหมดจากฐานข้อมูลที่เลือกมาเปรียบเทียบกัน และแสดงให้เห็นว่ามีตารางที่ไม่ตรงกันกี่ตัว
3. ใต้ชื่อตารางจะมีชื่อฟิลด์ที่ไม่ตรงกันปรากฏให้เห็น ซึ่งจะแสดงเฉพาะฟิลด์ที่มียังไม่มีในเทเบิลเดิม หรือฟิลด์ที่ Type หรือ Comment ไม่ตรงกันเท่านั้น
4. เมื่อคลิก "UPDATE STRUCTURE" สคริปต์จะปรับโครงสร้างฐานข้อมูลที่ใช้จริง ให้เหมือนโครงสร้างฐานข้อมูลตัวใหม่ (สร้างตาราง และเพิ่มฟิลด์ที่ไม่ครบเท่านั้น ที่เหลือย้อนกลับไปเช็กอีกรอบจะเหลือคอมเมนต์ หรือชนิดข้อมูลที่ต้องปรับเพิ่มเอง)
5. คลิก "ย้อนกลับ" ไปตรวจสอบอีกที เพื่อดูรายการที่ยังไม่ได้อัพเดต ให้อัพเดตเอง
HOWTO;
$howto = nl2br(str_replace("\t"," ",$howto));
//MAIN TAG
echo <<<HTML
<html>
<head>
<title>$title</title>
<script src="js/jquery-1.4.2.min.js" type="text/javascript"></script>
<link rel="stylesheet" href="css/style.css" type="text/css" />
<script type="text/javascript">
function add_option(){
var option = $('#select_option').val();
var no = $('select[name="db_source[]"]').length + 1;
var row = "<tr bgcolor='white'><td>"+no+"</td>";
row += "<td><select name='db_source[]'><option value=''>- เลือกฐานข้อมูล -</option>"+ option +"</select></td>";
row += "<td><select name='db_target[]'><option value=''>- เลือกฐานข้อมูล -</option>"+ option +"</select></td></tr>";
$("#tb_option").append(row);
}
</script>
</head>
<body>
<div style="width: 1024px;margin: auto;">
<h3 align="center" style="text-decoration:underline">$title</h3>
<div style="color:blue"><b>:: การทำงานของสคริปต์ ::</b>
<div style="color:#000066;border:1px dashed #0033CC;padding: 5px;background:#eeeeee">$howto</div></div><br>
<div align="center">
<a href="$selfpage" style="color:green;border:1px solid brown;background:orange;text-decoration:none;padding:5px"><<< หน้าหลัก >>></a>
<a href="$selfpage?logout" style="color:green;border:1px solid brown;background:orange;text-decoration:none;padding:5px">Log out</a>
</div><br>
<div id="content">
HTML;
//--end MAIN
$warning = '<h4 style="color:red" align="center">* กรุณาแบ็กอัพข้อมูล และทดสอบกับฐานข้อมูลทดสอบก่อนนำไปใช้จริง เพื่อป้องกันข้อผิดพลาด <br/>(คุณสามารถ แก้ไขโครงสร้างด้วยตนเอง ตามข้อมูลในหน้าเปรียบเทียบโครงสร้าง</h4>';
if(isset($_GET['logout'])){
$_SESSION['user']='';
}
if($_SESSION['user']=='' && $_POST['user']==''){
$user = $_SESSION['user'];if($user==''){$user='root';}
$pass = $_SESSION['pass'];if($pass==''){$pass='123456';}
echo '<div align="center">
<form action="'.$_SERVER['PHP_SELF'].'" method="post">
<font color="green"><u>ตั้งค่าฐานข้อมูลที่ต้องการใช้งาน</u></font><br>
host : <input type="text" name="host" value="localhost"><br>
User : <input type="text" name="user" value="'.$user.'"><br>
Pass : <input type="password" name="pass" value="'.$pass.'"><br>
<input type="submit" name="submit" value="เริ่มใช้งาน"><br>
</form>
</div>';
echo $warning;
exit();
}else if($_POST['user']){
$_SESSION['host'] =$_POST['host'];
$_SESSION['user'] = $_POST['user'];
$_SESSION['pass'] = $_POST['pass'];
}
define("DBHOST", $_SESSION['host']);
define("DBUSER", $_SESSION['user']);
define("DBPASS", $_SESSION['pass']);
$connect = @mysql_connect(DBHOST, DBUSER, DBPASS) or show_error( __FILE__,__LINE__, 'Connection error.' );
mysql_query("SET NAMES UTF8");
$operator = $_GET['operator'];
if($operator=='')//default
{
//ลิสต์ฐานข้อมูล
$dbSQL = "SHOW DATABASES";
$dbResult = mysql_query($dbSQL) or show_error(__FILE__, __LINE__, $dbSQL);
while($dbRec = mysql_fetch_assoc($dbResult)){
if(++$n % 2){$bg = '#fff';}else{$bg='#f7f7f7';}
$dbOption .= "<option value='$dbRec[Database]' style='background:$bg;'>$dbRec[Database]</option>";
}
$database = '<option value="">- เลือกฐานข้อมูล -</option>'.$dbOption;
mysql_free_result($dbResult);
unset($dbRec);
echo '<div style="width:50%; margin: auto"><b>New_structure</b> = โครงสร้างฐานข้อมูลใหม่ <br/><b>Old_structure</b> = ฐานข้อมูลที่ใช้จริง (ฐานข้อมูลที่ต้องการอัพเดต)</div>';
echo '<form action="'.$selfpage.'?operator=start_check" method="POST">
<table align="center" width="50%">
<tr>
<td>
<table id="tb_option" width="100%" align="center" class="" border="0" cellpadding="5" cellspacing="1" bgcolor="#cccccc">';
$th_option = array('fieldname'=>'yes','tag'=>'th','custom'=>array('bgcolor'=>'saddlebrown','style'=>'color:white'));
$tr_option = array('attr'=>array('bgcolor'=>'#ffffff'));
$td_option = array(
'New_structure'=>array('style'=>''),
'Old_structure'=>array('style'=>'')
);
$dropdown = array();
for($i=0;$i<$num_check;$i++)//สร้างตัวเลือกเปรียบเทียบตามจำนวนที่ระบุ
{
++$a['No'];
$dropdown['New_structure'] = '<select name="db_source[]"><option value="">- เลือกฐานข้อมูล -</option>'.$dbOption.'</select>';
$dropdown['Old_structure'] = '<select name="db_target[]"><option value="">- เลือกฐานข้อมูล -</option>'.$dbOption.'</select>';
$arr = array_merge($a, $dropdown);//ใส่คอลัมน์ NO ไว้ด้านหน้า
if($a['No']==1){
echo gen_tr($arr,$th_option,$td_option);
}
echo gen_tr($arr,$tr_option);
}
echo '</table>
</td>
</tr>
<tr>
<td align="center">
<textarea id="select_option" style="display:none">'.$dbOption.'</textarea>
<input type="button" value=" + เพิ่มตัวเลือก " style="color:orangered;font-weight:bold;height:40px;font-size:15px" onclick="add_option();">
<input type="submit" value=" Start Check " style="color:green;font-weight:bold;height:40px;font-size:15px"/>
</td></tr>
</table>
</form>
';
}
else if($operator=='start_check') //เริ่มการตรวจสอบ
{
$source = $_POST['db_source'];
$target = $_POST['db_target'];
if(empty($source[0]) || empty($target[0])){echo '<h1 align="center">ฐานข้อมูลที่เลือกไม่ครบ</h1>';exit();}
//ไม่มีผลกับอัพดับของ dropdown
$all_db = array_merge($source,$target);//มีปัญหาเรื่อง array ทับกัน
$all_db = array_unique($all_db);//ถ้าเป็นฐานข้อมูลเดียวกันก็ได้เทเบิลตรงกัน
sort($all_db);//เรียง key ใหม่
//TEST
/*
echo '<br>SOURCE :: ';
print_r($source);
echo '<br><br>TARGET :: ';
print_r($target);
echo '<br><br>MERGE :: ';
print_r($all_db);
echo '<br><br>';
*/
//โครงสร้างใหม่
$arr = array();
$count = count($all_db);
for($i=0;$i<$count;$i++){
$db = $all_db[$i];
if($db){
$sql = "SHOW TABLES FROM $db";
$result = mysql_query($sql) or show_error(__FILE__, __LINE__, $sql);
while($rs = mysql_fetch_array($result)){
$table = $rs[0];
$arr[$db]['table'][$table] = $table;
$sql = "SHOW FULL COLUMNS FROM $db.$table";
$res = mysql_query($sql) or show_error(__FILE__, __LINE__, $sql);
while($field = mysql_fetch_assoc($res)){
$arr[$db.$table]['field'][$field['Field']] = $field;
}
}
}
}//for
$no=0;
$data = array();
echo '<br><form action="'.$selfpage.'?operator=start_update_structure" onsubmit="if(confirm(\' ยืนยันการปรับปรุงโครงสร้างฐานข้อมูล?\n\n หากทดสอบกับฐานข้อมูลทดสอบจนแน่ใจ คลิกตกลงเพื่อ ยืนยัน \n หากยังไม่ได้ทดสอบการทำงาน และไม่แน่ใจ คลิก ยกเลิก \n\n (คุณสามารถ แก้ไขโครงสร้างด้วยตนเอง ตามข้อมูลที่ปรากฏด้านบน )\')==true){return true;}else{return false;}" method="POST">';
echo '<font color="red" style="font-size:15px;"><b>* การอัพเดต จะใช้ข้อมูลจาก <b style="color:blue">ด้านซ้าย</b> >> <b style="color:magenta">ด้านขวา</b> ตรวจสอบให้แน่ใจว่าตารางด้านซ้ายและขวา เป็นตารางที่เชื่อมโยงกัน</b></font>';
echo '<table id="" class="" border="0" cellpadding="5" cellspacing="1" bgcolor="#cccccc">';
echo '<tr bgcolor="saddlebrown">
<th align="right">DB</th>
<th align="right">TB</th>
<th><span>โครงสร้างฐานข้อมูลใหม่</span></th>
<th><span>ฐานข้อมูลเดิม(ที่ใช้อยู่ปัจจุบัน)</span></th>
<th></th>
</tr>';
foreach ($source as $key=>$db1){
$no++;
$db2 = $target[$key];
if($db1){
$tb_db1 = $arr[$db1]['table'];
$tb_db2 = $arr[$db2]['table'];
//echo '<br>1=>';print_r($arr[$db1]['table']);echo '<br>';
//echo '<br>2=>';print_r($arr[$db2]['table']);echo '<br>';
$arrr = array_merge($tb_db1,$tb_db2);
$s_no = 0;
echo '<tr bgcolor="#cccccc">
<th align="">'.$no.'</th>
<th align=""></th>
<th><span style="color:blue;font-size:16px">'.$db1.'</span></th>
<th><span style="color:blue;font-size:16px">'.$db2.'</span></th>
<th>หมายเหตุ</th>
</tr>';
$db_update = '';
$field_data = '';
$tb1_field = '';
foreach($arrr as $tb=>$tb1_name){
$s_no++;
$sub_no = $no.'.'.$s_no;
$tb1_name = $arr[$db1]['table'][$tb];
$tb2_name = $arr[$db2]['table'][$tb];
$style1 =$style2 = 'color:green;font-weight:bold;';
$check_field1 = $check_field2 = '';
$sign = '';
$remark = '<br>';
$tb_remark = '<br>';
$db_update = '';
$field_data = '';
if($tb2_name != $tb1_name){
if($tb1_name==''){
$style1 = "color:#556B2F;";
$style2 = 'color:blue;';
$tb1_name = $tb2_name;
$tb_remark = '<div style="color:blue" style="line-height:20px;"> * แสดงให้เห็นเท่านั้น ไม่จำเป็นต้องอัพให้เหมือนเวอร์ชั่นที่ใช้อยู่ </div>';
}
if($tb2_name==''){
$style1 = 'color:#333333;';
$style2 = "color:red;";
$tb2_name = $tb1_name;
//จะสร้างตารางเฉพาะโครงสร้างปัจจุบันเท่านั้น
$db_update = '<input type="text" name="new_table['.$db1.'.'.$tb1_name.']" value="'.$db2.'.'.$tb2_name.'" style="display:none">';
$tb_remark = '<div style="color:red" style="line-height:20px;">* สร้างตารางเพิ่ม</div>';
}
}else{//ถ้าตรงกัน ให้ตรวจสอบฟิลด์
$remark = '';
$tb1_field = '';
$tb1_field = $arr[$db1.$tb1_name]['field'];
$tb2_field = $arr[$db2.$tb2_name]['field'];
$count_field = '';
$field_c1 = count($tb1_field);
$field_c2 = count($tb2_field);
if($field_c1 != $field_c2){
$style1 = 'color:orangered;font-weight:bold;';
$style2 = 'color:orangered;font-weight:bold;';
$count_field = '<div style="color:blue" style="line-height:20px;">!!จำนวนฟิลด์ไม่เท่ากัน อาจทำให้เทเบิล LOG ที่เชื่อมโยงกัน เกิดปัญหาได้</div>';
$check_field1 .= '<div style="line-height:20px;"> จำนวนฟิลด์ <font color="magenta">'.$field_c1.'</font></div>';
$check_field2 .= '<div style="line-height:20px;"> จำนวนฟิลด์ <font color="magenta">'.$field_c2.'</font></div>';
}
foreach ($tb1_field as $name=>$dArr){
$no_math=false;
$field1 = $dArr['Field'];
$field2 = $arr[$db2.$tb2_name]['field'][$name]['Field'];
$f2 = $arr[$db2.$tb2_name]['field'][$name];
$remark1 = $remark2 = '';
if($field1!=$field2){
$no_math = true;
$color = "red";
if($field1==''){
$field1 = $field2;
}else if($field2==''){
$field2 = $field1;
$field_data .= '<input type="text" name="new_field['.$db1.'.'.$tb1_name.'@'.$field1.']" value="'.$db2.'.'.$tb2_name.'" style="display:none">';
}
$ch1=$ch2= '->NEW!! ';
$remark .= '<div style="color:blue;line-height:20px;">** เพิ่มฟิลด์</div>';
}else{
$ch1=$ch2='';
$color = "blue";
if($dArr['Type'] != $f2['Type']){
$ch1 = $dArr['Type'];
$ch2 = $f2['Type'];
$remark1 = '*** ชนิดของฟิลด์ไม่ตรงกัน';
}
if($dArr['Comment'] != $f2['Comment'] && $dArr['Comment']!=''){
$ch1 .= '[Comment='.$dArr['Comment'].']';
$ch2 .= '[Comment='.$f2['Comment'].']';
$remark2 = '**** Comment ฟิลด์ไม่ตรงกัน ';
}
if($ch1 || $ch2 ){
$no_math = true;
$remark .= '<div style="color:blue" style="line-height:20px;">'.$remark1.$remark2.'</div>';
$field_data .= '<input type="text" name="change_field['.$db1.'.'.$tb1_name.'@'.$field1.']" value="'.$db2.'.'.$tb2_name.'" style="display:none">';
}
}
if($no_math){
$check_field1 .= $sign.'<div style="line-height:20px;">'.$field1.' <font color="magenta">'.$ch1.'</font></div>';
$check_field2 .= $sign.'<div style="line-height:20px;">'.$field2.' <font color="magenta">'.$ch2.'</font></div>';
//$sign = ', ';
}
//$field_data = json_encode($dArr);
//echo "<br>$tb1_name :::> FIELD :: $field1==$field2";
//echo '<br>';print_r($dArr);
}
if($check_field1){
$check_field1 = '<span style="color:'.$color.'"><b>* '.$check_field1.'</b></span>';
}
if($check_field2){
$check_field2 = '<span style="color:'.$color.'"><b>* '.$check_field2.'</b></span>';
}
}//else if
$data['New_structure'] = $db1.'.'.$tb1_name;
$data['Old_structure'] = $db2.'.'.$tb2_name;
echo '<tr bgcolor="white">
<td valign="top">'.$db_update.$field_data.'</td>
<td valign="top">'.$sub_no.'</td>
<td valign="top"><span style="'.$style1.'">'.$db1.'.'.$tb1_name.'</span>'.$check_field1.'</td>
<td valign="top"><span style="'.$style2.'">'.$db2.'.'.$tb2_name.'</span>'.$check_field2.'</td>
<td>'.$tb_remark.$remark.$count_field.'</td>
</tr>';
}//foreach
echo '<tr><td colspan="5"></td></tr>';
}//if not null
}//foreach
echo '<tr bgcolor="white"><td colspan="5" align="center">
<input type="submit" value=" UPDATE STRUCTURE (สร้างตาราง เพิ่มฟิลด์ที่ไม่ครบ และอัพเดตฟิลด์ให้ตรงกัน ) " style="color:orangered;font-weight:bold;height:40px;font-size:15px"/>
<br> <br> <font color="#996C05" style="font-size:15px;"><b>* การอัพเดต จะใช้ข้อมูลจาก <b style="color:blue">ด้านซ้าย</b> >> <b style="color:magenta">ด้านขวา</b> ตรวจสอบให้แน่ใจว่าตารางด้านซ้ายและขวา เป็นตารางที่เชื่อมโยงกัน</b></font>
</td></tr>';
echo '</table></form>';
}
elseif ($operator=='start_update_structure')
{
echo '<a href="javascript:void(0);" onclick="javascript:history.back();"> << ย้อนกลับ </a>';
mysql_query('SET NAMES UTF8');
$create = 0;
echo '<br><b> สร้างตารางใหม่ :: </b>';
if($_POST['new_table']){
foreach ($_POST['new_table'] as $tb1=>$tb2) {
$create++;
$sql = "CREATE TABLE $tb2 LIKE $tb1 ";
mysql_query($sql) or show_error(__FILE__, __LINE__, $sql);
echo "<div style='color:green'>$create. $sql</div>";
}
}
echo "<div style='color:green'>รวมทั้งสิ้น <font color='blue'>$create</font> รายการ</div>";
$add=0;
echo '<br><b> เพิ่มฟิลด์ใหม่ :: </b>';
if($_POST['new_field']){
foreach ($_POST['new_field'] as $db_field=>$tb2) {
$add++;
$ex = explode('@', $db_field);
$source_table = $ex[0];//ตารางต้นทาง
$field_name = $ex[1]; //ฟิลด์ต้นทาง
$sql = "SHOW FULL COLUMNS FROM $source_table";
$res = mysql_query($sql) or show_error(__FILE__, __LINE__, $sql);
$n=0;
$arr=array();
while($field = mysql_fetch_assoc($res)){
$n++;
$new[$n] = $field['Field'];
if($field['Field']==$field_name){
$arr = $field;
break;
}
}
$after = $new[$n-1];
$table = $tb2;//เทเบิลปลายทาง
//ถ้าเป็น NO แสดงว่าไม่เซ็ต
if($arr['Null']=='NO'){$null = 'NOT NULL';}else{$null = 'NULL';}
//ถ้ามีฟิลด์ก่อนหน้าเป็น AFTER แต่ถ้าไม่มี แสดงว่าเพิ่มใหม่ที่ฟิลด์แรกเลย
if($after){$after = " AFTER $after ";}else{$after = "FIRST";}
$sql = "ALTER TABLE $table ADD `$arr[Field]` $arr[Type] $null COMMENT '$arr[Comment]' $after ";
mysql_query($sql) or show_error(__FILE__, __LINE__, $sql);
echo "<div style='color:green'>$add. $sql</div>";
}//foreach
}//if
echo "<div style='color:green'>รวมเพิ่มฟิลด์ใหม่ทั้งสิ้น <font color='blue'>$add</font> รายการ</div>";
$change = 0;
echo '<br><b> ฟิลด์ที่มีการเปลี่ยนแปลง :: </b>';
if($_POST['change_field']){
foreach ($_POST['change_field'] as $db_field=>$tb2) {
$change++;
$ex = explode('@', $db_field);
$source_table = $ex[0];//ตารางต้นทาง
$field_name = $ex[1]; //ฟิลด์ต้นทาง
$sql = "SHOW FULL COLUMNS FROM $source_table LIKE '$field_name'";
mysql_query('SET NAMES UTF8');
$res = mysql_query($sql) or show_error(__FILE__, __LINE__, $sql);
$field = mysql_fetch_assoc($res);
if($field['Null']=='NO'){$null = 'NOT NULL';}else{$null = 'NULL';}
$table = $tb2;//เทเบิลปลายทาง
$sql = "ALTER TABLE $table CHANGE `$field[Field]` `$field[Field]` $field[Type] $null COMMENT '$field[Comment]'";
mysql_query('SET NAMES UTF8');
mysql_query($sql) or show_error(__FILE__, __LINE__, $sql);
echo "<div style='color:green'>$change. $sql</div>";
}//forech
}//if
echo "<div style='color:green'>รวมทั้งสิ้น <font color='blue'>$change</font> รายการ</div>";
}//operator
CloseDB();
echo '</div>';
echo $warning;
//END
?>
Reference : http://sunzandesign.blogspot.com
|
|
|
By : |
To Be Developer
|
|
Article : |
บทความเป็นการเขียนโดยสมาชิก หากมีปัญหาเรื่องลิขสิทธิ์ กรุณาแจ้งให้ทาง webmaster ทราบด้วยครับ |
|
Score Rating : |
|
|
Create Date : |
2013-05-02 |
|
Download : |
No files |
|
Sponsored Links |
|
|
|
|
|
|