จริงๆ Blog นี้เกิดจากการได้เป็นผู้โชคดีไปช่วยน้องในทีม Run Script สำหรับ UAT ครับ โดยที่น้องคนนั้นก็ไม่ค่อยมั่นใจกับ Script ครับ เมื่อทดสอบที่ Site ลูกค้าจริงแล้วพบว่า
อ้าวเฮ้ยยยย ไม่เหมือนที่คุยกันไว้นี่นา
ที่บอกว่า Migrate ครบ แต่อ้าวข้อมูลหายไป
อ้าวเฮ้ย อย่ากลืนน้ำลายตัวเองดีกว่า
เสียเวลาร้องขออะไร
สุดท้ายข้อมูลก็ต้องกลับคืน (มันของลูกค้า ไม่ได้ข้อมูลครบคงหัวขาด)
ทำไมถึงเป็นเช่นนั้นหละ ทำไม Script ที่มีการซักซ้อมมาอย่างดีถึงเกิดปัญหาตอนใช้จริง มาดูโครงสร้าง Script กันดีกว่าครับ โดยได้ทำเป็น Batch File ชุดนึงครับ (ไฟล์ migrate.bat )
db2 -tvf "21TMP_SYSTEMINFO.txt" -z result21.txt db2 -tvf "22MOV_FROM_SYSTEMINFO_TO_TMP_SYSTEMINFO.txt" -z result22.txt db2 "DROP TABLE INVEST.SYSTEMINFO" db2 -tvf "31NEW_SYSTEMINFO.txt" -z result21.txt db2 -tvf "32MOV_FROM_TMP_SYSTEMINFO_TO_SYSTEMINFO.txt" -z result21.txt db2 "DROP TABLE INVEST.TMP_SYSTEMINFO"
ข้างในมีเนื้อหาประมาณนี้ครับ
- ของดั้งเดิมมี TABLE SYSTEMINFO ซึ่งมีโครงสร้างตาม Script (ของจริงมี 100 Column แต่อันนี้ของตัดมา เพื่อไม่ให้ Blog ยาวเกินไปครับ
CREATE TABLE ERP.SYSTEMINFO ( COMPANYNAMEFULL CHARACTER(100 OCTETS), COMPANYNAMESHORT CHARACTER(50 OCTETS), COMPANYADDRESS CHARACTER(200 OCTETS), LOGINUSER INTEGER NOT NULL DEFAULT , LOGINPOSITION INTEGER NOT NULL DEFAULT , //..... ACCOUNTDATE CHARACTER(10) );
- ตัวอย่างข้อมูล
- สร้าง Table TMP_SYSTEMINFO ด้วยคำสั่ง เพื่อ Backup ข้อมูลไว้ก่อน (ไฟล์ 21TMP_SYSTEMINFO.txt )
CREATE TABLE ERP.TMP_SYSTEMINFO ( COMPANYNAMEFULL CHARACTER(100 OCTETS), COMPANYNAMESHORT CHARACTER(50 OCTETS), COMPANYADDRESS CHARACTER(200 OCTETS), LOGINUSER INTEGER NOT NULL DEFAULT , LOGINPOSITION INTEGER NOT NULL DEFAULT , //..... ACCOUNTDATE CHARACTER(10 OCTETS) DEFAULT 'TRADE' );
- ย้ายข้อมูลจาก Table SYSTEMINFO ไปที่ Table TMP_SYSTEMINFO ด้วยคำสั่ง
(ไฟล์ 22MOV_FROM_SYSTEMINFO_TO_TMP_SYSTEMINFO.txt )
INSERT INTO ERP.TMP_SYSTEMINFO SELECT COMPANYNAMEFULL , COMPANYNAMESHORT , COMPANYADDRESS , LOGINUSER //.... FROM INVEST.SYSTEMINFO
- DROP Table SYSTEMINFO ทิ้ง
DROP TABLE INVEST.SYSTEMINFO;
- Create Table SYSTEMINFO ใหม่ขึ้นมา ที่ต้องทำแบบนี้ เพราะ Table ขนาดมันเกินจาก PageSize ต้อง DROP และ Create แยก ครับ(ไฟล์ 31NEW_SYSTEMINFO.txt )
CREATE TABLE ERP.SYSTEMINFO ( COMPANYNAMEFULL CHARACTER(100), COMPANYNAMESHORT CHARACTER(50), COMPANYADDRESS CHARACTER(200), LOGINUSER INTEGER NOT NULL DEFAULT , LOGINPOSITION INTEGER NOT NULL DEFAULT , //..... ACCOUNTDATE CHARACTER(10) POS_DATABASE CHARACTER(100) POS_DATABASEUSER CHARACTER(30) POS_DATABASEPASS CHARACTER(30) );
- นำข้อมูลจาก Table TMP_A ย้ายกลับมาคืน Table A
(ไฟล์ 32MOV_FROM_TMP_SYSTEMINFO_TO_SYSTEMINFO.txt )
INSERT INTO ERP.TMP_SYSTEMINFO SELECT COMPANYNAMEFULL , COMPANYNAMESHORT , COMPANYADDRESS , LOGINUSER //.... FROM INVEST.SYSTEMINFO
- DROP Table TMP_A ทิ้ง ด้วยคำสั่ง
DROP TABLE INVEST.SYSTEMINFO;
แต่พอลองทดสอบทำงานจริง อ้าวววววววว Schema ไม่ตรงกัน พบ Script แรกมัน Error แต่ที่มันจะต้องหยุดกลับต้องทำงานต่อไป DROP ข้อมูลทิ้งเลย
ซุนวูกล่าวไว้ว่า รู้เขารู้เรา รบร้อยครั้งชนะร้อยครัั้ง
แต่นี่รู้ไม่ครบ แล้วต้องทำอย่างไร กลศึกมีไว้พลิกแพลงครับ เราก็เล่นแบบ Safe สิ Execute Script ดู Error ถ้าไม่มีแล้วทำงานต่อ ดู Return Code ครับ
- Windows ดูค่าจากตัวแปร %errorlevel%
- Linux / AIX ดูค่าจากตัวแปร "$?"
ค่าที่ db2 return กลับมา มีค่าที่เป็นไปได้ครับ มีดังนี้
CODE | DESCRIPTION |
---|---|
0 | DB2® command or SQL statement executed successfully |
1 | SELECT or FETCH statement returned no rows |
2 | DB2 command or SQL statement warning |
4 | DB2 command or SQL statement error |
8 | Command line processor system error |
ลองมาปรับใช้กันครับ Blog นี้เอาเฉพาะของ Windows ก่อนครับ โดยถ้า Error Script หยุดทำงานครับ โดยเพิ่ม Section มา 2 ส่วน
- ดักเงื่อนไข
echo errorlevel = %errorlevel% IF %errorlevel% NEQ 0 GOTO ERROR
- ดักเมื่อเกิดเหตุการณ์ ERROR - จะถูกทำงานเมื่อมี Error
:ERROR ECHO "RunScript failed, please check this log file for errors ..."
- ดักเมื่อเกิดเหตุการณ์ END - Clear ข้อมูลทิ้งครับ
:END del migrate_withcheck.bat
ภาพรวมของ Script ครับ ไฟล์ migrate_withcheck.bat ครับ
db2 connect to ERPDB user ERP01 using ERP01 :: MIGRATE set errorlevel=%1 db2 -tvf "21TMP_SYSTEMINFO.txt" -z result21.txt echo errorlevel = %errorlevel% IF %errorlevel% NEQ 0 GOTO ERROR db2 -tvf "22MOV_FROM_SYSTEMINFO_TO_TMP_SYSTEMINFO.txt" -z result22.txt echo errorlevel = %errorlevel% IF %errorlevel% NEQ 0 GOTO ERROR db2 "DROP TABLE INVEST.SYSTEMINFO" echo errorlevel = %errorlevel% IF %errorlevel% NEQ 0 GOTO ERROR db2 -tvf "31NEW_SYSTEMINFO.txt" -z result31.txt echo errorlevel = %errorlevel% IF %errorlevel% NEQ 0 GOTO ERROR db2 -tvf "32MOV_FROM_TMP_SYSTEMINFO_TO_SYSTEMINFO.txt" -z result32.txt echo errorlevel = %errorlevel% IF %errorlevel% NEQ 0 GOTO ERROR db2 "DROP TABLE INVEST.TMP_SYSTEMINFO" echo errorlevel = %errorlevel% IF %errorlevel% NEQ 0 GOTO ERROR db2 COMMIT WORK db2 CONNECT RESET db2 TERMINATE :END del migrate_withcheck.bat :ERROR ECHO "RunScript failed, please check this log file for errors ..." GOTO END
ตัวอย่าง การ Run ครับ จะเห็นว่า ถ้า Error มันไม่ทำงานต่อแล้วครับ ปลอดภัยระดับนึงครับ โดยผมอาไปแก้ Script ในไฟล์ 22MOV_FROM_SYSTEMINFO_TO_TMP_SYSTEMINFO.txt โดยเอา , ออกไปครับ เอา DataType ติดกับชื่อ Column ครับ แก้แบบนี้แล้วต้องได้ ERRORCODE = 4 Return กลับมาครับ
- คำสั่งถัดไป คือ DROP ครับ ถ้า Execute ต่อก็งานเข้าครับ
- ผลการทดสอบครับ มันไม่ทำคำสั่ง DROP ครับ ^___^
มีข้อสังเกตุด้วยนะครับ
- สังเกตุว่าใน ฺBAT ของเรามีคำสั่งเพิ่มขึ้น 2 คำสั่งครับ ต่อการ Execute Statement ด้วย db2 มันเยอะมาก ถ้าต่อยอดทำ Tools ก็สามารถทำได้ครับ
- อันนี้เอาไปประยุกต์กับพวก Transaction ได้ด้วยครับ
อ๋อสุดท้ายเห็นมีหลายคน ถามว่าผมทำงานอะไรนะครับ เป็น Developer ถ้าภาษาทั่วไป Programmer กรรมการ IT แหละครับ ไม่ได้เป็น DBA นะครับ ^__^
Reference
Discover more from naiwaen@DebuggingSoft
Subscribe to get the latest posts sent to your email.