အခန်း 23 · animation 2 ခု

Chapter 22: Python နှင့် MySQL (Python with MySQL)

808 Coder မှ တင်ဆက်သည်

အရင်အခန်းမှာ database ဆိုတာဘာလဲ၊ SQL နဲ့ table တွေ ဘယ်လိုကိုင်တွယ်ရလဲဆိုတာ လေ့လာခဲ့ပြီးပြီ။ ဒါပေမယ့် SQL ကို MySQL program ထဲမှာ ကိုယ်တိုင် ရိုက်နေရတုန်းပဲ။ လက်တွေ့မှာ program တွေက database ကို အလိုအလျောက် ဆက်သွယ်ရတယ် — ဥပမာ ဆိုင်ရဲ့ POS program က ရောင်းလိုက်တဲ့ ပစ္စည်းရဲ့ stock ကို သူ့ဘာသာ လျှော့ပေးရတယ်။

ဒီအခန်းမှာ Python program ကနေ MySQL database ကို တိုက်ရိုက် ချိတ်ဆက်ပြီး CRUD လုပ်ငန်းတွေ လုပ်မယ်။ ဒါ ဒီစာအုပ်ရဲ့ အဆုံးသတ် အခန်း (capstone) ဖြစ်တယ် — အရင်အခန်းတွေက သင်ခဲ့တဲ့ function၊ loop၊ condition၊ exception handling စတာတွေအားလုံးကို database နဲ့ ပေါင်းပြီး တကယ့် program အပြည့်အစုံ ၂ ခု တည်ဆောက်ကြည့်မယ်။

ဒီအခန်းပြီးရင်...

  • MySQL server နဲ့ mysql-connector-python package ကို install လုပ်နိုင်မယ်
  • Python ကနေ MySQL ကို ချိတ်ဆက်ပြီး cursor နဲ့ SQL command တွေ run နိုင်မယ်
  • Parameterized query (%s) သုံးပြီး SQL injection အန္တရာယ်ကို ကာကွယ်နိုင်မယ်
  • Python ကနေ database/table ဖန်တီး၊ data ထည့်/ဖတ်/ပြင်/ဖျက် လုပ်နိုင်မယ်
  • Database သုံးတဲ့ program အပြည့်အစုံ ၂ ခု (Student Management System နဲ့ Pharmacy POS) ကို ကိုယ်တိုင် ရေးနိုင်မယ်

1. ပြင်ဆင်ခြင်း (Prerequisites)

မစခင် အရာ ၂ ခု လိုအပ်တယ်။

၁။ MySQL ကို install လုပ်ထားရမယ်။ MySQL server က ကိုယ့်ကွန်ပျူတာမှာ install လုပ်ပြီး run နေရမယ်။ ဒီကနေ ဒေါင်းလုဒ်လုပ်နိုင်တယ်။

Install လုပ်ပြီးရင် root user ရဲ့ password ကို မှတ်ထားပါ — Python ကနေ ချိတ်ဆက်တဲ့အခါ လိုမယ်။

၂။ Python package တစ်ခု install လုပ်ရမယ်။ Python ကနေ MySQL နဲ့ စကားပြောဖို့ တံတားတစ်ခု လိုတယ်။ MySQL ကုမ္ပဏီကိုယ်တိုင်ထုတ်တဲ့ official package ဖြစ်တဲ့ mysql-connector-python ကို သုံးမယ်။

pip install mysql-connector-python

Install အောင်မြင်သွားရင် စလို့ရပြီ။

Reference

  • MySQL Downloads — MySQL Community Server ကို ဒီကနေ ဒေါင်းလုဒ်လုပ်ပြီး install လုပ်ပါ၊ root password ကို သေချာ မှတ်ထားပါ
  • Python + MySQL (W3Schools) — install အဆင့်တွေနဲ့ ပထမဆုံး ချိတ်ဆက်မှုကို အင်္ဂလိပ်လို အသေးစိတ် ဖတ်နိုင်တယ်

2. Python ကနေ MySQL ကို ချိတ်ဆက်ခြင်း (Connecting to MySQL)

Server ကို ချိတ်ဆက်မယ်

import mysql.connector

conn = mysql.connector.connect(
    host="localhost",
    user="root",
    password="yourpassword"
)

print("Connected successfully!")
Connected successfully!

ဒီ code ကို တစ်ကြောင်းချင်း ကြည့်ရအောင်။

  • import mysql.connector — MySQL နဲ့ စကားပြောပေးမယ့် package ကို ခေါ်တာ။
  • mysql.connector.connect(...) — MySQL server ကို ချိတ်ဆက်တာ။ ရလာတဲ့ connection object (conn) က server နဲ့ ချိတ်ထားတဲ့ ကြိုးဖုန်းလိုင်းလိုပဲ — ဒီကနေတစ်ဆင့် စကားပြောရမယ်။
  • host="localhost" — MySQL က ကိုယ့်စက်ပေါ်မှာပဲ run နေတယ် (localhost = ကိုယ့်စက်)။
  • user="root" နဲ့ password="yourpassword" — MySQL ရဲ့ username နဲ့ password။ "yourpassword" နေရာမှာ ကိုယ့် တကယ့် password ကို ထည့်ပါ။
  • ဒီအဆင့်မှာ database= မထည့်ထားဘူး — ဘာလို့လဲဆိုတော့ database မဖန်တီးရသေးလို့ server သက်သက်ကို ချိတ်တာပါ။

မှတ်ချက်

connect() မှာ database="learning_db" လို့ ထည့်လိုက်ရင် အဲဒီ database ရှိပြီးသား ဖြစ်နေရမယ်။ မရှိသေးရင် error တက်မယ်။ ဒါ့ကြောင့် database အသစ် ဖန်တီးမယ့်အခါ database လိုင်းကို ဖြုတ်ထားရတယ်။

Cursor ဆိုတာဘာလဲ

Database ကို ချိတ်ပြီးရင် SQL command တွေ ပို့ဖို့ cursor လိုတယ်။ Cursor ဆိုတာ SQL ကို ကိုင်ဆောင်ပြီး server ဆီ ပို့၊ အဖြေကို ပြန်သယ်လာပေးတဲ့ "လက်" လိုပဲ။

cursor = conn.cursor()
cursor.execute("CREATE DATABASE IF NOT EXISTS learning_db")
print("Database created!")
Database created!
  • conn.cursor() — connection ကနေ cursor တစ်ခု ဖန်တီးတယ်။
  • cursor.execute(...) — SQL command တစ်ခုကို server ဆီ ပို့ပြီး run ခိုင်းတယ်။
  • IF NOT EXISTS ဆိုတာ "မရှိရင်သာ ဖန်တီးပါ၊ ရှိပြီးသားဆို ဘာမှ မလုပ်နဲ့" လို့ ပြောတာ — program ကို ထပ်ခါ run ရင် error မတက်ဘူး။

Python ကနေ Table တည်ဆောက်ခြင်း

အခု learning_db database ကို ချိတ်ပြီး table တစ်ခု တည်ဆောက်ကြည့်မယ်။

import mysql.connector

conn = mysql.connector.connect(
    host="localhost",
    user="root",
    password="yourpassword",
    database="learning_db"
)
cursor = conn.cursor()

cursor.execute("""
CREATE TABLE IF NOT EXISTS members (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100),
    age INT
)
""")
print("Table created!")
Table created!

SQL ကို triple-quoted string ("""...""") ထဲမှာ ရေးထားတယ် — စာကြောင်းအရှည် ရေးရတာ လွယ်လို့ ဒီနည်းက အဆင်ပြေတယ်။ အရင်အခန်းက SQL နဲ့ အတူတူပဲ — id က PRIMARY KEY + AUTO_INCREMENT ဖြစ်တယ်။

Python talks to MySQL through a connector + cursor Python program mysql.connector (the bridge) MySQL server connect cursor carries SQL -> <- brings results back
Python → mysql.connector → MySQL server ဆက်သွယ်ပုံ

သတိပြုရန်

cursor.execute() က SQL ကို ပို့ရုံပဲ — ပြောင်းလဲမှု (INSERT/UPDATE/DELETE) တွေကို အတည်ပြုဖို့ conn.commit() လိုသေးတယ်။ commit() အကြောင်း နောက်အပိုင်းမှာ အသေးစိတ် ပြောမယ်။

Reference

  • MySQL Downloads — MySQL server run နေဖို့ လိုတယ်၊ မရှိသေးရင် ဒီကနေ ရယူပါ
  • Python + MySQL (W3Schools) — connect() နဲ့ cursor အလုပ်လုပ်ပုံကို ဥပမာအပိုတွေနဲ့ လေ့လာနိုင်တယ်

3. Parameterized Query — %s နဲ့ ဘာကြောင့် သုံးရသလဲ (Why parameterized queries?)

အန္တရာယ်ရှိတဲ့နည်း (မလုပ်သင့်ဘူး)

Data ထည့်တဲ့အခါ အလွယ်နည်းနဲ့ f-string သုံးပြီး SQL ထဲ တိုက်ရိုက် ထည့်ရေးမိတတ်တယ်။

name = input("Enter name: ")
cursor.execute(f"INSERT INTO members (name, age) VALUES ('{name}', 20)")

ဒါ အလုပ်လုပ်တယ် — ဒါပေမယ့် အရမ်းအန္တရာယ်များတယ်။ ဘာလို့လဲဆိုတော့ user ရိုက်ထည့်တဲ့ စာသားက SQL command ရဲ့ အစိတ်အပိုင်း ဖြစ်သွားလို့ပဲ။

ဆိုးသွမ်းတဲ့ user တစ်ယောက်က name နေရာမှာ ဒါကို ရိုက်ထည့်လိုက်တယ်ဆိုပါစို့။

x'); DROP TABLE members; --

အဲဒါဆို server ဆီ ရောက်သွားတဲ့ SQL က ဒီလို ဖြစ်သွားမယ်။

INSERT INTO members (name, age) VALUES ('x'); DROP TABLE members; --', 20)

DROP TABLE members; ဆိုတာ table တစ်ခုလုံးကို ဖျက်ပစ်တဲ့ command — ဆိုလိုတာက user ရိုက်ထည့်တဲ့ စာသားကနေ database တစ်ခုလုံး ပျက်သွားနိုင်တယ်။ ဒီလို တိုက်ခိုက်မှုကို SQL injection လို့ ခေါ်တယ်။ လက်တွေ့ website တွေ အများကြီး ဒီနည်းနဲ့ ဖောက်ထွင်းခံရဖူးတယ်။

မှန်ကန်တဲ့နည်း — %s placeholder

sql = "INSERT INTO members (name, age) VALUES (%s, %s)"
values = ("Ma Thida", 19)
cursor.execute(sql, values)
conn.commit()
print(cursor.rowcount, "record inserted.")
1 record inserted.

ဒီနည်းမှာ %s ဆိုတာ placeholder (နေရာယထား) ပဲ — "ဒီနေရာမှာ တန်ဖိုးတစ်ခု လာမယ်" လို့ ပြောတာ။ တကယ့် တန်ဖိုးတွေကို values ဆိုတဲ့ tuple ထဲမှာ သပ်သပ် ပေးတယ်။ mysql.connector က အဲဒီတန်ဖိုးတွေကို SQL command အဖြစ် အဓိပ္ပာယ် မကောက်ဘဲ၊ သန့်ရှင်းအောင် စီမံပြီး (escape လုပ်ပြီး) server ဆီ ပို့ပေးတယ်။

ဆိုလိုတာက — user က x'); DROP TABLE members; -- လို့ ရိုက်ထည့်ရင်တောင် အဲဒါက name ဆိုတဲ့ စာသားအဖြစ် သက်သက်ပဲ သိမ်းသွားမယ်။ SQL command အဖြစ် run မသွားဘူး။ SQL injection ကာကွယ်ပြီးသား ဖြစ်သွားပြီ။

Parameterized queries: code and data stay separate SQL template VALUES (%s, %s) values tuple ("Ma Thida", 19) kept SEPARATE mysql.connector safely combines safe SQL sent user input can NEVER become code X SQL injection blocked
parameterized query က SQL injection ကာကွယ်ပုံ

conn.commit() — အတည်ပြုသိမ်းဆည်းခြင်း

cursor.execute(sql, values)
conn.commit()

execute() က SQL ကို ပို့ပေးရုံပဲ။ INSERT / UPDATE / DELETE လို ပြောင်းလဲမှုတွေက conn.commit() လို့ ခေါ်မှ တကယ် database ထဲမှာ အတည်ဖြစ်သွားတယ်။ commit() မေ့သွားရင် program ပိတ်သွားတာနဲ့ ပြောင်းလဲမှုတွေ ပျောက်သွားမယ် — data ဝင်သွားပြီလို့ ထင်နေပေမယ့် တကယ်မဝင်ဘူး။

ရိုးရိုးလေး မှတ်ထား — ထည့်/ပြင်/ဖျက်ပြီးတိုင်း commit() ခေါ်ပါ။

cursor.rowcount — ဘယ်နှခုထိခိုက်သလဲ

cursor.rowcount က နောက်ဆုံး execute လုပ်တဲ့ command က row ဘယ်နှခုကို ထိခိုက်သွားလဲဆိုတာ ပြောပြတယ်။ အပေါ်က ဥပမာမှာ 1 record inserted. လို့ ထွက်လာတယ် — row တစ်ခု ထည့်ပြီးသွားပြီဆိုတဲ့ အတည်ပြုချက်ပဲ။

မှတ်ချက်

တန်ဖိုးတစ်ခုတည်းကို tuple အဖြစ် ပေးရတဲ့အခါ ကော်မာ (comma) ထည့်ဖို့ မမေ့နဲ့ — ("Ma Thida",) လို့ ရေးရမယ်။ ("Ma Thida") လို့ ရေးရင် Python က tuple လို့ မမှတ်ဘဲ စာသားလို့ပဲ မှတ်တယ်။

သတိပြုရန်

%s placeholder က Python ရဲ့ % string formatting နဲ့ မတူဘူး။ SQL ထဲက %s တွေကို % operator နဲ့ ကိုယ်တိုင် ဖြည့်တာမျိုး လုံးဝ မလုပ်ပါနဲ့ — အဲဒါလည်း SQL injection အန္တရာယ် ရှိတယ်။ တန်ဖိုးတွေကို execute(sql, values) ရဲ့ ဒုတိယ argument အဖြစ် အမြဲ ပေးပါ။

Reference

  • Python + MySQL (W3Schools) — parameterized query နဲ့ %s placeholder သုံးပုံကို ဥပမာတွေနဲ့ လေ့လာနိုင်တယ်
  • MySQL Downloads — စမ်းသပ်ဖို့ MySQL server လိုတယ်၊ ဒီကနေ ရယူနိုင်တယ်

4. Data ဖတ်ခြင်း၊ ပြင်ခြင်း၊ ဖျက်ခြင်း (Reading, Updating, Deleting)

SELECT — fetchall() နဲ့ fetchone()

Table ထဲက data အားလုံး ဖတ်ချင်ရင် fetchall() သုံးတယ် — row အားလုံးကို list အဖြစ် ပြန်ပေးတယ်။

cursor.execute("SELECT * FROM members")
for row in cursor.fetchall():
    print("ID:", row[0], "Name:", row[1], "Age:", row[2])
ID: 1 Name: Ma Thida Age: 19
ID: 2 Name: Ko Aung Age: 22

Row တစ်ခုချင်းစီက tuple တစ်ခု — row[0] က id၊ row[1] က name၊ row[2] က age။ Column အစီအစဉ် (SELECT * ဆိုရင် table ထဲက အစီအစဉ်အတိုင်း) ကို သိထားရမယ်။

Row တစ်ခုတည်း လိုချင်ရင် fetchone() သုံးတယ်။ မတွေ့ရင် None ပြန်ပေးတယ်။

cursor.execute("SELECT * FROM members WHERE id = %s", (1,))
row = cursor.fetchone()
if row:
    print("Found:", row)
else:
    print("Not found.")
Found: (1, 'Ma Thida', 19)

UPDATE — Data ပြင်ဆင်ခြင်း

sql = "UPDATE members SET age = %s WHERE name = %s"
values = (20, "Ma Thida")
cursor.execute(sql, values)
conn.commit()
print(cursor.rowcount, "record(s) updated.")
1 record(s) updated.

အရင်အခန်းက SQL နဲ့ အတူတူပဲ — ကွာတာက တန်ဖိုးတွေကို %s placeholder နဲ့ ပေးတာ။ commit() ခေါ်ဖို့ မမေ့နဲ့။

DELETE — Data ဖျက်ပစ်ခြင်း

sql = "DELETE FROM members WHERE name = %s"
values = ("Ko Aung",)
cursor.execute(sql, values)
conn.commit()
print(cursor.rowcount, "record(s) deleted.")
1 record(s) deleted.

သတိပြုရန်

SQL အခန်းမှာ သတိပေးခဲ့သလိုပဲ — UPDATE နဲ့ DELETE မှာ WHERE မပါရင် row အားလုံး ထိခိုက်သွားမယ်။ Python program တွေမှာ ဒီအမှားက ပိုအန္တရာယ်များတယ်၊ ဘာလို့လဲဆိုတော့ program က အလိုအလျောက် run သွားလို့ လူက တားချိန် မရဘူး။ WHERE ပါတယ်/မပါဘူး အမြဲ နှစ်ခါစစ်ပါ။

Connection ပိတ်ခြင်း

အလုပ်ပြီးရင် cursor နဲ့ connection ကို ပိတ်ရမယ် — file ကို close() လုပ်သလိုပဲ။ မပိတ်ဘဲ ထားရင် server ဘက်မှာ resource တွေ ပိတ်မိနေမယ်။

cursor.close()
conn.close()
print("Connection closed.")
Connection closed.

Reference

  • Python + MySQL (W3Schools) — fetchall()၊ fetchone()၊ rowcount သုံးပုံတွေကို ဥပမာအပြည့်အစုံနဲ့ ကြည့်နိုင်တယ်
  • MySQL Downloads — SELECT/UPDATE/DELETE တွေကို ကိုယ့် MySQL မှာ လက်တွေ့ စမ်းသပ်ပါ

5. Mini Project 1 — Student Management System

အခု တကယ့် program အပြည့်အစုံ တစ်ခု ရေးကြည့်မယ်။ ကွန်ပျူတာသင်တန်း (Sunshine Academy) တစ်ခုအတွက် ကျောင်းသားစာရင်း စီမံခန့်ခွဲတဲ့ system ဖြစ်တယ်။ လုပ်နိုင်တာတွေ။

  1. ကျောင်းသားအသစ် ထည့်မယ်
  2. ကျောင်းသားအားလုံး ကြည့်မယ်
  3. ID နဲ့ ကျောင်းသား ရှာမယ်
  4. ကျောင်းသား အချက်အလက် ပြင်မယ်
  5. ID နဲ့ ကျောင်းသား ဖျက်မယ်
  6. ထွက်မယ်

Database နဲ့ Table ပြင်ဆင်ခြင်း

CREATE DATABASE IF NOT EXISTS sunshine_academy;
USE sunshine_academy;
CREATE TABLE IF NOT EXISTS students (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    age INT,
    course VARCHAR(30)
);

Program အပြည့်အစုံ

import mysql.connector

conn = mysql.connector.connect(
    host="localhost",
    user="root",
    password="yourpassword",
    database="sunshine_academy"
)
cursor = conn.cursor()


def add_student(name, age, course):
    query = "INSERT INTO students (name, age, course) VALUES (%s, %s, %s)"
    cursor.execute(query, (name, age, course))
    conn.commit()
    print("Student added successfully.")


def view_students():
    cursor.execute("SELECT * FROM students")
    rows = cursor.fetchall()
    if not rows:
        print("No students found.")
        return
    print(f"{'ID':<5}{'Name':<20}{'Age':<6}Course")
    print("-" * 45)
    for row in rows:
        print(f"{row[0]:<5}{row[1]:<20}{row[2]:<6}{row[3]}")


def search_student(student_id):
    cursor.execute("SELECT * FROM students WHERE id = %s", (student_id,))
    result = cursor.fetchone()
    if result:
        print("Student found:", result)
    else:
        print("Student not found.")


def update_student(student_id, name, age, course):
    query = "UPDATE students SET name = %s, age = %s, course = %s WHERE id = %s"
    cursor.execute(query, (name, age, course, student_id))
    conn.commit()
    if cursor.rowcount:
        print("Student updated successfully.")
    else:
        print("No student with that ID.")


def delete_student(student_id):
    cursor.execute("DELETE FROM students WHERE id = %s", (student_id,))
    conn.commit()
    if cursor.rowcount:
        print("Student deleted successfully.")
    else:
        print("No student with that ID.")


def menu():
    while True:
        print("\n--- Student Management System ---")
        print("1. Add Student")
        print("2. View Students")
        print("3. Search Student by ID")
        print("4. Update Student")
        print("5. Delete Student")
        print("6. Exit")

        choice = input("Enter your choice: ")

        if choice == "1":
            name = input("Enter name: ")
            age = int(input("Enter age: "))
            course = input("Enter course: ")
            add_student(name, age, course)
        elif choice == "2":
            view_students()
        elif choice == "3":
            student_id = int(input("Enter student ID: "))
            search_student(student_id)
        elif choice == "4":
            student_id = int(input("Enter student ID: "))
            name = input("Enter new name: ")
            age = int(input("Enter new age: "))
            course = input("Enter new course: ")
            update_student(student_id, name, age, course)
        elif choice == "5":
            student_id = int(input("Enter student ID: "))
            delete_student(student_id)
        elif choice == "6":
            print("Exiting...")
            break
        else:
            print("Invalid choice. Try again.")


menu()
cursor.close()
conn.close()

နမူနာ အသုံးပြုပုံ

--- Student Management System ---
1. Add Student
2. View Students
3. Search Student by ID
4. Update Student
5. Delete Student
6. Exit
Enter your choice: 1
Enter name: Thiri Nanda
Enter age: 18
Enter course: Python Foundation
Student added successfully.

--- Student Management System ---
1. Add Student
2. View Students
3. Search Student by ID
4. Update Student
5. Delete Student
6. Exit
Enter your choice: 2
ID   Name                Age   Course
---------------------------------------------
1    Thiri Nanda         18    Python Foundation
2    Zaw Htet            20    Web Development

ဒီ program မှာ သတိထားရမယ့် အချက်တွေ။

  • Function တစ်ခုချင်းစီက database လုပ်ငန်းတစ်ခုကို တာဝန်ယူတယ် — add_student၊ view_students စသဖြင့်။ ဒါ function အခန်းမှာ သင်ခဲ့တဲ့ "လုပ်ငန်းခွဲဝေခြင်း" သဘောတရားပဲ။
  • update_student နဲ့ delete_student မှာ cursor.rowcount ကို စစ်တယ် — ID မှားရိုက်မိရင် "No student with that ID." လို့ ပြောပြတယ်။
  • view_students မှာ f-string ရဲ့ {:<5} formatting နဲ့ column တွေ ညီအောင် ပြထားတယ်။

သတိပြုရန်

int(input("Enter age: ")) မှာ user က စာသား ရိုက်ထည့်မိရင် ValueError တက်မယ်။ အခန်း ၁၉ (Exception Handling) မှာ သင်ခဲ့တဲ့ try/except နဲ့ ကာကွယ်ထားနိုင်တယ်။ ဒီ program ကို ပိုကောင်းအောင် လုပ်ချင်ရင် အဲဒါက ပထမဆုံး တိုးတက်မှုပဲ။

Reference

  • Python + MySQL (W3Schools) — ဒီ project မှာသုံးတဲ့ technique အားလုံးရဲ့ အခြေခံ ဥပမာတွေ ရှိတယ်
  • MySQL Downloads — project ကို run ဖို့ MySQL server လိုတယ်

6. Mini Project 2 — Pharmacy POS System

ဒုတိယ project က ဆေးဆိုင် (pharmacy) တစ်ခုအတွက် POS (Point of Sale) system — ပစ္စည်းစာရင်း စီမံတာ၊ ရောင်းတာ၊ ဘေလ်ထုတ်တာတွေ လုပ်နိုင်တယ်။ ပထမ project ထက် တစ်ဆင့် ပိုရှုပ်တယ် — ရောင်းတဲ့အခါ stock ရှိမရှိ စစ်ရမယ်၊ လက်ကျန် လျှော့ရမယ်၊ စုစုပေါင်း ကျသင့်ငွေ တွက်ရမယ်။

လုပ်နိုင်တာတွေ။

  1. ဆေးအသစ် ထည့်မယ်
  2. ဆေးအားလုံး ကြည့်မယ်
  3. ဆေး ရှာမယ် (နာမည်အစိတ်အပိုင်းနဲ့)
  4. ဆေး အချက်အလက် ပြင်မယ်
  5. ဆေး ဖျက်မယ်
  6. ဆေး ရောင်းမယ် (stock စစ်မယ်၊ ဘေလ် ထုတ်မယ်)
  7. ထွက်မယ်

Database နဲ့ Table ပြင်ဆင်ခြင်း

CREATE DATABASE IF NOT EXISTS pharmacy_pos;
USE pharmacy_pos;
CREATE TABLE IF NOT EXISTS medicines (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100),
    company VARCHAR(100),
    price FLOAT,
    quantity INT
);

Program အပြည့်အစုံ

import mysql.connector

conn = mysql.connector.connect(
    host="localhost",
    user="root",
    password="yourpassword",
    database="pharmacy_pos"
)
cursor = conn.cursor()


def add_medicine(name, company, price, quantity):
    query = """INSERT INTO medicines (name, company, price, quantity)
               VALUES (%s, %s, %s, %s)"""
    cursor.execute(query, (name, company, price, quantity))
    conn.commit()
    print("Medicine added.")


def view_medicines():
    cursor.execute("SELECT * FROM medicines")
    rows = cursor.fetchall()
    if not rows:
        print("No medicines found.")
        return
    print(f"{'ID':<4}{'Name':<18}{'Company':<16}{'Price':<10}Qty")
    print("-" * 55)
    for row in rows:
        print(f"{row[0]:<4}{row[1]:<18}{row[2]:<16}{row[3]:<10}{row[4]}")


def search_medicine(name):
    cursor.execute("SELECT * FROM medicines WHERE name LIKE %s",
                   ("%" + name + "%",))
    results = cursor.fetchall()
    if results:
        for row in results:
            print(row)
    else:
        print("No medicine found.")


def update_medicine(med_id, name, company, price, quantity):
    query = """UPDATE medicines
               SET name = %s, company = %s, price = %s, quantity = %s
               WHERE id = %s"""
    cursor.execute(query, (name, company, price, quantity, med_id))
    conn.commit()
    if cursor.rowcount:
        print("Medicine updated.")
    else:
        print("No medicine with that ID.")


def delete_medicine(med_id):
    cursor.execute("DELETE FROM medicines WHERE id = %s", (med_id,))
    conn.commit()
    if cursor.rowcount:
        print("Medicine deleted.")
    else:
        print("No medicine with that ID.")


def sell_medicine(med_id, sell_qty):
    cursor.execute(
        "SELECT name, price, quantity FROM medicines WHERE id = %s",
        (med_id,)
    )
    data = cursor.fetchone()
    if not data:
        print("Medicine not found.")
        return

    name, price, quantity = data

    if quantity < sell_qty:
        print("Not enough stock!")
        return

    new_quantity = quantity - sell_qty
    cursor.execute(
        "UPDATE medicines SET quantity = %s WHERE id = %s",
        (new_quantity, med_id)
    )
    conn.commit()

    total = sell_qty * price
    print(f"SOLD: {sell_qty} x {name} @ {price} Ks = {total} Ks")


def menu():
    while True:
        print("\n--- Pharmacy POS ---")
        print("1. Add Medicine")
        print("2. View Medicines")
        print("3. Search Medicine")
        print("4. Update Medicine")
        print("5. Delete Medicine")
        print("6. Sell Medicine")
        print("7. Exit")

        choice = input("Enter choice: ")

        if choice == "1":
            name = input("Name: ")
            company = input("Company: ")
            price = float(input("Price: "))
            quantity = int(input("Quantity: "))
            add_medicine(name, company, price, quantity)
        elif choice == "2":
            view_medicines()
        elif choice == "3":
            name = input("Enter medicine name to search: ")
            search_medicine(name)
        elif choice == "4":
            med_id = int(input("Enter medicine ID to update: "))
            name = input("New name: ")
            company = input("New company: ")
            price = float(input("New price: "))
            quantity = int(input("New quantity: "))
            update_medicine(med_id, name, company, price, quantity)
        elif choice == "5":
            med_id = int(input("Enter medicine ID to delete: "))
            delete_medicine(med_id)
        elif choice == "6":
            med_id = int(input("Enter medicine ID to sell: "))
            sell_qty = int(input("Enter quantity to sell: "))
            sell_medicine(med_id, sell_qty)
        elif choice == "7":
            print("Exiting...")
            break
        else:
            print("Invalid choice.")


menu()
cursor.close()
conn.close()

နမူနာ အသုံးပြုပုံ

ဆေး ၃ မျိုး ထည့်ထားတယ်ဆိုပါစို့။

--- Pharmacy POS ---
1. Add Medicine
2. View Medicines
3. Search Medicine
4. Update Medicine
5. Delete Medicine
6. Sell Medicine
7. Exit
Enter choice: 2
ID  Name              Company         Price     Qty
-------------------------------------------------------
1   Paracetamol       Pacific         500.0     100
2   Amoxicillin       AA Medical      1200.0    50
3   Vitamin C         Seoul Pharma    800.0     75
Enter choice: 6
Enter medicine ID to sell: 1
Enter quantity to sell: 10
SOLD: 10 x Paracetamol @ 500.0 Ks = 5000.0 Ks

ဒီ project မှာ အရေးကြီးတဲ့ အချက်တွေ။

  • LIKE နဲ့ ရှာဖွေခြင်း — search_medicine("cillin") လို့ ရှာရင် "Amoxicillin" ထွက်လာမယ်။ % သင်္ကေတက "ရှေ့/နောက် ဘာပဲရှိရှိ ရတယ်" လို့ အဓိပ္ပာယ်ရတယ်။ သတိထားပါ — LIKE ထဲက % က SQL ရဲ့ wildcard ဖြစ်ပြီး၊ parameterized query ရဲ့ %s placeholder နဲ့ မတူဘူး။
  • Stock စစ်ဆေးခြင်း — sell_medicine က အရင် SELECT နဲ့ လက်ကျန်ကို ဖတ်တယ်။ ရောင်းချင်တဲ့ အရေအတွက်ထက် လက်ကျန် နည်းနေရင် "Not enough stock!" လို့ ပြောပြီး ရပ်လိုက်တယ်။ ဒါ လက်တွေ့ business logic ပဲ — မရှိတဲ့ ပစ္စည်း ရောင်းလို့ မရဘူး။
  • Tuple unpacking — name, price, quantity = data ဆိုတာ fetchone() က ပြန်ပေးတဲ့ tuple ကို တစ်ခါတည်း variable ၃ ခုထဲ ခွဲထည့်တာ။ အခန်း ၁၀ (Tuple) မှာ သင်ခဲ့တဲ့ unpacking ပဲ။
  • ဘေလ် — total = sell_qty * price နဲ့ ကျသင့်ငွေ တွက်ပြီး f-string နဲ့ ရှင်းရှင်းလင်းလင်း ပြတယ်။

မှတ်ချက်

sell_medicine မှာ လုပ်ငန်း ၂ ခု (SELECT ပြီးမှ UPDATE) ဆက်တိုက် လုပ်တယ်။ တကယ့် ဆိုင်ကြီးတွေမှာ ဒါမျိုး အဆင့်နှစ်ဆင့်ကို တစ်ပြိုင်နက် ပြီးအောင် "transaction" ဆိုတဲ့ ယန္တရား သုံးတယ်။ အခု အခြေခံအဆင့်မှာတော့ commit() တစ်ခါ ခေါ်တာနဲ့ လုံလောက်တယ်။

Reference

  • Python + MySQL (W3Schools) — LIKE ရှာဖွေမှု၊ UPDATE logic စတာတွေရဲ့ အခြေခံ ဥပမာတွေ ရှိတယ်
  • MySQL Downloads — ဒီ POS project ကို ကိုယ်တိုင် run ကြည့်ဖို့ MySQL server လိုတယ်

လေ့ကျင့်ခန်းများ

  1. Database နဲ့ table ဖန်တီးခြင်း — Python program တစ်ခု ရေးပြီး bookstore_db ဆိုတဲ့ database နဲ့ အထဲမှာ books table (id, title, author, price, stock) ကို cursor.execute() နဲ့ ဖန်တီးပါ။ IF NOT EXISTS ထည့်ဖို့ မမေ့နဲ့။

  2. Parameterized INSERT — အပေါ်က books table ထဲကို စာအုပ် ၃ အုပ် ထည့်ပါ။ %s placeholder သုံးရမယ်။ ပြီးရင် cursor.rowcount ကို print ထုတ်ပါ။

  3. SQL injection ရှင်းပြခြင်း — SQL injection ဆိုတာဘာလဲ၊ ဘာကြောင့် ဖြစ်တာလဲဆိုတာ ကိုယ့်စကားနဲ့ ရှင်းပြပါ။ f-string နဲ့ SQL တည်ဆောက်ရင် တိုက်ခိုက်သူက ဘယ်လို အသုံးချနိုင်လဲဆိုတဲ့ ဥပမာ တစ်ခုပေးပါ။

  4. Project တိုးချဲ့ခြင်း — Mini Project 1 (Student Management System) မှာ နာမည်နဲ့ ရှာတဲ့ search_by_name() function တစ်ခု ထည့်ပါ။ LIKE သုံးပြီး နာမည် အစိတ်အပိုင်းနဲ့ ရှာနိုင်ရမယ်။ Menu ထဲမှာလည်း option အသစ် ထည့်ပါ။

  5. အစွမ်းကုန် စိန်ခေါ်မှု — Pharmacy POS မှာ ရောင်းပြီးတိုင်း ဘေလ်မှာ ရက်စွဲ (datetime module သုံးပါ) ပါ ပြနိုင်အောင် ပြင်ပါ။ ပြီးရင် တစ်နေ့တာ စုစုပေါင်း ရောင်းရငွေကို ပြတဲ့ daily_report() function တစ်ခု ထပ်ရေးပါ။ (အရိပ်အမြွက် — ရောင်းအားမှတ်တမ်းကို table သပ်သပ် တစ်ခု (sales table) မှာ သိမ်းရင် ပိုလွယ်မယ်။)