[VB.NET] พื้นฐานการเขียนโปรแกรมแบบ CRUD (Create, Read, Update, Delete) กับตัวอย่างฐานข้อมูลผู้ป่วย MS Access
http://www.g2gnet.com/webboard/images/vbnet/PatientVB.pngที่ต้องบอกว่าเป็นพื้นฐาน ก็เพราะว่าแอดมินจะใช้ตารางข้อมูลแบบเดี่ยวๆ โดยที่ไม่มีการสร้างความสัมพันธ์ใดๆระหว่างตารางข้อมูลเลย โดยจะเน้นแนวทางให้ศึกษาวิธีการ เพิ่มรายการใหม่ (Create) การอ่านหรือค้นคืน (Read/Retrieve) การปรับปรุง (Update) และการลบข้อมูล (Delete) ซึ่งเป็นพื้นฐานของการเขียนโปรแกรมเพื่อติดต่อกับฐานข้อมูล แต่โดยรวมๆการควบคุมโปรแกรม (Flow Control) จะเรียงลำดับขั้นตอนนี้ คือ
การค้นคืนข้อมูล จะมี 2 ลักษณะคือ
- หากไม่พบข้อข้อมูลที่ต้องการ ก็คือต้องไปทำการสร้างใหม่
- หากพบข้อมูล ก็จะมี 2 ทางเลือก คือ นำมาแก้ไข หรือ ลบข้อมูล
http://www.g2gnet.com/webboard/images/vbnet/PatientDB.png
การออกแบบตารางข้อมูลอย่างง่าย
จบภาคทฤษฎีเล็กๆ ก็จะมาว่ากันเรื่องการปฏิบัติ โดยเน้นการลงมือทำ อันเป็นหัวใจสำคัญของการเรียนรู้ ...
โค้ดในการค้นคืนข้อมูล ...
' / --------------------------------------------------------------------
' / Data Retrieval
Private Sub RetrieveData(Optional ByVal blnSearch As Boolean = False)
If blnSearch Then
strSQL = _
" SELECT Patient.HNPK, Patient.HN, Patient.PatientName, Patient.Address, Patient.Amphur, Patient.ProvinceName, Patient.PostCode, Patient.Telephone, Patient.BirthDate, Patient.Sex, Patient.Blood " & _
" FROM(Patient) " & _
" WHERE " & _
" " & " Like '%" & txtSearch.Text & "%'" & " OR " & _
" " & " Like '%" & txtSearch.Text & "%'" & " OR " & _
" " & " Like '%" & txtSearch.Text & "%'" & " OR " & _
" " & " Like '%" & txtSearch.Text & "%'" & " OR " & _
" " & " Like '%" & txtSearch.Text & "%'" & " OR " & _
" " & " Like '%" & txtSearch.Text & "%'" & " OR " & _
" " & " Like '%" & txtSearch.Text & "%'" & " OR " & _
" " & " Like '%" & txtSearch.Text & "%'" & " OR " & _
" " & " Like '%" & txtSearch.Text & "%'" & _
" ORDER BY Patient.HN "
Else
strSQL = _
" SELECT Patient.HNPK, Patient.HN, Patient.PatientName, Patient.Address, Patient.Amphur, Patient.ProvinceName, " & _
" Patient.PostCode, Patient.Telephone, Patient.BirthDate, Patient.Sex, Patient.Blood " & _
" FROM(Patient) ORDER BY Patient.HN "
End If
DA = New OleDb.OleDbDataAdapter(strSQL, Conn)
DS = New DataSet
DS.Clear()
DA.Fill(DS, "Patient")
dgvData.DataSource = DS.Tables("Patient")
lblRecordCount.Text = "[จำนวน : " & dgvData.RowCount & " รายการ]"
'//
DA.Dispose()
DS.Dispose()
Conn.Close()
'//
InitializeGrid()
txtSearch.Clear()
End Subจากโปรแกรมย่อย RetrieveData(Optional ByVal blnSearch As Boolean = False) เป็นเทคนิคในการเขียนโค้ดที่สามารถค้นหาและนำข้อมูลมาแสดงผลได้ในโปรแกรมย่อยตัวเดียวกัน โดยการกำหนดว่า หาก blnSearch = False จะเป็นการแสดงผลข้อมูลทั้งหมด แต่ถ้าหาก blnSearch = True จะเป็นการค้นหาข้อมูล ซึ่งการค้นหาข้อมูลจะมาจากการป้อนค่าใน TextBox
โค้ดการค้นหาข้อมูลที่ป้อนลงใน TextBox
' / --------------------------------------------------------------------
Private Sub txtSearch_KeyPress(sender As Object, e As System.Windows.Forms.KeyPressEventArgs) Handles txtSearch.KeyPress
'// ดักจับตัวอักขระอันไม่พึงปรารถนาสำหรับฐานข้อมูล เช่น ', * หรือ %
txtSearch.Text = Replace(Trim(txtSearch.Text), "'", "")
txtSearch.Text = Replace(Trim(txtSearch.Text), "%", "")
txtSearch.Text = Replace(Trim(txtSearch.Text), "*", "")
If Trim(txtSearch.Text) = "" Or Len(Trim(txtSearch.Text)) = 0 Then Exit Sub
'// SearchData(True) หมายความว่า เป็นการค้นหาข้อมูล
If e.KeyChar = Chr(13) Then '// Chr(13) คือ ASCII Code ของ Enter
'// ปิดเสียงเตือน
e.Handled = True
Call RetrieveData(True)
End If
End SubRetrieveData(True) เพื่อระบุว่าเป็นการค้นหา
การเพิ่มข้อมูลใหม่ (Create)
โค้ดในส่วนของการสร้าง Primary Key เพื่อไม่ให้เกิดมีค่าที่ซ้ำกัน ... นิยามของ Primary Key หรือ PK คือกุญแจหลัก จะมีค่าที่ซ้ำกันไม่ได้ และเปลี่ยนแปลงค่าไม่ได้ การที่เปลี่ยนค่านี้ไม่ได้ ก็เพราะจะต้องนำคีย์หลักตัวนี้ไปเชื่อมต่อ หรือสร้างความสัมพันธ์เข้ากับตารางตัวอื่นๆ และที่สำคัญค่า PK เป็นค่าที่ผู้เขียนโปรแกรมจะต้องอ้างอิงไว้ใช้งาน
' / --------------------------------------------------------------------
' / ฟังค์ชั่นในการหาค่า Primary Key ตัวใหม่ไม่ให้ซ้ำกัน
Function SetupNewPK(ByVal sql As String) As Long
If Conn.State = ConnectionState.Closed Then Conn.Open()
Cmd = New OleDb.OleDbCommand(sql, Conn)
'/ ตรวจสอบว่ามีข้อมูลอยู่หรือไม่ และคืนค่ากลับ
If IsDBNull(Cmd.ExecuteScalar) Then
SetupNewPK = 1
Else
SetupNewPK = Cmd.ExecuteScalar + 1
End If
End Function
โค้ดในส่วนของการสร้าง ID หรือ IDentfier โดยไม่ให้เกิดมีค่าที่ซ้ำกัน ... แอดมินขอแนะนำให้แยกนิยามความหมายของคำว่า Primary Key ออกไปจาก IDentifier ซึ่งในที่นี้ ID ก็คือ HN หรือ Hospital Number ของผู้ป่วย
' / --------------------------------------------------------------------
' / ฟังค์ชั่นในการสร้างรหัสลูกค้า หรือ ID แบบอัตโนมัติ ตามรูปแบบที่เราต้องการ
Function SetupAutoID() As String
strSQL = _
" SELECT MAX(Patient.HNPK) AS MaxPK FROM Patient "
If Conn.State = ConnectionState.Closed Then Conn.Open()
Cmd = New OleDb.OleDbCommand(strSQL, Conn)
Dim MaxPK As Long
'/ ตรวจสอบว่ามีข้อมูลอยู่หรือไม่
If IsDBNull(Cmd.ExecuteScalar) Then
MaxPK = 1
Else
MaxPK = Cmd.ExecuteScalar + 1
End If
'/ ตัวอย่างของการสร้างรูปแบบ ID อัตโนมัติ HN-ปีพ.ศ.XXXXX เช่น HN-6000013
'/ เช่น ได้ MaxPK = 13 เอามาเรียงต่อกันกับ 0 จำนวน 5 ตัว ก็จะได้ "00000" & "13" = "0000013"
'/ ให้นับกลับมาจากทางขวาเข้ามาทางซ้าย ก็จะได้ "00013"
SetupAutoID = "HN-" & Microsoft.VisualBasic.Right(Year(Now), 2) & Microsoft.VisualBasic.Right("00000" & MaxPK, 5)
End Function
ฟังค์ชั่นในการตรวจสอบค่า ID (หรือ HN) ว่ามีค่าที่ซ้ำกันหรือไม่ ... นิยามของ IDentifier หรือ รหัสผู้ป่วย (HN) จะมีค่าที่ซ้ำกันไม่ได้ แต่สามารถเปลี่ยนแปลงค่าได้ การที่มันสามารถเปลี่ยนแปลงค่าได้ ก็เพราะอาจจะเกิดการป้อนข้อมูลที่ผิดพลาดของผู้ใช้งาน และค่า HN จะเป็นค่าที่ Users เขาอ้างอิงถึงเสมอ
' / --------------------------------------------------------------------
' / ฟังค์ชั่นในการหาค่า ID ซ้ำกัน
Public Function DuplicateID(ByVal Sql As String) As Boolean
If Conn.State = ConnectionState.Closed Then Conn.Open()
Cmd = New OleDb.OleDbCommand(Sql, Conn)
' Return count records
DuplicateID = Cmd.ExecuteScalar
End Function
เทคนิคในการดักตรวจสอบค่า HN เพื่อไม่ให้เกิดการซ้ำกันได้ สิ่งแรกคือต้องเก็บค่า HN ของเดิมเอาไว้ในตัวแปรตัวใดตัวหนึ่งก่อน แต่แอดมินใช้คุณสมบัติของ TextBox ที่มีชื่อว่า Tag เพื่อประหยัดตัวแปร ...
txtHN.Text = "" & .Rows(0)("HN").ToString()
'// เก็บค่า HN เดิมเอาไว้ เพื่อทำการเปรียบเทียบในภายหลัง
txtHN.Tag = txtHN.Text- กรณีที่เพิ่มข้อมูลใหม่ ค่าใน Tag = "" แต่ต้องนำค่าคุณสมบัติใน Text ของ TextBox ไปเปรียบเทียบกับของเดิมที่มีอยู่ในตารางข้อมูล
- กรณีที่ทำการแก้ไข จะแบ่งเป็น 2 กรณี คือ
---- ค่าใน Tag = Text นั่นหมายความว่า ไม่มีการแก้ไขค่า HN ก็ให้ทำการบันทึกข้อมูลได้ทันที
---- ค่าใน Tag <> Text แสดงว่ามีการเปลี่ยนแปลงค่า HN ก็จะต้องไปเปรียบเทียบกับของเดิมที่มีอยู่ในตารางข้อมูล
If txtHN.Text.ToLower <> LCase(txtHN.Tag) Then
strSQL = _
" SELECT Count(Patient.HN) AS CountHN FROM Patient " & _
" WHERE HN = " & "'" & txtHN.Text & "'"
If DuplicateID(strSQL) Then
MessageBox.Show("HN มีค่าซ้ำ กรุณาแก้ไขใหม่ให้เรียบร้อยด้วย.", "รายงานความผิดพลาด", MessageBoxButtons.OK, MessageBoxIcon.Warning)
txtHN.Focus()
Exit Sub
End If
End If
โค้ดในส่วนของการบันทึกข้อมูล ... สามารถกระทำได้ทั้งการเพิ่ม (Insert) หรือ การปรับปรุง (Update) ในโปรแกรมย่อยตัวเดียวกัน ก็เพราะแอดมินอาศัยตัวแปรแบบ Boolean ชื่อ NewData หากค่า NewData = True ก็คือการเพิ่มข้อมูลใหม่ หากเป็น False ก็คือการแก้ไข
' / --------------------------------------------------------------------
' / บันทึกข้อมูล
' / --------------------------------------------------------------------
Private Sub SaveData()
If NewData Then
strSQL = _
" INSERT INTO Patient(" & _
" HNPK, HN, PatientName, Address, Amphur, ProvinceName, PostCode, Telephone, " & _
" BirthDate, Sex, Blood, DateAdded, DateModified) " & _
" VALUES('" & _
SetupNewPK(" SELECT MAX(Patient.HNPK) AS MaxPK FROM Patient ") & "','" & _
txtHN.Text & "','" & _
txtPatientName.Text & "','" & _
txtAddress.Text & "','" & _
txtAmphur.Text & "','" & _
txtProvinceName.Text & "','" & _
txtPostCode.Text & "','" & _
txtTelephone.Text & "','" & _
dtpBirthDate.Value & "','" & _
CheckSex() & "','" & _
cmbBlood.Text & "','" & _
Now & "','" & _
Now & _
"')"
'// EDIT MODE
Else
'// START UPDATE
strSQL = _
" UPDATE Patient SET " & _
" HN='" & txtHN.Text & "', " & _
" PatientName='" & txtPatientName.Text & "', " & _
" Address='" & txtAddress.Text & "', " & _
" Amphur='" & txtAmphur.Text & "', " & _
" ProvinceName='" & txtProvinceName.Text & "', " & _
" PostCode='" & txtPostCode.Text & "', " & _
" Telephone='" & txtTelephone.Text & "', " & _
" BirthDate='" & dtpBirthDate.Value & "', " & _
" Sex='" & CheckSex() & "', " & _
" Blood='" & cmbBlood.Text & "', " & _
" DateModified='" & Now & "'" & _
" WHERE HNPK=" & PK & "" ' ค่า PK จะได้มาจากการดับเบิ้ลคลิ๊กเลือกรายการแก้ไขเอาไว้แล้วล่วงหน้า
End If
'// การ Insert/Update กระทำเหมือนกัน
If DoSQL(strSQL) Then
MessageBox.Show("ปรับปรุงข้อมูลเรียบร้อย.", "รายงานสถานะ", MessageBoxButtons.OK, MessageBoxIcon.Information)
End If
'// แสดงข้อมูลในตารางกริดใหม่
RetrieveData()'// Refresh
'// ตั้งค่าโหมด
NewMode()
End Sub
แถมท้ายกับการเรียกข้อมูลมาแสดงผล ... แอดมินมีโค้ดอยู่ 2 ชุด เพื่อให้ศึกษาและเปรียบเทียบ โดยชุดจริงจะเป็นกรณีที่ใช้แบบ Multi-users ซึ่งจะต้องทำการ Query ข้อมูลเข้ามาใหม่ อีกชุดตามโค้ดด้านล่างจะเป็นแบบ Stand Alone โดยการเรียกข้อมูลมาแสดงผลจากตารางกริดแทน ซึ่งการเลือกไปใช้ในงานจริงๆ ก็อยู่ที่ว่าจะเป็นงานเล็กงานใหญ่กันล่ะครับ
' / --------------------------------------------------------------------
' / เรียกข้อมูลจาก DataGrid มาแสดงผล (กรณีใช้ Stand Alone)
' / --------------------------------------------------------------------
Private Sub DataGridToScreen()
'//
Dim iRow As Integer
'// อ่านค่าแถวที่ถูกโฟกัส
iRow = dgvData.CurrentRow.Index
'//
PK = dgvData.Item(0, iRow).Value'// เก็บค่า Primary Key เอาไว้
txtHN.Text = "" & dgvData.Item(1, iRow).Value
'// เก็บค่า HN เดิมเอาไว้ เพื่อทำการเปรียบเทียบในภายหลัง
txtHN.Tag = txtHN.Text
'// การใช้ Double quote "" เพื่อดักค่าว่าง (แนวคิดดั้งเดิมมาตั้งแต่ VB6)
txtPatientName.Text = "" & dgvData.Item(2, iRow).Value
txtAddress.Text = "" & dgvData.Item(3, iRow).Value
txtAmphur.Text = "" & dgvData.Item(4, iRow).Value
txtProvinceName.Text = "" & dgvData.Item(5, iRow).Value
txtPostCode.Text = "" & dgvData.Item(6, iRow).Value
txtTelephone.Text = "" & dgvData.Item(7, iRow).Value
'//
dtpBirthDate.Value = dgvData.Item(8, iRow).Value
lblAge.Text = CalcDate(dtpBirthDate.Value, Now)
'//
If dgvData.Item(9, iRow).Value = "ชาย" Then
rbtSexM.Checked = True
Else
rbtSexF.Checked = True
End If
cmbBlood.Text = dgvData.Item(10, iRow).Value
End SubConclusion: แอดมินก็หวังว่า คงจะเป็นแนวทางให้ได้เรียนรู้ศึกษากระบวนการขั้นตอนต่างๆ เพื่อให้ทุกๆท่านที่ได้เผลอเข้ามาอ่านกัน ได้รับความรู้ไปบ้างไม่เล็กก็น้อยก็ใหญ่ก็มากครับผม ... อนึ่ง!!! การได้เห็นโค้ด แต่ถ้าหากไม่ลองนำไปปฏิบัติจริง หรือคิดเพิ่มเติม ก็คงจะไม่มีประโยชน์อะไร ... สวัสดี
ดาวน์โหลดโค้ดต้นฉบับแบบเต็ม VB.NET (2010) ได้ที่นี่
ดีมากเลยครับ แบ่งปันความรู้...
ขออนุญาตนำไปศึกษาและประยุกต์ใช้นะครับอาจารย์
ขอบพระคุณมากๆครับ ค่อยจีบเมียใหม่ครับเฮีย
https://i.ytimg.com/vi/R9VA31rozLg/hqdefault.jpg ขอบคุณครับ
ขออนุญาตินำไปศึกษาและพัฒนานะครับ ขอบพระคุณคะ :) ขอบคุณครับ:loveliness: ขอบคุณครับ ขอบคุณครับ อาจารย์ ขอบคุณค่ะ ขอบคุรครับ
หน้า:
[1]
2