[DB2] Query แบบ Check & Next

จริงๆ 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