Category: Oracle

  • การเรียกดูรายการ object ในฐานข้อมูล Oracle

    คำสั่งที่ใช้ในการเรียกดู รายการ object ในฐานข้อมูล Oracle

    • การเรียกดูรายการ object ทั้งหมดในฐานข้อมูล Oracle (เช่น table, view ฯลฯ)  สามารถเรียกดูได้จาก view ที่ชื่อว่า ALL_OBJECTS  ตัวอย่างคำสั่งคือที่ใช้เรียกดูคือ

     

    SELECT * FROM ALL_OBJECTS;

     

    โดยคำสั่งนี้จะแสดงรายการ object ทั้งหมดที่มี

     

    • แต่ในการใช้งานส่วนใหญ่ อาจจะต้องการเจาะจงดูแค่บางเงื่อนไข เช่น ต้องการดูรายการ table ทั้งหมด โดยเจาะจงแค่ schema ใด schema  หนึ่งเท่านั้น  ซึ่งสามารถใช้เงื่อนไขจากฟีลด์ต่อไปนี้ คือ
      • OBJECT_TYPE เป็นการเรียกดูตามเงื่อนไขของประเภท object เช่น หากต้องการดูเฉพาะ table จะใช้เงื่อนไขเป็น  WHERE OBJECT_TYPE = ‘TABLE’
      • OWNER เป็นการเรียกดูเฉพาะเจาะจง schema ใด schema  หนึ่ง เช่น ต้องการเรียกดูข้อมูลจาก schema ชื่อ SCOTT จะใช้เงื่อนไขเป็น WHERE OWNER = ‘SCOTT’
      • ตัวอย่างคำสั่งเต็ม ๆ กรณีที่ต้องการเรียกดูเฉพาะ table ทั้งหมดที่อยู่ใน schema ที่ชื่อ SCOTT

    SELECT * FROM ALL_OBJECTS WHERE OBJECT_TYPE=’TABLE’ AND OWNER=’SCOTT’;

     

    ตัวอย่างการนำไปใช้ประโยชน์

    เพื่อให้เห็นภาพการนำไปใช้งานจริง จึงขอยกตัวอย่างที่เคยใช้งาน คือ การสร้างสคริปต์คำสั่ง sql ที่อ้างอิงชื่อ table ที่อยู่ใน schema ใด schema หนึ่ง โดยในที่นี้จะยกตัวอย่างการ grant สิทธิ์ในการเข้าถึงข้อมูลของ schema หนึ่งไปให้กับอีก schema หนึ่ง

    • ที่มาที่ไปคือ ในบางครั้ง เราต้องการ grant สิทธิ์ในการเข้าถึงข้อมูลของ schema หนึ่งไปให้กับอีก schema หนึ่ง เช่น ต้องการ grant สิทธิ์การเรียกดูข้อมูลใน table ชื่อ TABLE01 ของ schema ที่ชื่อ SCHEMA01 ให้ schema ที่ชื่อ SCHEMA02 สามารถเรียกดูข้อมูลได้ คำสั่งที่ใช้ในการ grant คือGRANT SELECT ON SCHEMA01.TABLE01 TO SCHEMA02;
    • แต่หากต้องการ grant หลาย ๆ  table ก็ต้องพิมพ์คำสั่งเหล่านี้ทีละคำสั่งซ้ำๆ ไปจนครบตามชื่อ talbe ที่ต้องการ grant ซึ่งถ้า table ที่ต้องการ grant มีเป็นจำนวนมากก็จะยิ่งใช้เวลามากยิ่งขึ้น และอีกปัญหาคือ มีโอกาสพิมพ์ชื่อ table ผิด
    • เทคนิคในการสร้างสคริปต์เพื่อช่วยให้การทำงานรวดเร็วขึ้นจะมีรูปแบบดังนี้คือSELECT ‘GRANT SELECT ON OWNER_SCHEMA.’ || OBJECT_NAME || ‘ TO OTHER_SCHEMA;’
      FROM ALL_OBJECTS
      WHERE OBJECT_TYPE = ‘TABLE’;

      เมื่อ

      • OWNER_SCHEMA คือชื่อของ schema ที่เป็นเจ้าของ table
      • OBJECT_NAME คือชื่อฟีลด์ที่อยู่ใน ALL_OBJECTS โดยเป็นข้อมูลของชื่อ object ซึ่งกรณีนี้คือชื่อของ table นั่นเอง
      • OTHER_SCHEMA คือชื่อของ schema ที่ได้รับการ grant สิทธิ์ให้เรียกดูข้อมูลใน table ของ OWNER_SCHEMA
      • WHERE OBJECT_TYPE = ‘TABLE’ เป็นการระบุเงื่อนไขว่าต้องการ object ที่เป็น table เท่านั้น

    ผลลัพธ์ที่ได้คือ

    GRANT SELECT ON OWNER_SCHEMA.TABLE01 TO OTHER_SCHEMA;

    GRANT SELECT ON OWNER_SCHEMA.TABLE02 TO OTHER_SCHEMA;

    GRANT SELECT ON OWNER_SCHEMA.TABLE03 TO OTHER_SCHEMA;

    GRANT SELECT ON OWNER_SCHEMA.TABLE04 TO OTHER_SCHEMA;

    …….

    …….

    …….

    GRANT SELECT ON OWNER_SCHEMA.TABLE99 TO OTHER_SCHEMA;

     

    โดยคำสั่งทั้งหมดจะเท่ากับจำนวน table ของ OWNER_SCHEMA นั่นเอง ซึ่งหากไม่ต้องการ grant table ไหนก็ลบคำสั่ง grant เฉพาะ table นั้นออกไปได้

    • จะเห็นว่าการใช้เทคนิคลักษณะนี้ จะทำให้สามารถสร้างสคริปต์คำสั่งที่มีลักษณะแบบเดียวกันได้ภายในเวลาอันรวดเร็ว และลดความผิดพลาดของการอ้างอิงชื่อ object ลงไปได้ด้วย
    • อ้างอิงข้อมูล https://docs.oracle.com/cd/B19306_01/server.102/b14237/statviews_2005.htm#i1583352

     

     

     

     

     

  • Oracle: retrieve top n records for each group

    วิธีการเขียน Query เพื่อดึงข้อมูลข้อมูลสูงสุดหรือต่ำสุด N ลำดับแรกของแต่ละกลุ่มออกมาจากตาราง
    สมมติว่าเรามีข้อมูลคะแนนภาษาอังกฤษของนักศึกษาใหม่ซึ่งประกอบด้วย 5 ฟิลด์ข้อมูลดังตัวอย่างข้างล่าง
    ข้อมูล: ตาราง TEST_NEW_STUDENT เป็นตัวอย่างข้อมูลคะแนนภาษาอังกฤษของนักศึกษาใหม่จำนวน 773 รายการ

    โจทย์: ต้องการดึงข้อมูลนักศึกษาที่ได้คะแนนภาษาอังกฤษสูงสุดแยกตามคณะจากข้อมูลคะแนนภาษาอังกฤษของนักศึกษาใหม่จำนวน 773 รายการนี้

    เริ่มต้นด้วย query ดังนี้

    SELECT a.*,
    ROW_NUMBER ()
    OVER (PARTITION BY fac_id ORDER BY eng_score DESC)
    AS val_row_number
    FROM test_new_student a

    จุดสำคัญของ query ข้างต้นก็คือฟังก์ชัน ROW_NUMBER ซึ่งเป็นฟังก์ชันที่จะให้เลขบรรทัดของผลลัพธ์ออกมาตามการจัดกลุ่มข้อมูลหรือการเรียงลำดับที่เรากำหนดไว้ด้วยคำสั่ง OVER, PARTITION BY และ ORDER BY ที่ตามมา

    จากตัวอย่างข้างต้นหมายความว่า เรากำลัง Select * จากตาราง TEST_NEW_STUDENT พร้อมกับดึงเลข ROW_NUMBER ออกมา โดยเป็นเลขบรรทัดที่ให้แบ่งกลุ่มด้วยคณะ และให้เรียงลำดับด้วยคะแนนภาษาอังกฤษจากมากไปน้อย ซึ่งผลที่ได้จะเป็นดังนี้

    สังเกตที่ฟิลด์ VAL_ROW_NUMBER จะเห็นว่ามันแสดงตามอันดับของคะแนนภาษาอังกฤษ และถูกแบ่งตามคณะอย่างเรียบร้อย แค่นี้เราก็สามารถที่จะ select เอา Top ที่เท่าไหร่ของแต่ละกลุ่มได้แล้ว โดยเลือกเอา VAL_ROW_NUMBER ที่ต้องการ ซึ่งสามารถทำได้โดยเขียน select…where ซ้อน query ข้างต้นเข้าไปอีกทีดังนี้

    SELECT *
    FROM (SELECT a.*,
    ROW_NUMBER ()
    OVER (PARTITION BY fac_id ORDER BY eng_score DESC)
    AS val_row_number
    FROM test_new_student a)
    WHERE val_row_number <= 1;

    ผลลัพธ์:

    สรุปจากความต้องการที่ตั้งไว้ เราสามารถแก้ได้โดยใช้ Window Function ซึ่งมันสามารถหาเลขลำดับบางอย่างภายในกลุ่มข้อมูลออกมาให้ได้รูปแบบทั่วไปของ query คือ

    1 SELECT *,
    2 WFUNCTION OVER (PARTITION BY GROUP_FIELDS ORDER BY ORDER_FIELDS) n
    3 FROM SOURCE

    โดยที่

    SOURCE คือตัวข้อมูล
    WFUNCTION  หมายถึง Window Function ตัวอย่างที่เราเลือกใช้คือ ROW_NUMBER()
    GROUP_FIELDS คือรายการฟิลด์ที่จะแบ่งกลุ่ม เขียนเหมือนตอนที่เราจะ group by สามารถแบ่งด้วยหลายฟิลด์ก็ได้
    ORDER_FIELDS คือรายการฟิลด์ที่ใช้เรียงลำดับ, สามารถเรียงด้วยหลายฟิลด์ก็ได้, ใส่ ASC หรือ DESC ได้เหมือนคำสั่ง order by ปกติเราไม่จำเป็นต้องใส่ทั้ง partition by และ order by อาจจะใส่แค่อันใดอันหนึ่ง แล้วแต่ว่าต้องการแบ่งกลุ่มหรือเรียงลำดับหรือไม่
    n เป็นชื่อ alias ของผลลัพธ์ จะตั้งชื่ออย่างไรก็ได้ เมื่อเราได้เลขลำดับ n ของแต่ละกลุ่มออกมาแล้ว ทีนี้จะเอาไปหา Top N หรือพลิกแพลงยังไง ก็แล้วแต่จะ query ออกมา

  • Oracle: retrieve top n records from a query

    Top-N queries เป็นวิธีการดึงข้อมูลสูงสุดหรือต่ำสุด N ลำดับแรกออกมาจากตาราง โดยวิธีการดึงข้อมูลแบบ Top-N นั้นมีได้หลายวิธี แต่ในบทความนี้จะนำเสนอวิธีการดึงข้อมูลแบบ Top-N records เพียง 3 วิธีการดังนี้

    1. Inline View and ROWNUM
    2. WITH Clause and ROWNUM
    3. ROW_NUMBER

     

    สมมติว่าเรามีข้อมูลคะแนนภาษาอังกฤษของนักศึกษาใหม่ซึ่งประกอบด้วย 5 ฟิลด์ข้อมูลดังตัวอย่างข้างล่าง
    ข้อมูล: ตาราง TEST_NEW_STUDENT เป็นตัวอย่างข้อมูลคะแนนภาษาอังกฤษของนักศึกษาใหม่จำนวน 773 รายการ

    โจทย์: ต้องการดึงข้อมูลนักศึกษาที่ได้คะแนนภาษาอังกฤษสูงสุด 5 อันดันแรกจากข้อมูลคะแนนภาษาอังกฤษของนักศึกษาใหม่จำนวน 773 รายการนี้

     

    เริ่มต้น Top-N query ตามลำดับเพื่อแก้โจทย์กันค่ะ

    Inline View and ROWNUM
    Classic Top-N style query

    SELECT a.*,rownum
    FROM (SELECT *
    FROM test_new_student
    ORDER BY eng_score desc) a
    WHERE ROWNUM <= 5;

    ผลลัพธ์:

    • จากผลลัพธ์ที่ได้ข้อมูลจะถูกจัดเรียงจากคะแนนจากมากไปน้อยก่อนด้วย ORDER BY clause และหลังจากนั้นก็จะจำกัดจำนวนข้อมูลที่ต้องการด้วย ROWNUM
    • Pseudocolumn ROWNUM เป็นค่าตัวเลขแสดงลำดับที่ของการดึงข้อมูลจากตาราง
    • กรณีที่ต้องการข้อมูลคะแนนภาษาอังกฤษต่ำสุด ใส่ ASC แทน DESC ตรง ORDER BY clause

     

    WITH Clause and ROWNUM
    จากตัวอย่างข้างต้นเรายังสามารถเขียน query ด้วย WITH clause แทนที่ inline view ได้ดังนี้

    WITH ordered_query AS
    (SELECT *
    FROM test_new_student
    ORDER BY eng_score desc)
    SELECT ordered_query.*,rownum
    FROM ordered_query
    WHERE rownum <= 5;

     

    ROW_NUMBER
    ฟังก์ชัน ROW_NUMBER เป็นฟังก์ชันที่กำหนดค่าลำดับของข้อมูลที่จัดเรียงตามข้อมูลที่กำหนดไว้ใน order_by_clause โดยจะมีค่าเริ่มต้นเท่ากับ 1 โดยเราจะมีวิธีการเขียน query ได้ดังนี้

    SELECT *
    FROM (SELECT a.*, row_number() OVER (ORDER BY eng_score DESC) AS val_row_number
    FROM test_new_student a)
    WHERE val_row_number <= 5;

    ผลลัพธ์:

    สังเกตที่ฟิลด์ VAL_ROW_NUMBER จะเห็นว่ามันแสดงตามอันดับของคะแนนภาษาอังกฤษแล้ว แค่นี้เราก็สามารถที่จะ select เอา Top ที่เท่าไหร่ได้แล้ว โดยเลือกเอา VAL_ROW_NUMBER ที่ต้องการ

  • Oracle MySQL Cluster :- The shared-nothing architecture (Manual Installation)

    1. สิ่งที่ต้องเตรียม ได้แก่ Ubuntu Server 16.04 (รุ่น x86_64 architecture) จำนวนอย่างน้อย 4 เครื่อง (แต่ควรอย่างน้อย 6 เครื่อง), IP Address 4 IP, Software MySQL Cluster โหลดที่ https://edelivery.oracle.com/ (ต้องสมัครสมาชิกให้เรียบร้อยก่อน) ใช้คำค้นว่า MySQL Cluster (จะมีรุ่น 7.5.5 ให้โหลด) โดยไฟล์ที่ใช้งานชื่อว่า V840854-01.zip MySQL Cluster 7.5.5 TAR for Generic Linux (glibc2.5) x86 (64bit)

    2. 4 เครื่องประกอบด้วยอะไรบ้าง
      2 x data nodes เปลี่ยน IP ให้ตรงกับที่ใช้งาน
      192.168.106.32  Data-node1
      192.168.106.33  Data-node2
      1 x SQL/NoSQL Application Node
      192.168.106.42  SQL-Node
      1 x Management Node
      192.168.106.40  Management-node
    3. เริ่มที่ Management Node
      1. ssh 192.168.106.40 -l sudo_user (user ที่เรียกใช้คำสั่ง sudo ได้)
      2. คลายแฟ้ม V840854-01.zip ด้วยคำสั่ง
        unzip V840854-01.zip (อาจต้องติดตั้งเพิ่มเติมด้วยคำสั่ง sudo apt install unzip)
      3. จะได้แฟ้ม  mysql-cluster-advanced-7.5.5-linux-glibc2.5-x86_64.tar.gz คลายแฟ้ม mysql-cluster-advanced-7.5.5-linux-glibc2.5-x86_64.tar.gz ด้วยคำสั่ง
        tar zxvf mysql-cluster-advanced-7.5.5-linux-glibc2.5-x86_64.tar.gz
      4. เปลี่่ยนชื่อ mysql-cluster-advanced-7.5.5-linux-glibc2.5-x86_64 เป็น mysql
        mv mysql-cluster-advanced-7.5.5-linux-glibc2.5-x86_64 mysql
      5. คัดลอกแฟ้ม mysql/bin/ndb_mgmd และ mysql/bin/ndb_mgm ไปไว้ที่ /usr/local/bin
        cp mysql/bin/ndb_mgm* /usr/local/bin/
      6. สร้างโฟลเดอร์ /var/lib/mysql-cluster และสร้างแฟ้ม /var/lib/mysql-cluster/config.ini
        sudo mkdir -p /var/lib/mysql-cluster/
      7. เพื่อเป็นการบอก Management node ว่า Data Node และ SQL Node มีใครบ้าง ให้สร้าง config.ini ไว้ที่ /var/lib/mysql-cluster ด้วยคำสั่ง
        cat<< EOF | sudo tee /var/lib/mysql-cluster/config.ini
        เพิ่มข้อความต่อไปนี้ลงไป
        [ndbd default]
        NoOfReplicas=2
        DataMemory=80M
        IndexMemory=18M
        [mysqld default]
        [ndb_mgmd default]
        [tcp default]
        # Cluster Control / Management node
        [ndb_mgmd]
        hostname=192.168.106.40# Data Node 1
        [ndbd]
        hostname=192.168.106.32
        DataDir= /var/lib/mysql-cluster# Data Node 2
        [ndbd]
        HostName=192.168.106.33
        DataDir=/var/lib/mysql-cluster# SQL Node
        [mysqld]
        hostname=192.168.106.42

        # If you to add new SQL Node
        [mysqld]

        EOF

      8. เพิ่มข้อความต่อไปนี้ในแฟ้ม /etc/rc.local
        /var/lib/mysql-cluster/config.ini --configdir=/var/lib/mysql-cluster/
        โดยเพิ่มให้อยู่บรรทัดก่อนคำว่า exit 0 ตัวอย่าง /etc/rc.local
        #!/bin/sh -e
        #
        # rc.local
        #
        # This script is executed at the end of each multiuser runlevel.
        # Make sure that the script will "exit 0" on success or any other
        # value on error.
        #
        # In order to enable or disable this script just change the execution
        # bits.
        #
        # By default this script does nothing.
        ndb_mgmd -f /var/lib/mysql-cluster/config.ini --configdir=/var/lib/mysql-cluster/
        exit 0
      9. สั่งคำสั่ง
        sudo ndb_mgmd -f /var/lib/mysql-cluster/config.ini --configdir=/var/lib/mysql-cluster/
        ต้องเห็นข้อความว่า MySQL Cluster Management Server mysql-5.7.17 ndb-7.5.5 แปลว่า management node ทำงานแล้ว
      10. สามารถตรวจสอบด้วยคำสั่งอื่นๆ
        netstat -plntu
        ได้ผลดังภาพ สังเกตุบรรทัดที่เขียนว่า tcp 0 0 0.0.0.0:1186 แปลว่า management node ทำงานแล้ว
      11. สามารถทำซ้ำได้อีกเครื่อง (ไม่จำกัด) แต่ในตัวอย่างนี้มีเพียงเครื่องเดียว
      12. ส่งแฟ้ม mysql-cluster-advanced-7.5.5-linux-glibc2.5-x86_64.tar.gz ให้ SQL node
        cd
        scp mysql-cluster-advanced-7.5.5-linux-glibc2.5-x86_64.tar.gz sudo_user@192.168.106.42
    4. ติดตั้ง SQL Node
      1. ssh 192.168.106.42 -l sudo_user (User ที่สามารถเรียกใช้คำสั่ง sudo ได้)
      2. ติดตั้ง Package ที่จำเป็น
        sudo apt install libaio1
      3. สร้าง user  และ group
        sudo groupadd mysql
        sudo useradd -g mysql mysql
      4. คลายแฟ้ม mysql-cluster-advanced-7.5.5-linux-glibc2.5-x86_64.tar.gz ด้วยคำสั่ง
        tar zxvf mysql-cluster-advanced-7.5.5-เพิ่มข้อความต่อไปนี้ในแฟ้ม /etc/rc.local
        /var/lib/mysql-cluster/config.ini --configdir=/var/lib/mysql-cluster/
        โดยเพิ่มให้อยู่บรรทัดก่อนคำว่า exit 0 ตัวอย่าง /etc/rc.locallinux-glibc2.5-x86_64.tar.gz
      5. เปลี่่ยนชื่อ mysql-cluster-advanced-7.5.5-linux-glibc2.5-x86_64 เป็น mysql
        mv mysql-cluster-advanced-7.5.5-linux-glibc2.5-x86_64 mysql
      6. ย้าย mysql ไปที่ /usr/local/ ด้วยคำสั่ง
        sudo mv mysql /usr/local
      7. สร้างโฟลเดอร์และสั่งคำสั่งต่อไปนี้
        sudo mkdir /usr/local/mysql/data
        sudo mkdir /var/lib/mysql-files
        sudo chown mysql:mysql /var/lib/mysql-files
        sudo chown mysql:mysql /usr/local/mysql/data
      8. สร้างแฟ้ม /etc/my.cnf ด้วยคำสั่ง
        cat << EOF | sudo tee /etc/my.cnf
        เพิ่มข้อความต่อไปนี้ลงไป
        # MySQL Config
        [mysqld]
        datadir=/usr/local/mysql/data
        socket=/tmp/mysql.sock
        user=mysql# Run ndb storage engine
        ndbcluster
        # IP address management node
        ndb-connectstring=192.168.106.40[mysql_cluster]
        # IP address management node
        ndb-connectstring=192.168.106.40# MySQL Pid and Log
        [mysqld_safe]
        log-error=/var/log/mysqld.log
        pid-file=/var/run/mysqld/mysqld.pid
        EOF
      9. สั่งคำสั่งต่อไปนี้เพื่อเตรียมฐานข้อมูล ในขั้นตอนนี้จะมีการสร้าง passwd ของ root ให้ด้วยโดยอัตโนมัติ  *จดไว้ด้วย*
        sudo /usr/local/mysql/bin/mysqld --initialize --user=mysql --datadir=/usr/local/mysql/data
      10. เพื่อให้ตัวควบคุมฐานข้อมูลทำงานอัตโนมัติสั่งคำสั่งต่อไปนี้
        sudo cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysqld
        sudo systemctl enable mysqld.service
        sudo systemctl start mysqld
      11. สามารถทำซ้ำได้อีกเครื่อง (ไม่จำกัด) แต่ในตัวอย่างนี้มี SQL Node เพียงเครื่องเดียว
      12. ส่งแฟ้ม mysql-cluster-advanced-7.5.5-linux-glibc2.5-x86_64.tar.gz ให้ SQL node
        cd
        scp mysql-cluster-advanced-7.5.5-linux-glibc2.5-x86_64.tar.gz sudo_user@192.168.106.32
    5. ติดตั้ง Data Node
      1. ssh sudo_user@192.168.106.32  (sudo_user คือ user ที่เรียกใช้คำสั่ง sudo ได้)
      2. สร้างแฟ้ม /etc/my.cnf ด้วยคำสั่ง
        cat << EOF | sudo tee /etc/my.cnf
        เพิ่มข้อความต่อไปนี้เข้าไป
        # MySQL Config
        [mysqld]
        datadir=/usr/local/mysql/data
        socket=/tmp/mysql.sock
        user=mysql# Run ndb storage engine
        ndbcluster
        # IP address management node
        ndb-connectstring=192.168.106.40[mysql_cluster]
        # IP address management node
        ndb-connectstring=192.168.106.40# MySQL Pid and Log
        [mysqld_safe]
        log-error=/var/log/mysqld.log
        pid-file=/var/run/mysqld/mysqld.pid
        EOF
      3. ติดตั้ง Package ที่จำเป็น
        sudo apt install libaio1
      4. สร้าง user  และ group
        sudo groupadd mysql
        sudo useradd -g mysql mysql
      5. คลายแฟ้ม mysql-cluster-advanced-7.5.5-linux-glibc2.5-x86_64.tar.gz ด้วยคำสั่ง
        tar zxvf mysql-cluster-advanced-7.5.5-linux-glibc2.5-x86_64.tar.gz
      6. เปลี่่ยนชื่อ mysql-cluster-advanced-7.5.5-linux-glibc2.5-x86_64 เป็น mysql
        mv mysql-cluster-advanced-7.5.5-linux-glibc2.5-x86_64 mysql
      7. ย้าย mysql ไปที่ /usr/local/ ด้วยคำสั่ง
        sudo mv mysql /usr/local
      8. สร้างโฟลเดอร์และสั่งคำสั่งต่อไปนี้
        sudo mkdir /usr/local/mysql/data
        sudo mkdir /var/lib/mysql-files
        sudo mkdir /var/lib/mysql-cluster
        sudo chown mysql:mysql /var/lib/mysql-files
        sudo chown mysql:mysql /usr/local/mysql/data
      9. สั่ง start service ด้วยคำสั่ง
        sudo  /usr/local/mysql/bin/ndbd
      10. เพิ่มข้อความต่อไปนี้ในแฟ้ม /etc/rc.local
        /usr/local/mysql/bin/ndbd โดยเพิ่มให้อยู่บรรทัดก่อนคำว่า exit 0
        ตัวอย่าง /etc/rc.local
        #!/bin/sh -e
        #
        # rc.local
        #
        # This script is executed at the end of each multiuser runlevel.
        # Make sure that the script will "exit 0" on success or any other
        # value on error.
        #
        # In order to enable or disable this script just change the execution
        # bits.
        #
        # By default this script does nothing.
        /usr/local/mysql/bin/ndbd
        exit 0
      11. ทำซ้ำสำหรับ Data Node2 (ไม่จำกัด)
    6. ทดสอบ Cluster
      1. พิมพ์คำสั่ง
        sudo /usr/local/mysql/bin/ndb_mgm
        เมื่อได้ prompt พิมพ์คำว่า show ได้ผลดังภาพ
      2. แปลว่าทำงานถูกต้องแล้ว..
    7. เชื่อมต่อกับ SQL Node เพื่อเปลี่ยนรหัสผ่าน root
      1. ssh sudo_user@192.168.106.42  (sudo_user คือ user ที่เรียกใช้คำสั่ง sudo ได้)
      2. พิมพ์คำสั่งต่อไปนี้เพื่อสร้าง link ไปยัง mysql client
        sudo ln -s /usr/local/mysql/bin/mysql /usr/bin
      3. เรียกใช้งาน mysql
        mysql -u root -p
        ใส่ passwd ที่จดไว้ในข้อ 4 ข้อย่อย 9 แล้วเปลี่ยนใหม่ด้วยคำสั่ง
        ALTER USER ‘root’@’localhost’ IDENTIFIED BY ‘newPassw0rd’
    8. ทุกครั้งที่จะทำอะไรผ่าน mysql client ต้องติดต่อกับ SQL Node เท่านั้นซึ่งตามตัวอย่างนี้มีเพียงเครื่องเดียวจึงไม่มีการทำ replicate data ใดๆ ทั้งสิ้นจำเป็นต้องเพิ่ม SQL Node เข้าไปอีก
    9. จบ.. ขอให้สนุกครับ

    อ้างอิง

    https://www.howtoforge.com/tutorial/how-to-install-a-mysql-cluster-on-ubuntu-16-04/

    https://medium.com/@ophasnoname_44358/mysql-cluster-7-5-5-on-ubuntu-16-04-step-by-step-9132cf76d5b8

     

  • Removing duplicate records by using Oracle’s ROWID

    ถ้าคุณมีตารางข้อมูลอยู่ และรู้ว่ามีบางแถวที่มีข้อมูลซ้ำซ้อนกัน ทางไหนเป็นวิธีที่ดีที่จะสามารถหาและกำจัดแถวที่มีข้อมูลซ้ำนี้ออกไปจากตารางของฐานข้อมูล Oracle ?

     

    การหาแถวที่มีข้อมูลซ้ำซ้อน

    เราสามารถหาข้อมูลแถวที่มีข้อมูลซ้ำซ้อนกันได้โดยใช้คำสั่ง select ดังนี้

     

    select a,b,count(*)

    from test

    group by a,b

    having count(*) > 1;

    ผลลัพธ์ที่ได้ :

    A          B   COUNT(*)

    ———- ———- ———-

    1          2        259

    2          2          5

     

    จากตัวอย่างในตาราง test นี้เราจะกำหนดว่าให้ค่าในคอลัมภ์ a และ b จะต้องมีค่าไม่ซ้ำ ซึ่งผลลัพธ์ที่ปรากฏคือ มีข้อมูลซ้ำ 258 แถว และ 4 แถว

     

    การกำจัดแถวที่มีข้อมูลซ้ำซ้อน
    เราสามารถกำจัดแถวที่มีข้อมูลซ้ำซ้อนกันได้โดยการใช้ rowid เข้ามาช่วย คราวนี้คุณต้องเลือกว่าจะเลือกเก็บข้อมูลแถวไหนไว้

    เราลองมาดูข้อมูลที่ควรจะเป็นที่ไม่ซ้ำกันว่ามีข้อมูลอะไรบ้าง โดยสามารถใช้คำสั่งได้ดังนี้

    select a,b,count(*) from test

    group by a,b;

    A          B   COUNT(*)

    ———- ———- ———-

    1          2        259

    2          2          5

    3          0          1

     

    กรณีที่ต้องการลบและคงเหลือไว้เฉพาะแถวแรกที่ซ้ำสามารถใช้คำสั่งได้ดังนี้

     

    เราต้องการกำจัด 258 แถวที่ซึ่ง A = 1 และ B = 2 บวกกับ

    — 4 แถวที่ซึ่ง A = 2 และ B = 2

    ลองมา select แถวที่เราจะคงไว้ดูก่อน

    select min(rowid),a,b from test

    group by a,b;

    MIN(ROWID)                             A          B

    ——————————- ———- ———-

    AAAAyvAAGAAAABYAAA          1          2

    AAAAyvAAGAAAABYAED          2          2

    AAAAyvAAGAAAABYAEI           3          0

     

    — คราวนี้ก็ถึงเวลาลบข้อมูลกันแล้ว

    — เริ่มกันเลย

    delete from test where rowid not in (

    select min(rowid) from test group by a,b);

    262 rows deleted.

     

    — คราวนี้มาตรวจสอบกันว่าข้อมูลที่คงเหลือถูกต้องหรือไม่

    select rowid,a,b from test;

    ROWID                                      A          B

    ——————————— ———- ———-

    AAAAyvAAGAAAABYAAA          1          2

    AAAAyvAAGAAAABYAED          2          2

    AAAAyvAAGAAAABYAEI           3          0

     

    กรณีที่ต้องการลบและคงเหลือไว้เฉพาะแถวสุดท้ายที่ซ้ำสามารถใช้คำสั่งได้ดังนี้

    delete from test where rowid not in (

    select max(rowid) from test group by a,b);

    262 rows deleted.

     

    แต่เพื่อป้องกันการเกิดการซ้ำซ้อนของข้อมูลเหล่านี้ เราสามารถที่จะใช้ unique constraints หรือ primary key ช่วยได้ ปัญหาข้อมูลซ้ำซ้อนแบบนี้ก็จะไม่มีทางเกิดขึ้นให้เกิดความปวดหัวได้อีก

     

  • อีกหนึ่งวิธีในการกำจัดข้อมูลที่ซ้ำซ้อนกันในตาราง

    ถ้าคุณมีตารางข้อมูลอยู่ และรู้ว่ามีบางแถวที่มีข้อมูลซ้ำซ้อนกัน ทางไหนเป็นวิธีที่ดีที่จะสามารถหาและกำจัดแถวที่มีข้อมูลซ้ำนี้ออกไปจากตารางของฐานข้อมูล Oracle ?

    อีกวิธีหนึ่งที่เป็นไปได้ในการกำจัดแถวที่ซ้ำซ้อนกันคือการใช้คำสั่ง select distinct และใส่ข้อมูลที่ได้ลงในตารางใหม่

     

    จากที่เราสามารถตรวจสอบหาข้อมูลแถวที่มีข้อมูลซ้ำซ้อนกันได้โดยใช้คำสั่ง select ดังนี้

    SQL> select a,b,count(*) from test group by a,b;

    ผลลัพธ์ที่ได้

    A           B COUNT(*)
    ———- ———- ———-
    1           2       259
    2           2           5
    3           0           1

    จากตัวอย่างในตาราง test นี้ที่กำหนดไว้ว่าค่าในคอลัมภ์ a และ b จะต้องมีค่าไม่ซ้ำ ซึ่งผลลัพธ์ที่ปรากฏคือ มีข้อมูลซ้ำ 258 แถว และ 4 แถว

     

    เรามาเริ่มต้นกำจัดข้อมูลซ้ำซ้อนอีกวิธีกันเลย

     

    การหาแถวข้อมูลที่ไม่ซ้ำซ้อนกัน

    เราสามารถหาข้อมูลที่ไม่ซ้ำซ้อนกันได้โดยใช้คำสั่ง select distinct ดังนี้

    SQL> select distinct * from test;

    ผลลัพธ์ที่ได้

             A           B
    ———- ———-
              1           2
              2           2
              3           0

     

    สร้างตารางใหม่ชั่วคราวเพื่อเก็บผลลัพธ์ที่ได้

    SQL> create table new_test as (select distinct * from test);

     

    ตรวจสอบผลลัพธ์ที่ได้ในตารางชั่วคราวนี้

    SQL> select * from new_test;

    ผลลัพธ์ที่ได้

             A           B
    ———- ———-
              1           2
              2           2
              3           0 

     

    ทำการลบข้อมูลในตาราง test ทั้งหมด

    SQL> truncate table test;

    Table truncated.

     

    ทำการเพิ่มข้อมูลกลับไปยังตาราง test จากตารางชั่วคราว    

    SQL> insert into test (select * from new_test);

    3 rows created.

     

    ทำการลบตารางข้อมูลชั่วคราวทิ้ง

    SQL> drop table new_test;

    Table dropped.

     

    ตรวจสอบกันอีกครั้งว่าข้อมูลยังซ้ำกันอีกหรือไม่โดยใช้คำสั่ง select ดังนี้

    SQL> select a,b,count(*) from test group by a,b;

    ผลลัพธ์ที่ได้

    A           B COUNT(*)
    ———- ———- ———-
    1           2           1
    2           2           1
    3           0           1

     

    นี่ก็เป็นอีกหนึ่งวิธีในการกำจัดแถวที่มีข้อมูลซ้ำซ้อนกันในตาราง แต่เพื่อป้องกันการเกิดการซ้ำซ้อนของข้อมูลเหล่านี้ ขอย้ำอย่าลืมใช้ unique constraints หรือ primary key ช่วยได้ ปัญหาข้อมูลซ้ำซ้อนแบบนี้ก็จะไม่มีทางเกิดขึ้นให้เกิดความปวดหัวได้อีก

  • Auto remove schema in EDMX on build

    Entity Framework (EF)  คือ data access technology ที่เริ่มเปิดตัวครั้งแรกเป็นส่วนหนึ่งของ .NET Framework 3.5 SP1 โดยตัว EF จะทำหน้าที่เป็น object-relational mapper ที่ทำให้ผู้พัฒนาไม่จำเป็นต้องเขียน code ในส่วน data access ก็สามารถใช้ข้อมูลจาก relational database โดยผ่าน object model

    การพัฒนาโปรแกรมโดยใช้ EF นั้นจำเป็นต้องมี Entity Data Model เป็น model ที่กำหนดรายละเอียดเกี่ยวกับ entity และ relationship ระหว่าง entity นั้นๆ การสร้าง Entity Data Model สามารถแยกออกเป็น 2 แนวทางคือ “Code First” เป็นการกำหนดรูปร่างของ model โดยการสร้าง class (เขียน code) จะมี database หรือไม่มีอยู่ก่อนก็ได้  และ “Database First” ที่จะทำการสร้าง model ( reverse engineer) จาก database ที่มีอยู่โดย EF Designer ซึ่ง model ที่ได้จะเก็บอยู่ใน EDMX file (.edmx) สามารถเปิดหรือแก้ไขเพิ่มเติมได้ด้วย EF Designer สำหรับ class ที่ใช้ในโปรแกรมจะถูกสร้างโดยอัตโนมัติจาก EDMX file

    ข้อมูล Entity Data Model ใน EDMX file อยู่ในรูปแบบ xml สามารถแบ่งออกเป็น 3 ส่วนคือ Storage model, Conceptual model และ Mapping ซึ่งในส่วนของ Storage model จะเป็นข้อมูลรายละเอียดของ entity จาก database เช่น

    ข้อมูล EntityType ที่ให้รายละเอียดของชื่อของ entity (table ใน database), ชื่อและประเภทของ property (column ของ table ใน database)

     <EntityType Name="VF_CONFIG_REPORT">
      <Key>
        <PropertyRef Name="ID" />
      </Key>
        <Property Name="ID" Type="number" Precision="38" Scale="0" Nullable="false" />
        <Property Name="REPORT_NAME" Type="varchar2" MaxLength="512" />
        <Property Name="REPORT_PATH" Type="varchar2" MaxLength="512" />
        <Property Name="GROUP_TYPE" Type="number" Precision="38" Scale="0" />
        <Property Name="SIGN_NUM" Type="number" Precision="38" Scale="0" />
        <Property Name="SIGNS" Type="varchar2" MaxLength="128" />
     </EntityType>

    ข้อมูล EntitySet ที่ประกอบด้วย ชื่อ,ประเภทของ entity, schema และ query ที่ใช้ดึงข้อมูล

    <EntitySet Name="VF_CONFIG_REPORT" EntityType="Self.VF_CONFIG_REPORT" store:Type="Views" store:Schema="FINANCE">
       <DefiningQuery>
          SELECT 
           "VF_CONFIG_REPORT"."ID" AS "ID",
           "VF_CONFIG_REPORT"."REPORT_NAME" AS "REPORT_NAME", 
           "VF_CONFIG_REPORT"."REPORT_PATH" AS "REPORT_PATH", 
           "VF_CONFIG_REPORT"."GROUP_TYPE" AS "GROUP_TYPE", 
           "VF_CONFIG_REPORT"."SIGN_NUM" AS "SIGN_NUM", 
           "VF_CONFIG_REPORT"."SIGNS" AS "SIGNS"
         FROM "FINANCE"."VF_CONFIG_REPORT" "VF_CONFIG_REPORT"   
       </DefiningQuery>
    </EntitySet>

    เมื่อมีการระบุ schema ของ entityใน EDMX file  นั่นทำให้การ deploy ระบบ(โปรแกรมและ database) จำเป็นต้องมี database ที่มี schema ชื่อเดียวกับที่กำหนดใน EDMX file เท่านั้น(schema ได้มาจากการ generate ของ EF Designer ในขั้นตอนการพัฒนาระบบ) ถ้าต้องการให้ EF ทำงานกับ database schema อื่นจะต้องแก้ไข schema ใน EDMX file ให้ตรงกัน หรือไม่ระบุ schema โดยลบส่วนที่ระบุ schema ออก ซึ่งการแก้ไขจะต้องทำการแก้ไขโดยตรงไปที่ EDMX file แล้วทำการ build ใหม่ (ในกรณีที่ไม่ได้เลือก build EDMX file เป็นแบบ embeded resource สามารถแก้ไขที่ .ssdl file ได้โดยไม่ต้อง build ใหม่)

    ในการเปลี่ยน schema ใน EDMX file นั้นจะต้องแก้ทุก EntitySet ที่มี ทำให้มีความเสี่ยงที่จะเกิดความผิดพลาดในการแก้ไข ทำให้ระบบไม่สามารถทำงานได้ และถ้ามีความจำเป็นต้องปรับ Entity Data Model เพื่อเพิ่ม, แก้ไข หรือลบ entity ใดๆ EF Designer จะทำการ update .EDMX file ใหม่ ทำให้ schema ที่แก้ไขไปแล้วกลับมาเหมือนเดิม ต้องเปลี่ยน schema ใหม่อีกครั้ง ก็ยิ่งจะเพิ่มความเสี่ยงที่จะเกิดความผิดพลาด และยุ่งยากในการบริการจัดการ source code

    เราสามารถทำให้กระบวนการแก้ไขหรือลบ schema ใน EDMX file เป็นไปโดยอัตโนมัติ โดยการแก้ใข .csproj เพิ่มกระบวนการแก้ไขหรือลบ schema เข้าไปในขั้นตอนการ build ของ MsBuild หลังจากกระบวนการ “EntityDeployEmbededResource” ของ EF ดังนี้

     

    <Target Name="RemoveSchemaEntityDeployEmbeddedResources" AfterTargets="EntityDeployEmbeddedResources" Condition="'@(EntityDeployEmbeddingItems)' != ''">
      <PropertyGroup>
        <RemoveSchemaEmbeddedResources>"Libs\EFRemoveSchema" $(EntityDeployIntermediateResourcePath)%(EntityDeployEmbeddedResources.EntityDeployRelativeDir)</RemoveSchemaEmbeddedResources>
      </PropertyGroup>
      <Exec WorkingDirectory="$(MSBuildProjectDirectory)" Command="$(RemoveSchemaEmbeddedResources)" />
    </Target>

    “Libs\EFRomoveSchema” เป็นโปรแกรมเล็กๆที่พัฒนาเพื่อลบ schema ใน Entity Data Model ที่อยู่ใน folder   $(EntityDeployIntermediateResourcePath)%(EntityDeployEmbeddedResources.EntityDeployRelativeDir) โดยใช้ เทคนิคการค้นหา attribute ของ node ที่ต้องการใน XML file (EDMX file) เพื่อลบ และบันทึกกลับลงไปที่ XML file นั้นๆ

     

    อ้างอิง : https://msdn.microsoft.com/en-us/data/ee712907

  • การเขียนโปรแกรม JSP เชื่อมต่อ ORACLE

         JSP หรือชื่อเต็มว่า Java Server Page เป็นภาษาที่ใช้ในการพัฒนา Application ที่ทำงานบนเว็บไซต์ โดยรูปแบบการทำงานจะทำงานคล้ายกับภาษา  ASP ,PHP และ .Net รูปแบบการทำงานจะแตกต่างกันตรงที่ JSP เป็น Subset ของภาษา Java โดยรูปแบบการเขียนนั้นจะใช้รูปแบบคำสั่งและชุด SDK ของ Java และใน JSP จะมีนามสกุลของไฟล์เป็น .jsp โดยการทำงานจะทำงานในรูปแบบของ Server และ Client แสดงผลและโต้ตอบกับ User Interface ผ่าน Web Browser เช่น  IE ,Chrome ,Firefox และอื่นๆ โดยจะสามารถทำงานร่วมกับ Client Tags เช่นพวก HTML / JavaScript / CSS และพวก jQuery ให้ได้ผลลัพธ์ตามที่ต้องการ ที่สำคัญ JSP สามารถใช้งานได้ฟรี และสามารถรองรับได้ทุก Platform ไม่ว่าจะเป็น Windows ,Linux และ iOS รวมทั้ง Software อื่น ๆ

         Oracle เป็น Database ชนิดหนึ่งซึ่งเป็นโปรแกรมที่ใช้ในการจัดการฐานข้อมูล โดยจะทำหน้าที่เป็นตัวกลางคอยติดต่อประสานระหว่างผู้ใช้และฐานข้อมูล ทำให้ผู้ใช้งานสามารถใช้งานฐานข้อมูลได้สะดวกขึ้น เช่น การค้นหาข้มูลต่างๆ ภายในฐานข้อมูลที่ง่ายและสะดวก โดยผู้ใช้ไม่จำเป็นต้องทราบถึงโครงสร้างภายในของฐานข้อมูลก็สามารถเข้าใช้ฐานข้อมูลนั้นได้

         เริ่มต้นในการเขียนโปรแกรมที่นิยมการ connect  oracle ด้วย jsp จะใช้การ connect  ด้วย  JDBC โดยในส่วน ภาษา jsp จะสามารถใช้ packet ของ java ที่จะสามารถ import class ของ JDBC มาใช้งานใน  jsp ได้ทันที โดยไม่จำเป็นต้องเขียน โปรแรกม เพิ่มเติมให้ยุ่งยาก

     

    ขั้นตอนที่ 1 สร้างไฟล์ jsp โดยข้อมูลภายในจะมีsyntax เหมือนกับ HTML แต่ต่างกันที่นามสกุลไฟล์ จะเป็นนามสกุล .jsp

    <HTML>
    <HEAD>
    <TITLE>Simple JSP to Oracle connection Example</TITLE>
    </HEAD>
    <BODY>
    </BODY>
    <HTML>
    

    ขั้นตอนที่ 2 ทำการ import library ที่ใช้ในการเชื่อมต่อกับ database oracle ด้วย java.sql.*

    <%@ page import="java.sql.*" %>
    
    <HTML>
    <HEAD>
    <TITLE>Simple JSP to Oracle connection Example</TITLE>
    </HEAD>
    <BODY>
    </BODY>
    <HTML>
    

    ขั้นต้อนที่ 3 สร้างตัวแปลที่ใช้ในการเขื่อมต่อ

    String strdrive ="oracle.jdbc.OracleDriver";   //driver ของ oracle
    String url = "jdbc:oracle:thin:@localhost:1521:xe";  //server database
    String usr = "username";  //user name
    String pwd = "pwd";     //password 

    ขั้นต้อนที่ 4 สร้าง connection การเชื่อมต่อไปยัง database

    Connection conn = null;

    ขั้นตอนที่ 5 ทำการเชื่อมต่อกับ database โดยใช้ ตัวแปลจากข้างต้น

    <%
        Connection conn = null;
        try
        {
            Class.forName(strdrive );
            conn = DriverManager.getConnection(url, usr, pwd);
            out.println("connected....!!");
    
        }
    
        catch(Exception e)
        {
            out.println("Exception : " + e.getMessage() + "");
        }
    
    
    %>

    ขั้นตอนที่6 ต้องสร้างตัวแปลเพื่อใช้ในการประมวลผล

    Statement st; // ใช้ในการรับคำสัง sql
    ResultSet rs;  //เก็บข้อมูลที่ได้ขาการประมวลผล
    

    ขั้นตอนที่ 7 ทดสอบการทำงาน

    String SQL="select T1 from table";
    rs=st.executeQuery(SQL);
           while(rs.next())
           {
              out.println("number is: "+rs.getString(1));%>          
           }