|
ที่ต้องบอกว่าเป็นพื้นฐาน ก็เพราะว่าแอดมินจะใช้ตารางข้อมูลแบบเดี่ยวๆ โดยที่ไม่มีการสร้างความสัมพันธ์ใดๆระหว่างตารางข้อมูลเลย โดยจะเน้นแนวทางให้ศึกษาวิธีการ เพิ่มรายการใหม่ (Create) การอ่านหรือค้นคืน (Read/Retrieve) การปรับปรุง (Update) และการลบข้อมูล (Delete) ซึ่งเป็นพื้นฐานของการเขียนโปรแกรมเพื่อติดต่อกับฐานข้อมูล แต่โดยรวมๆการควบคุมโปรแกรม (Flow Control) จะเรียงลำดับขั้นตอนนี้ คือ
การค้นคืนข้อมูล จะมี 2 ลักษณะคือ
- หากไม่พบข้อข้อมูลที่ต้องการ ก็คือต้องไปทำการสร้างใหม่
- หากพบข้อมูล ก็จะมี 2 ทางเลือก คือ นำมาแก้ไข หรือ ลบข้อมูล
การออกแบบตารางข้อมูลอย่างง่าย
จบภาคทฤษฎีเล็กๆ ก็จะมาว่ากันเรื่องการปฏิบัติ โดยเน้นการลงมือทำ อันเป็นหัวใจสำคัญของการเรียนรู้ ...
โค้ดในการค้นคืนข้อมูล ...
- ' / --------------------------------------------------------------------
- ' / 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 " & _
- " [HN] " & " Like '%" & txtSearch.Text & "%'" & " OR " & _
- " [PatientName] " & " Like '%" & txtSearch.Text & "%'" & " OR " & _
- " [Address] " & " Like '%" & txtSearch.Text & "%'" & " OR " & _
- " [Amphur] " & " Like '%" & txtSearch.Text & "%'" & " OR " & _
- " [ProvinceName] " & " Like '%" & txtSearch.Text & "%'" & " OR " & _
- " [PostCode] " & " Like '%" & txtSearch.Text & "%'" & " OR " & _
- " [Telephone] " & " Like '%" & txtSearch.Text & "%'" & " OR " & _
- " [Sex] " & " Like '%" & txtSearch.Text & "%'" & " OR " & _
- " [Blood] " & " 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 Sub
คัดลอกไปที่คลิปบอร์ด RetrieveData(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 Sub
คัดลอกไปที่คลิปบอร์ด Conclusion: แอดมินก็หวังว่า คงจะเป็นแนวทางให้ได้เรียนรู้ศึกษากระบวนการขั้นตอนต่างๆ เพื่อให้ทุกๆท่านที่ได้เผลอเข้ามาอ่านกัน ได้รับความรู้ไปบ้างไม่เล็กก็น้อยก็ใหญ่ก็มากครับผม ... อนึ่ง!!! การได้เห็นโค้ด แต่ถ้าหากไม่ลองนำไปปฏิบัติจริง หรือคิดเพิ่มเติม ก็คงจะไม่มีประโยชน์อะไร ... สวัสดี
ดาวน์โหลดโค้ดต้นฉบับแบบเต็ม VB.NET (2010) ได้ที่นี่
|
ขออภัย! โพสต์นี้มีไฟล์แนบหรือรูปภาพที่ไม่ได้รับอนุญาตให้คุณเข้าถึง
คุณจำเป็นต้อง ลงชื่อเข้าใช้ เพื่อดาวน์โหลดหรือดูไฟล์แนบนี้ คุณยังไม่มีบัญชีใช่ไหม? ลงทะเบียน
x
|