ทำความรู้จักฟังก์ชันจัดการข้อความและวันเวลาใน MS-SQL
เวลาเราทำงานกับฐานข้อมูล (ที่เก็บข้อมูลของโปรแกรม) เรามักต้องจัดการกับ T-SQL Built-in Functions (ชุดคำสั่งสำเร็จรูปที่ระบบเตรียมไว้ให้) เพื่อปรับแต่งข้อมูลให้ออกมาในรูปแบบที่ต้องการ หากเปรียบเทียบให้เห็นภาพ มันเหมือนกับการที่เราใช้ฟังก์ชันใน Excel เพื่อรวมคำหรือคำนวณวันเวลานั่นเอง การรู้คำสั่งเหล่านี้จะช่วยให้เราไม่ต้องเขียนโค้ดเองยาวๆ และลดข้อผิดพลาดในการทำงานกับข้อมูลจริงได้มาก
สำหรับมือใหม่ที่กำลังฝึก Query (คำสั่งถามข้อมูลจากฐานข้อมูล) การเข้าใจฟังก์ชันพื้นฐานเหล่านี้เปรียบเสมือนการมีเครื่องมือทุ่นแรงในกล่องเครื่องมือ ยิ่งเราใช้คล่องเท่าไหร่ เราก็ยิ่งจัดการกับข้อมูลที่ซับซ้อนได้เร็วขึ้นเท่านั้น ไม่ว่าจะเป็นการนำชื่อกับนามสกุลมารวมกัน หรือการคำนวณระยะเวลาที่ลูกค้าสมัครสมาชิกเข้ามา การเขียนโปรแกรมที่ดีเริ่มต้นจากการใช้เครื่องมือที่มีอยู่ให้เกิดประโยชน์สูงสุด
ในบทความนี้เราจะเน้นไปที่การใช้งานคำสั่งจัดการข้อความและวันเวลาที่นักพัฒนาต้องเจอแทบทุกวัน เราจะค่อยๆ ไล่ไปทีละตัวพร้อมตัวอย่างประกอบเพื่อให้เห็นภาพชัดเจนที่สุด ขอให้จำไว้ว่าการเรียนรู้คำสั่งเหล่านี้ไม่ได้มีไว้เพื่อท่องจำ แต่มีไว้เพื่อนำไปประยุกต์ใช้ในการดึงข้อมูลจาก Table (ตารางเก็บข้อมูล) ให้ตรงกับความต้องการของงานที่ได้รับมอบหมาย
การรวมข้อความด้วย CONCAT()
บ่อยครั้งที่เรามีข้อมูลแยกกันในฐานข้อมูล เช่น ชื่อช่องหนึ่งและนามสกุลอีกช่องหนึ่ง แต่เราอยากแสดงผลรวมกันเป็นชื่อเต็ม ฟังก์ชัน CONCAT() จะเข้ามาช่วยรวมข้อความหลายส่วนเข้าด้วยกันอย่างง่ายดาย โดยที่เราไม่ต้องกังวลเรื่องค่าว่างหรือ Null (ค่าที่ไม่มีข้อมูล) เพราะระบบจะจัดการให้โดยอัตโนมัติ ทำให้โค้ดของเราสะอาดและปลอดภัยมากขึ้น
ลองนึกภาพว่าเรากำลังทำระบบสมาชิกและต้องการแสดงผลชื่อผู้ใช้งานแบบเต็มรูปแบบ การใช้ CONCAT() จะช่วยให้เราเชื่อมคำได้โดยไม่ต้องกังวลเรื่องการพิมพ์เครื่องหมายบวกหรือการจัดการช่องว่างระหว่างคำให้ยุ่งยาก เป็นฟังก์ชันพื้นฐานที่โปรแกรมเมอร์ทุกคนต้องใช้ในการเตรียมข้อมูลก่อนส่งไปแสดงผลที่หน้าเว็บ
จุดที่มือใหม่มักพลาดคือการลืมเว้นวรรคระหว่างคำ ทำให้ผลลัพธ์ที่ได้ชื่อกับนามสกุลติดกันเป็นพืด วิธีแก้คือให้เพิ่มช่องว่างเข้าไปใน CONCAT() ด้วยเสมอ ดังตัวอย่างด้านล่างนี้
-- รวมชื่อและนามสกุลโดยมีช่องว่างคั่นกลาง
SELECT CONCAT(FirstName, ' ', LastName) AS FullName
FROM Employees;
อธิบายโค้ด: CONCAT คือคำสั่งรวมข้อความ บรรทัดนี้รับค่า 3 ส่วนคือชื่อ ช่องว่าง และนามสกุลมารวมกัน ส่วน AS FullName คือการตั้งชื่อคอลัมน์ใหม่ให้แสดงผลเป็นคำว่า FullName
ผลลัพธ์: จะได้ตารางที่มีคอลัมน์ชื่อ FullName แสดงผลเป็น "สมชาย ใจดี" หรือชื่ออื่นๆ ตามข้อมูลในฐานข้อมูล
การตัดและค้นหาข้อความด้วย SUBSTRING() และ CHARINDEX()
บางครั้งเราได้รับข้อมูลที่ยาวเกินไปหรือมีข้อมูลที่ไม่ต้องการติดมาด้วย เช่น รหัสพนักงานที่มีตัวอักษรนำหน้า SUBSTRING() คือฟังก์ชันที่ใช้ตัดข้อความตามตำแหน่งที่ระบุ ส่วน CHARINDEX() ใช้หาว่าตัวอักษรที่เราต้องการนั้นอยู่ที่ตำแหน่งไหนในข้อความนั้นๆ เมื่อใช้คู่กันจะช่วยให้เราดึงข้อมูลเฉพาะส่วนที่ต้องการออกมาได้แม่นยำ
เปรียบเทียบเหมือนกับการใช้กรรไกรตัดกระดาษ เราต้องรู้ก่อนว่าจะเริ่มตัดที่ตรงไหนและจะตัดยาวเท่าไหร่ CHARINDEX() ทำหน้าที่บอกตำแหน่งเริ่มต้น ส่วน SUBSTRING() ทำหน้าที่ตัดตามความยาวที่เรากำหนด การรู้จักใช้สองตัวนี้ร่วมกันจะช่วยให้เราจัดการข้อมูล String (ข้อความ) ที่ไม่เป็นระเบียบให้กลับมาสะอาดได้
ข้อควรระวังคือการนับตำแหน่งใน SUBSTRING() เริ่มต้นที่เลข 1 เสมอ หากเราใส่ตำแหน่งเริ่มต้นผิดหรือความยาวเกินกว่าที่ข้อความมีอยู่ ระบบอาจจะตัดออกมาไม่ครบหรือได้ผลลัพธ์ว่างเปล่า ควรตรวจสอบข้อมูลตัวอย่างก่อนรันคำสั่งจริงเสมอ
-- ค้นหาตำแหน่งของขีดกลางและตัดเอาเฉพาะรหัสหลังขีด
SELECT SUBSTRING('EMP-12345', CHARINDEX('-', 'EMP-12345') + 1, 5) AS EmpID;
อธิบายโค้ด: CHARINDEX('-', 'EMP-12345') จะหาตำแหน่งของเครื่องหมายขีด ซึ่งคือตำแหน่งที่ 4 จากนั้น + 1 เพื่อข้ามขีดไปเริ่มที่เลข 1 และ SUBSTRING จะตัดเอา 5 ตัวอักษรถัดไป
ผลลัพธ์: จะได้ค่า "12345" ออกมาเป็นรหัสพนักงานที่ต้องการ
การจัดการวันเวลาปัจจุบันด้วย GETDATE()
ในงานพัฒนาซอฟต์แวร์ เราต้องบันทึกเวลาที่ข้อมูลถูกสร้างหรือแก้ไขอยู่เสมอ GETDATE() เป็นฟังก์ชันที่ง่ายที่สุดในการดึงวันที่และเวลาปัจจุบันของระบบขึ้นมาใช้งาน มันเหมาะมากสำหรับการทำ Timestamp (การประทับตราเวลา) เพื่อให้รู้ว่ารายการนั้นเกิดขึ้นเมื่อไหร่
คุณอาจจะใช้คำสั่งนี้ในการตั้งค่าเริ่มต้นให้กับคอลัมน์ CreatedDate (วันที่สร้างข้อมูล) ของตารางทุกครั้งที่มีการเพิ่มข้อมูลใหม่ การมีเวลาที่แม่นยำช่วยให้เราตรวจสอบย้อนหลังได้ง่ายเมื่อเกิดบั๊กหรือปัญหาข้อมูลผิดพลาดในระบบ ทำให้การทำงานร่วมกับทีม QA (ผู้ตรวจสอบคุณภาพซอฟต์แวร์) ง่ายขึ้นมาก
สิ่งสำคัญที่ต้องรู้คือ GETDATE() จะอ้างอิงเวลาจากเซิร์ฟเวอร์ที่ฐานข้อมูลติดตั้งอยู่ หากเซิร์ฟเวอร์ตั้งค่าเวลาผิด เวลาในระบบของคุณก็จะผิดตามไปด้วย ควรตรวจสอบการตั้งค่า Timezone (เขตเวลา) ของเซิร์ฟเวอร์ให้ถูกต้องก่อนเริ่มใช้งานจริง
-- ดึงวันที่และเวลาปัจจุบันเพื่อบันทึกลงฐานข้อมูล
INSERT INTO Orders (OrderDate)
VALUES (GETDATE());
อธิบายโค้ด: บรรทัดนี้เป็นการบันทึกข้อมูลเข้าตาราง Orders โดยใช้คำสั่ง GETDATE() เพื่อเอาเวลา ณ ขณะที่กดรันคำสั่งลงไปในช่อง OrderDate โดยอัตโนมัติ
ผลลัพธ์: ข้อมูลในตารางจะมีวันที่และเวลาปัจจุบันบันทึกไว้ เช่น "2023-10-27 10:30:00.000"
การคำนวณวันเวลาด้วย DATEADD() และ DATEDIFF()
โปรแกรมเมอร์มักต้องคำนวณระยะเวลา เช่น การกำหนดวันหมดอายุของสินค้า หรือการคำนวณอายุสมาชิก DATEADD() ใช้สำหรับบวกหรือลบวันเวลาออกไปจากวันที่ปัจจุบัน ส่วน DATEDIFF() ใช้หาผลต่างระหว่างวันที่สองวันว่าห่างกันกี่วันหรือกี่เดือน
ลองจินตนาการว่าคุณต้องทำระบบแจ้งเตือนสมาชิกที่จ่ายเงินล่วงหน้า 30 วัน DATEADD() จะช่วยให้คุณบวกเวลาเพิ่มเข้าไปได้ง่ายๆ ส่วน DATEDIFF() จะช่วยคุณคำนวณว่าวันนี้ห่างจากวันหมดอายุเท่าไหร่ การเข้าใจสองคำสั่งนี้จะช่วยให้คุณจัดการเงื่อนไขทางธุรกิจที่ซับซ้อนได้อย่างมืออาชีพ
ข้อควรระวังสำหรับมือใหม่คือการกำหนดหน่วยของเวลา เช่น การระบุว่าเป็นวัน (day), เดือน (month) หรือปี (year) ใน DATEADD() หากระบุหน่วยผิด การคำนวณจะคลาดเคลื่อนไปไกลมาก ต้องหมั่นตรวจสอบหน่วยที่ใช้ให้สอดคล้องกับความต้องการของงานเสมอ
-- คำนวณวันหมดอายุโดยบวกเพิ่มไป 30 วันจากวันนี้
SELECT DATEADD(day, 30, GETDATE()) AS ExpiryDate;
-- หาจำนวนวันที่ผ่านไปตั้งแต่วันที่สมัคร
SELECT DATEDIFF(day, '2023-01-01', GETDATE()) AS DaysActive;
อธิบายโค้ด: บรรทัดแรกใช้ DATEADD บวกไป 30 วันจากวันปัจจุบัน ส่วนบรรทัดที่สองใช้ DATEDIFF หาส่วนต่างระหว่างวันที่ 1 มกราคม 2023 กับปัจจุบันโดยแสดงผลเป็นจำนวนวัน
ผลลัพธ์: บรรทัดแรกจะได้วันที่ในอีก 30 วันข้างหน้า บรรทัดที่สองจะได้ตัวเลขจำนวนวันที่ผ่านไปแล้วนับจากต้นปี
การดึงชื่อวันหรือเดือนด้วย DATENAME()
บางครั้งเราอยากแสดงผลข้อมูลให้คนอ่านเข้าใจง่ายขึ้น เช่น แทนที่จะแสดงเป็นตัวเลขเดือน เราอยากให้แสดงเป็นชื่อเดือนภาษาอังกฤษ DATENAME() จะทำหน้าที่ดึงชื่อของส่วนประกอบวันที่ออกมา เช่น ชื่อวันในสัปดาห์หรือชื่อเดือน ซึ่งช่วยให้หน้าจอแสดงผลข้อมูลดูเป็นมิตรกับผู้ใช้งานมากขึ้น
ฟังก์ชันนี้มีประโยชน์มากตอนทำรายงานสรุปข้อมูลรายเดือน หรือการแสดงผลตารางเรียนที่ต้องระบุว่าเป็นวันจันทร์หรือวันอังคาร การใช้ DATENAME() ช่วยให้เราไม่ต้องเขียนเงื่อนไข If-Else (คำสั่งถ้า...ทำอย่างนี้ ถ้าไม่ใช่...ทำอย่างนั้น) หลายๆ ชั้นเพื่อแปลงตัวเลขเป็นชื่อวัน
ข้อควรสังเกตคือ DATENAME() จะคืนค่าออกมาเป็นข้อความ (String) เสมอ ไม่ใช่ตัวเลข ดังนั้นหากคุณต้องการนำผลลัพธ์ไปคำนวณต่อ ต้องระวังเรื่อง Data Type (ประเภทของข้อมูล) ที่อาจจะไม่ตรงกัน
-- ดึงชื่อเดือนจากวันที่ปัจจุบัน
SELECT DATENAME(month, GETDATE()) AS CurrentMonth;
-- ดึงชื่อวันในสัปดาห์
SELECT DATENAME(weekday, GETDATE()) AS CurrentDay;
อธิบายโค้ด: บรรทัดแรกสั่งให้ดึงชื่อเดือนจากวันที่ปัจจุบัน บรรทัดที่สองสั่งให้ดึงชื่อวันในสัปดาห์ออกมาแสดงผล
ผลลัพธ์: จะได้ผลลัพธ์เป็นข้อความ เช่น "October" สำหรับเดือน และ "Friday" สำหรับวันในสัปดาห์
สรุป: นำไปใช้จริงให้คล่อง
การฝึกเขียน T-SQL ให้เก่งไม่ใช่เรื่องของการจำคำสั่งทั้งหมด แต่คือการรู้จักเลือกใช้เครื่องมือให้เหมาะกับงาน สมมติว่าคุณกำลังทำโปรเจกต์ Dashboard (หน้าจอแสดงผลสรุปข้อมูล) สำหรับผู้จัดการ คุณอาจต้องใช้ CONCAT() เพื่อรวมชื่อลูกค้า ใช้ DATEDIFF() เพื่อคำนวณระยะเวลาการสั่งซื้อ และใช้ DATENAME() เพื่อระบุว่ายอดขายเกิดขึ้นในเดือนไหน
คำแนะนำสำหรับมือใหม่คือ ให้ลองสร้างตารางจำลองขึ้นมาใน SQL Server Management Studio (โปรแกรมจัดการฐานข้อมูล) แล้วลองเล่นกับข้อมูลจริงๆ อย่าเพิ่งกลัวที่จะรันคำสั่งผิด เพราะการเห็นข้อผิดพลาดจะช่วยให้คุณจำได้แม่นขึ้นว่าแต่ละคำสั่งทำงานอย่างไร และที่สำคัญที่สุดคือการฝึกอ่าน Documentation (คู่มือการใช้งาน) อย่างเป็นทางการเพื่อดูรายละเอียดเพิ่มเติม
การเรียนรู้ที่จะแก้ปัญหาด้วยฟังก์ชันเหล่านี้จะทำให้คุณก้าวข้ามจากการเขียนโค้ดพื้นฐานไปสู่การเขียนโค้ดที่ทรงพลัง ขอให้สนุกกับการทดลองและอย่าลืมจดบันทึกสิ่งที่ได้เรียนรู้ในแต่ละวันลงใน Portfolio (แฟ้มสะสมผลงาน) ของคุณ เพราะสิ่งเหล่านี้จะเป็นฐานที่สำคัญเมื่อคุณต้องไปสัมภาษณ์งานจริงในอนาคต