ตัวอย่าง T sql ความรู้เบื้องต้นเกี่ยวกับ MS SQL Server และ T-SQL การจำกัดค่ารวมโดยใช้เงื่อนไขการจัดกลุ่ม: ส่วนคำสั่ง HAVING

อัพเดทล่าสุด: 24.06.2017

SQL Server เป็นหนึ่งในมากที่สุด ระบบยอดนิยมการจัดการฐานข้อมูล (DBMS) ในโลก DBMS นี้เหมาะสำหรับโครงการที่หลากหลาย: ตั้งแต่แอปพลิเคชันขนาดเล็กไปจนถึงโครงการขนาดใหญ่ที่มีโหลดสูง

สร้างเซิร์ฟเวอร์ SQL แล้ว โดยไมโครซอฟต์- รุ่นแรกเปิดตัวในปี 1987 ก รุ่นปัจจุบันคือเวอร์ชัน 16 ซึ่งเปิดตัวในปี 2559 และจะใช้ในคู่มือฉบับปัจจุบัน

เซิร์ฟเวอร์ SQL เป็นเวลานานเป็นระบบจัดการฐานข้อมูลสำหรับ Windows โดยเฉพาะ แต่ตั้งแต่เวอร์ชัน 16 ระบบนี้ก็มีให้ใช้งานบน Linux เช่นกัน

SQL Server โดดเด่นด้วยคุณสมบัติต่างๆ เช่น:

    ผลงาน. SQL Server ทำงานเร็วมาก

    ความน่าเชื่อถือและความปลอดภัย SQL Server มีการเข้ารหัสข้อมูล

    ความเรียบง่าย DBMS นี้ค่อนข้างง่ายต่อการทำงานและบริหารจัดการ

สิ่งสำคัญใน MS SQL Server เช่นเดียวกับใน DBMS อื่นๆ คือฐานข้อมูล ฐานข้อมูลเป็นที่เก็บข้อมูลที่จัดระเบียบในลักษณะเฉพาะ บ่อยครั้งที่ฐานข้อมูลแสดงไฟล์ในฮาร์ดไดรฟ์ทางกายภาพ แม้ว่าจะไม่จำเป็นต้องโต้ตอบก็ตาม ในการจัดเก็บและจัดการฐานข้อมูล จะใช้ระบบการจัดการฐานข้อมูลหรือ DBMS และเพียงแค่ MS SQL Server ก็เป็นหนึ่งใน DBMS ดังกล่าว

ในการจัดระเบียบฐานข้อมูล MS SQL Server จะใช้ โมเดลเชิงสัมพันธ์- โมเดลฐานข้อมูลนี้ได้รับการพัฒนาในปี 1970 โดย Edgar Codd และในปัจจุบันนี้ได้กลายเป็นมาตรฐานในการจัดฐานข้อมูลอย่างแท้จริง

โมเดลเชิงสัมพันธ์เกี่ยวข้องกับการจัดเก็บข้อมูลในรูปแบบของตาราง ซึ่งแต่ละอันประกอบด้วยแถวและคอลัมน์ ร้านค้าแต่ละบรรทัด แยกวัตถุและคอลัมน์ต่างๆ มีคุณลักษณะของวัตถุนี้

คีย์หลักใช้เพื่อระบุแต่ละแถวภายในตาราง คีย์หลักสามารถมีได้ตั้งแต่หนึ่งคอลัมน์ขึ้นไป การใช้คีย์หลักที่เราสามารถอ้างอิงได้ สตริงเฉพาะในตาราง ดังนั้น สองแถวจึงไม่สามารถมีคีย์หลักเดียวกันได้

เมื่อใช้คีย์ ตารางหนึ่งสามารถเชื่อมโยงกับอีกตารางหนึ่งได้ กล่าวคือ สามารถจัดระเบียบความสัมพันธ์ระหว่างสองตารางได้ และตัวตารางเองก็สามารถแสดงเป็นความสัมพันธ์ได้

ในการโต้ตอบกับฐานข้อมูล จะใช้ภาษา SQL (Structured Query Language) ไคลเอ็นต์ (เช่น โปรแกรมภายนอก) ส่งคำขอไปที่ ภาษา SQLผ่าน API พิเศษ DBMS ตีความและดำเนินการตามคำขออย่างเหมาะสม จากนั้นจึงส่งผลการดำเนินการไปยังไคลเอนต์

SQL ได้รับการพัฒนาโดย IBM สำหรับระบบฐานข้อมูลชื่อ System/R ในเวลาเดียวกัน ภาษานั้นถูกเรียกว่า SEQUEL (Structured English Query Language) แม้ว่าทั้งฐานข้อมูลและภาษาจะไม่ได้รับการเผยแพร่อย่างเป็นทางการในเวลาต่อมา แต่ตามธรรมเนียมแล้ว คำว่า SQL มักถูกออกเสียงว่าเป็น "ภาคต่อ"

ในปี 1979 บริษัท Relational Software Inc. พัฒนาระบบการจัดการฐานข้อมูลระบบแรกที่เรียกว่า Oracle ซึ่งใช้ภาษา SQL เนื่องจากความสำเร็จของผลิตภัณฑ์นี้ บริษัทจึงเปลี่ยนชื่อเป็น Oracle

ต่อมาระบบฐานข้อมูลอื่นๆ ที่ใช้ SQL ก็เริ่มปรากฏขึ้น ด้วยเหตุนี้ ในปี 1989 สถาบันมาตรฐานแห่งชาติอเมริกัน (ANSI) จึงได้จัดทำภาษาและเผยแพร่มาตรฐานฉบับแรก หลังจากนั้นมาตรฐานจะได้รับการปรับปรุงและเสริมเป็นระยะ การอัปเดตครั้งล่าสุดเกิดขึ้นในปี 2554 แต่ถึงแม้จะมีมาตรฐาน แต่ผู้ผลิต DBMS ก็มักจะใช้มาตรฐานของตนเอง การใช้งานของตัวเองภาษา SQL ซึ่งมีความแตกต่างกันเล็กน้อย

ภาษา SQL มีสองประเภท: PL-SQL และ T-SQL PL-SQL ใช้ใน DBMS เช่น Oracle และ MySQL T-SQL (Transact-SQL) ใช้ใน SQL Server อันที่จริง นี่คือสาเหตุที่ T-SQL จะได้รับการพิจารณาภายในคำแนะนำปัจจุบัน

ขึ้นอยู่กับงานที่คำสั่ง T-SQL ดำเนินการ อาจเป็นประเภทใดประเภทหนึ่งต่อไปนี้:

    DDL (ภาษาคำจำกัดความข้อมูล) ประเภทนี้ประกอบด้วยคำสั่งต่างๆ ที่สร้างฐานข้อมูล ตาราง ดัชนี ขั้นตอนการจัดเก็บ ฯลฯ โดยทั่วไปข้อมูลจะถูกกำหนด

    โดยเฉพาะเราสามารถจำแนกคำสั่งต่อไปนี้เป็นประเภทนี้:

    • CREATE : สร้างวัตถุฐานข้อมูล (ฐานข้อมูล ตาราง ดัชนี ฯลฯ)

      ALTER: ปรับเปลี่ยนวัตถุฐานข้อมูล

      DROP: ลบวัตถุฐานข้อมูล

      TRUNCATE: ลบข้อมูลทั้งหมดออกจากตาราง

    DML (ภาษาการจัดการข้อมูล) ประเภทนี้รวมถึงคำสั่งสำหรับการเลือกข้อมูล อัปเดต เพิ่ม ลบ - โดยทั่วไปแล้ว คำสั่งทั้งหมดที่เราสามารถจัดการข้อมูลได้

    คำสั่งต่อไปนี้เป็นของประเภทนี้:

    • SELECT: ดึงข้อมูลจากฐานข้อมูล

      UPDATE: อัปเดตข้อมูล

      INSERT: เพิ่มข้อมูลใหม่

      DELETE: ลบข้อมูล

    DCL (ภาษาควบคุมข้อมูล / ภาษาควบคุมการเข้าถึงข้อมูล) ประเภทนี้รวมถึงคำสั่งที่จัดการสิทธิ์การเข้าถึงข้อมูล โดยเฉพาะคำสั่งต่อไปนี้:

    • GRANT: ให้สิทธิ์ในการเข้าถึงข้อมูล

      REVOKE: เพิกถอนสิทธิ์การเข้าถึงข้อมูล

ในส่วนแรก เราได้สัมผัสภาษา DML เพียงเล็กน้อยแล้ว โดยใช้คำสั่งเกือบทั้งหมด ยกเว้นคำสั่ง MERGE

ฉันจะพูดถึง DML ตามลำดับของฉันเองซึ่งพัฒนาจากประสบการณ์ส่วนตัว ระหว่างทาง ฉันจะพยายามพูดถึงสถานที่ที่ "ลื่น" ที่ควรค่าแก่การมุ่งเน้น สถานที่ "ลื่น" เหล่านี้มีความคล้ายคลึงกันในภาษาท้องถิ่นหลายภาษาของ SQL

เพราะ หนังสือเรียนนี้มีไว้สำหรับผู้อ่านที่หลากหลาย (ไม่เพียง แต่โปรแกรมเมอร์เท่านั้น) ดังนั้นบางครั้งคำอธิบายก็เหมาะสมเช่น ยาวและน่าเบื่อ นี่คือวิสัยทัศน์ของฉันเกี่ยวกับเนื้อหา ซึ่งส่วนใหญ่ได้รับในทางปฏิบัติอันเป็นผลมาจากกิจกรรมทางวิชาชีพ

เป้าหมายหลักของบทช่วยสอนนี้ทีละขั้นตอนคือการพัฒนาความเข้าใจที่สมบูรณ์ในสาระสำคัญของภาษา SQL และสอนวิธีใช้โครงสร้างอย่างถูกต้อง ผู้เชี่ยวชาญในสาขานี้อาจสนใจเลื่อนดูด้วย วัสดุนี้บางทีพวกเขาอาจจะสามารถเรียนรู้สิ่งใหม่ๆ สำหรับตัวเอง หรือบางทีมันอาจจะมีประโยชน์ในการอ่านเพื่อฟื้นฟูความทรงจำของพวกเขา ฉันหวังว่าทุกคนจะพบว่ามันน่าสนใจ

เพราะ DML ในภาษาถิ่นฐานข้อมูล MS SQL มีความสัมพันธ์อย่างใกล้ชิดกับไวยากรณ์ของโครงสร้าง SELECT ดังนั้นฉันจะเริ่มพูดถึง DML ด้วย ในความคิดของฉัน โครงสร้าง SELECT เป็นโครงสร้างที่สำคัญที่สุดในภาษา DML เพราะ เนื่องจากข้อมูลหรือชิ้นส่วนข้อมูลที่จำเป็นจึงถูกดึงมาจากฐานข้อมูล

ภาษา DML มีโครงสร้างดังต่อไปนี้:

  • เลือก – การเลือกข้อมูล
  • INSERT – การแทรกข้อมูลใหม่
  • อัปเดต – อัปเดตข้อมูล
  • DELETE – การลบข้อมูล
  • MERGE – การรวมข้อมูล

ในส่วนนี้ เราจะดูเฉพาะไวยากรณ์พื้นฐานของคำสั่ง SELECT ซึ่งมีลักษณะดังนี้:

เลือก column_list หรือ * จากแหล่งที่มา โดยที่ตัวกรอง ORDER BY sort_expression
เรื่อง คำสั่งเลือกกว้างขวางมาก ดังนั้นในส่วนนี้ผมจะเน้นเฉพาะการออกแบบขั้นพื้นฐานเท่านั้น ฉันเชื่อว่าหากไม่รู้พื้นฐานดีพอ คุณจะไม่สามารถเริ่มศึกษาโครงสร้างที่ซับซ้อนกว่านี้ได้ เพราะ... จากนั้นทุกอย่างจะหมุนรอบการออกแบบพื้นฐานนี้ (แบบสอบถามย่อย การรวม ฯลฯ)

นอกจากนี้ ในส่วนนี้ ฉันจะพูดถึงข้อเสนอ TOP ด้วย ฉันไม่ได้ตั้งใจระบุประโยคนี้ในรูปแบบพื้นฐานเพราะ... มันถูกนำไปใช้แตกต่างกันในภาษา SQL ที่ต่างกัน

หากภาษา DDL มีความคงที่มากกว่านี้ เช่น ด้วยความช่วยเหลือ โครงสร้างที่เข้มงวดจะถูกสร้างขึ้น (ตาราง ความสัมพันธ์ ฯลฯ) จากนั้นภาษา DML มีลักษณะเป็นไดนามิก ที่นี่คุณจะได้รับผลลัพธ์ที่ถูกต้องในรูปแบบต่างๆ

การฝึกอบรมจะดำเนินต่อไปในโหมดทีละขั้นตอน เช่น เมื่ออ่านคุณควรพยายามทำตัวอย่างด้วยมือของคุณเองทันที จากนั้นคุณวิเคราะห์ผลลัพธ์ที่ได้รับและพยายามทำความเข้าใจอย่างสังหรณ์ใจ หากมีบางสิ่งยังไม่ชัดเจน เช่น ความหมายของฟังก์ชัน ให้ขอความช่วยเหลือจากอินเทอร์เน็ต

ตัวอย่างจะแสดงอยู่ในฐานข้อมูล Test ซึ่งสร้างขึ้นโดยใช้ DDL+DML ในส่วนแรก

สำหรับผู้ที่ไม่ได้สร้างฐานข้อมูลในส่วนแรก (เนื่องจากไม่ใช่ทุกคนอาจสนใจภาษา DDL) จึงสามารถใช้สคริปต์ต่อไปนี้:

ทดสอบสคริปต์สร้างฐานข้อมูล

การสร้างฐานข้อมูล CREATE DATABASE Test GO - ทำให้ฐานข้อมูล Test ปัจจุบัน USE Test GO - สร้างตารางอ้างอิง CREATE TABLE Positions(ID int IDENTITY(1,1) NOT NULL CONSTRAINT PK_Positions คีย์หลัก, ชื่อ nvarchar(30) ไม่เป็นโมฆะ) สร้างแผนกตาราง (ID int IDENTITY(1,1) ไม่เป็นโมฆะข้อจำกัด PK_แผนกคีย์หลัก ชื่อ nvarchar(30) ไม่เป็นโมฆะ) GO -- กรอกตารางอ้างอิงด้วยข้อมูล SET IDENTITY_INSERT ตำแหน่งบน INSERT ตำแหน่ง ( ID,ชื่อ)ค่า (1,N"นักบัญชี"), (2,N"ผู้อำนวยการ"), (3,N"โปรแกรมเมอร์"), (4,N"โปรแกรมเมอร์อาวุโส") SET IDENTITY_INSERT ตำแหน่ง OFF GO SET IDENTITY_INSERT แผนก ON INSERT แผนก(ID,ชื่อ)ค่า (1,N"การบริหาร"), (2,N"การบัญชี"), (3,N"IT") SET IDENTITY_INSERT แผนก OFF GO -- สร้างตารางที่มีพนักงาน สร้างตาราง พนักงาน (ID int ไม่เป็น NULL, ชื่อ nvarchar (30), วันเกิด, อีเมล nvarchar (30), PositionID int, DepartmentID int, วันที่จ้างงาน ไม่ใช่ NULL CONSTRAINT DF_Employees_HireDate DEFAULT SYSDATETIME(), ManagerID int, CONSTRAINT PK_Employees PRIMARY KEY (ID), CONSTRAINT FK_Employees_DepartmentID คีย์ต่างประเทศ (ID แผนก) การอ้างอิงแผนก (ID), CONSTRAINT FK_Employees_PositionID คีย์ต่างประเทศ (ID ตำแหน่ง) ตำแหน่งอ้างอิง (ID), CONSTRAINT FK_Employees_ManagerID คีย์ต่างประเทศ (ID ผู้จัดการ) การอ้างอิงพนักงาน (ID), CONSTRAINT s_Email UNIQUE (อีเมล), ข้อ จำกัด CK_Emp loyees_ID CHECK (ID ระหว่าง 1,000 ถึง 1999), INDEX IDX_Employees_Name(ชื่อ)) GO -- กรอกข้อมูลด้วย INSERT Employees (ID,Name,Birthday,Email,PositionID,DepartmentID,ManagerID)VALUES (1000,N"Ivanov I.I.","19550219 , " [ป้องกันอีเมล]",2,1,NULL), (1001,N"เปตรอฟ พี.พี.","19831203"," [ป้องกันอีเมล]",3,3,1003), (1002,N"Sidorov S.S.","19760607"," [ป้องกันอีเมล]",1,2,1000), (1003,น"อันดรีฟ เอ.เอ.","19820417"," [ป้องกันอีเมล]",4,3,1000)

เพียงเท่านี้เราก็พร้อมที่จะเริ่มเรียนรู้ภาษา DML แล้ว

SELECT – ตัวดำเนินการเลือกข้อมูล

ก่อนอื่น สำหรับตัวแก้ไขแบบสอบถามที่ใช้งานอยู่ ให้ทำการทดสอบฐานข้อมูลปัจจุบันโดยเลือกฐานข้อมูลในรายการแบบเลื่อนลงหรือใช้คำสั่ง "USE Test"

เริ่มจากรูปแบบพื้นฐานที่สุดของ SELECT:

เลือก * จากพนักงาน
ในแบบสอบถามนี้ เราขอให้ส่งคืนคอลัมน์ทั้งหมด (ระบุด้วย "*") จากตารางพนักงาน - คุณสามารถอ่านได้ว่า "เลือก all_fields จากตารางพนักงาน" หากมีดัชนีแบบคลัสเตอร์ ข้อมูลที่ส่งคืนมักจะถูกจัดเรียงตามดัชนีนั้น ในกรณีนี้ตามคอลัมน์ ID (แต่สิ่งนี้ไม่สำคัญเนื่องจากในกรณีส่วนใหญ่เราจะระบุการเรียงลำดับอย่างชัดเจนโดยใช้ ORDER BY ...):

บัตรประจำตัวประชาชน ชื่อ วันเกิด อีเมล รหัสตำแหน่ง รหัสแผนก HireDate รหัสผู้จัดการ
1000 อีวานอฟ ไอ.ไอ. 1955-02-19 [ป้องกันอีเมล] 2 1 2015-04-08 โมฆะ
1001 เปตรอฟ พี.พี. 1983-12-03 [ป้องกันอีเมล] 3 3 2015-04-08 1003
1002 ซิโดรอฟ เอส.เอส. 1976-06-07 [ป้องกันอีเมล] 1 2 2015-04-08 1000
1003 Andreev A.A. 1982-04-17 [ป้องกันอีเมล] 4 3 2015-04-08 1000

โดยทั่วไปควรบอกว่าในภาษา MS SQL รูปแบบที่ง่ายที่สุดคือ เลือกแบบสอบถามอาจไม่มีบล็อก FROM ซึ่งในกรณีนี้คุณสามารถใช้เพื่อรับค่าบางอย่างได้:

SELECT 5550/100*15, SYSDATETIME() - รับวันที่ของระบบฐานข้อมูล SIN(0)+COS(0)

(ไม่มีชื่อคอลัมน์) (ไม่มีชื่อคอลัมน์) (ไม่มีชื่อคอลัมน์)
825 2015-04-11 12:12:36.0406743 1

โปรดทราบว่านิพจน์ (5550/100*15) ให้ผลลัพธ์ 825 แม้ว่าเราจะคำนวณด้วยเครื่องคิดเลข ค่าก็จะเป็น (832.5) ผลลัพธ์ที่ได้คือ 825 เนื่องจากในนิพจน์ของเราตัวเลขทั้งหมดเป็นจำนวนเต็ม ดังนั้นผลลัพธ์จึงเป็นจำนวนเต็ม เช่น (5550/100) ให้ 55 ไม่ใช่ (55.5)

โปรดจำไว้ว่าตรรกะต่อไปนี้ใช้งานได้ใน MS SQL:

  • จำนวนเต็ม / จำนวนเต็ม = จำนวนเต็ม (เช่น ในกรณีนี้เกิดการหารจำนวนเต็ม)
  • จริง / จำนวนเต็ม = จริง
  • จำนวนเต็ม / จริง = จริง
เหล่านั้น. ผลลัพธ์จะถูกแปลงเป็น ประเภทที่ใหญ่กว่าดังนั้นใน 2 กรณีสุดท้าย เราจะได้จำนวนจริง (คิดเหมือนในคณิตศาสตร์ ช่วงของจำนวนจริงมากกว่าช่วงของจำนวนเต็ม ดังนั้นผลลัพธ์จะถูกแปลงเป็นค่านั้น):

เลือก 123/10, -- 12 123./10, -- 12.3 123/10 --12.3
ในที่นี้ (123.) = (123.0) ในกรณีนี้ 0 สามารถละทิ้งได้ และเหลือเพียงจุดเท่านั้น

กับคนอื่นๆ การดำเนินการทางคณิตศาสตร์ใช้ตรรกะเดียวกัน เพียงแต่ว่าในกรณีของการแบ่งความแตกต่างเล็กน้อยนี้มีความเกี่ยวข้องมากกว่า

ดังนั้นควรคำนึงถึงชนิดข้อมูลของคอลัมน์ตัวเลขด้วย หากเป็นจำนวนเต็มและคุณต้องการผลลัพธ์ที่แท้จริง ให้ใช้การแปลงหรือใส่จุดหลังตัวเลขที่ระบุเป็นค่าคงที่ (123.)

คุณสามารถใช้ฟังก์ชัน CAST หรือ CONVERT เพื่อแปลงฟิลด์ได้ ตัวอย่างเช่น ลองใช้ช่อง ID ซึ่งเป็นประเภท int:

SELECT ID, ID/100, -- การหารจำนวนเต็มจะเกิดขึ้นที่นี่ CAST(ID AS float)/100 -- ใช้ฟังก์ชัน CAST เพื่อแปลงเป็นประเภท float CONVERT(float,ID)/100 -- ใช้ฟังก์ชัน CONVERT เพื่อแปลงเป็นประเภท float ID/100 -- ใช้การแปลงโดยระบุว่าตัวส่วนเป็นจำนวนจริงจากพนักงาน

บัตรประจำตัวประชาชน (ไม่มีชื่อคอลัมน์) (ไม่มีชื่อคอลัมน์) (ไม่มีชื่อคอลัมน์) (ไม่มีชื่อคอลัมน์)
1000 10 10 10 10.000000
1001 10 10.01 10.01 10.010000
1002 10 10.02 10.02 10.020000
1003 10 10.03 10.03 10.030000

เพียงแค่บันทึกในฐานข้อมูล ORACLE ไม่สามารถยอมรับไวยากรณ์ที่ไม่มีบล็อก FROM ได้ เพื่อจุดประสงค์นี้ จะใช้ตารางระบบ DUAL ซึ่งมีหนึ่งบรรทัด:

SELECT 5550/100*15, -- และใน ORACLE ผลลัพธ์จะเท่ากับ 832.5 sysdate, sin(0)+cos(0) FROM DUAL


บันทึก.ชื่อตารางใน RDB หลายรายการอาจนำหน้าด้วยชื่อสคีมา:

SELECT * FROM dbo.Employees -- dbo – ชื่อสคีมา

สคีมาเป็นหน่วยทางลอจิคัลของฐานข้อมูลซึ่งมีชื่อเป็นของตัวเอง และช่วยให้คุณสามารถจัดกลุ่มอ็อบเจ็กต์ฐานข้อมูล เช่น ตาราง มุมมอง ฯลฯ ภายในตัวมันเองได้

คำจำกัดความของสคีมาในฐานข้อมูลที่แตกต่างกันอาจแตกต่างกัน ในบางกรณี สคีมาจะเกี่ยวข้องโดยตรงกับผู้ใช้ฐานข้อมูล เช่น ในกรณีนี้ เราสามารถพูดได้ว่าสคีมาและผู้ใช้เป็นคำพ้องความหมาย และวัตถุทั้งหมดที่สร้างขึ้นในสคีมานั้นเป็นวัตถุของผู้ใช้รายนี้ ใน MS SQL สคีมาเป็นหน่วยลอจิคัลอิสระที่สามารถสร้างได้ด้วยตัวเอง (ดู CREATE SCHEMA)

ตามค่าเริ่มต้น สคีมาหนึ่งจะถูกสร้างขึ้นในฐานข้อมูล MS SQL ด้วยชื่อ dbo (เจ้าของฐานข้อมูล) และออบเจ็กต์ที่สร้างขึ้นทั้งหมดจะถูกสร้างขึ้นตามค่าเริ่มต้นในสคีมานี้ ดังนั้น หากเราระบุชื่อของตารางในการสืบค้น ตารางนั้นก็จะถูกค้นหาใน dbo schema ของฐานข้อมูลปัจจุบัน หากเราต้องการสร้างวัตถุในสคีมาเฉพาะ เราจะต้องเติมชื่อวัตถุด้วยชื่อสคีมา เช่น “CREATE TABLE schema_name.table_name(...)”

ในกรณีของ MS SQL ชื่อสคีมาอาจนำหน้าด้วยชื่อของฐานข้อมูลที่มีสคีมาอยู่:

เลือก * จาก Test.dbo.Employees --database_name.schema_name.table
คำชี้แจงนี้จะมีประโยชน์ ตัวอย่างเช่น หาก:

  • ในคำขอเดียว เราเข้าถึงออบเจ็กต์ที่อยู่ในสคีมาหรือฐานข้อมูลที่แตกต่างกัน
  • คุณต้องถ่ายโอนข้อมูลจากสคีมาหรือฐานข้อมูลหนึ่งไปยังอีกสคีมาหรือฐานข้อมูลอื่น
  • เมื่ออยู่ในฐานข้อมูลเดียว คุณจะต้องขอข้อมูลจากฐานข้อมูลอื่น
  • ฯลฯ
สคีมาเป็นเครื่องมือที่สะดวกมากซึ่งมีประโยชน์ในการพัฒนาสถาปัตยกรรมฐานข้อมูล โดยเฉพาะฐานข้อมูลขนาดใหญ่

นอกจากนี้ อย่าลืมว่าในข้อความคำขอ เราสามารถใช้ความคิดเห็นทั้งบรรทัดเดียว “-- ... ” และความคิดเห็นหลายบรรทัด “/* ... */” หากคำขอมีขนาดใหญ่และซับซ้อน ความคิดเห็นสามารถช่วยให้คุณหรือบุคคลอื่นจดจำหรือเข้าใจโครงสร้างของคำขอได้อย่างมาก

หากมีคอลัมน์จำนวนมากในตาราง และโดยเฉพาะอย่างยิ่งหากยังมีแถวจำนวนมากในตาราง บวกกับหากเรากำลังทำการสืบค้นไปยังฐานข้อมูลผ่านเครือข่าย ก็ควรจะเลือกด้วยรายการโดยตรงของ ฟิลด์ที่คุณต้องการ คั่นด้วยเครื่องหมายจุลภาค:

เลือก ID ชื่อจากพนักงาน

เหล่านั้น. ที่นี่เราบอกว่าเราเพียงต้องส่งคืนฟิลด์ ID และชื่อจากตารางเท่านั้น ผลลัพธ์จะเป็นดังนี้ (โดยวิธีการเพิ่มประสิทธิภาพที่นี่ตัดสินใจใช้ดัชนีที่สร้างโดยฟิลด์ชื่อ):

บัตรประจำตัวประชาชน ชื่อ
1003 Andreev A.A.
1000 อีวานอฟ ไอ.ไอ.
1001 เปตรอฟ พี.พี.
1002 ซิโดรอฟ เอส.เอส.

เพียงแค่บันทึกบางครั้งการดูวิธีการดึงข้อมูลอาจมีประโยชน์ เช่น การค้นหาว่ามีการใช้ดัชนีใดบ้าง ซึ่งสามารถทำได้โดยคลิกปุ่ม “แสดงแผนการดำเนินการโดยประมาณ” หรือตั้งค่า “รวมแผนการดำเนินการจริง” (ในกรณีนี้เราจะสามารถดูได้ แผนที่แท้จริงตามลำดับ หลังจากดำเนินการตามคำขอแล้วเท่านั้น):

การวิเคราะห์แผนการดำเนินการมีประโยชน์มากเมื่อปรับแบบสอบถามให้เหมาะสม ช่วยให้คุณค้นหาดัชนีที่ขาดหายไปหรือดัชนีใดที่ไม่ได้ใช้เลยและสามารถลบออกได้

หากคุณเพิ่งเริ่มเรียนรู้ DML ตอนนี้สิ่งนี้ไม่สำคัญสำหรับคุณ เพียงจดไว้และคุณสามารถลืมมันได้อย่างปลอดภัย (บางทีคุณอาจไม่ต้องการมันเลย) - เป้าหมายเริ่มแรกของเราคือการเรียนรู้พื้นฐานของภาษา DML และ เรียนรู้วิธีใช้อย่างถูกต้อง และการเพิ่มประสิทธิภาพเป็นศิลปะที่แยกจากกันอยู่แล้ว บางครั้ง สิ่งที่สำคัญกว่านั้นคือคุณเพียงแค่มีคำถามที่เขียนอย่างถูกต้องซึ่งส่งคืนผลลัพธ์ที่ถูกต้องจากมุมมองของหัวเรื่อง และบุคคลแต่ละคนก็ได้ปรับให้เหมาะสมแล้ว ขั้นแรก คุณต้องเรียนรู้วิธีเขียนแบบสอบถามอย่างถูกต้อง โดยใช้วิธีใดก็ได้เพื่อให้บรรลุเป้าหมาย เป้าหมายหลักที่คุณต้องบรรลุในตอนนี้คือเพื่อให้ข้อความค้นหาของคุณแสดงผลลัพธ์ที่ถูกต้อง

การตั้งค่านามแฝงของตาราง

เมื่อแสดงรายการคอลัมน์ สามารถนำหน้าด้วยชื่อของตารางที่อยู่ในบล็อก FROM:

เลือก Employees.ID, Employees.Name จากพนักงาน

แต่ไวยากรณ์นี้มักจะใช้งานไม่สะดวกเพราะว่า ชื่อตารางอาจยาวได้ เพื่อวัตถุประสงค์เหล่านี้เพิ่มเติม ชื่อสั้น ๆ– นามแฝง:

เลือก emp.ID,emp.Name จากพนักงาน AS emp
หรือ

SELECT emp.ID,emp.Name จาก Employees emp -- สามารถละคีย์เวิร์ด AS ได้ (ฉันชอบตัวเลือกนี้มากกว่า)

emp ในที่นี้คือนามแฝงสำหรับตารางพนักงานที่สามารถใช้ในบริบทของคำสั่ง SELECT นี้ เหล่านั้น. เราสามารถพูดได้ว่าในบริบทของคำสั่ง SELECT นี้ เราจะตั้งชื่อใหม่ให้กับตาราง

แน่นอน ในกรณีนี้ ผลลัพธ์การสืบค้นจะเหมือนกับ "SELECT ID,Name FROM Employees" ทุกประการ เหตุใดจึงจำเป็นจะชัดเจนในภายหลัง (ไม่แม้แต่ในส่วนนี้) สำหรับตอนนี้เราเพียงจำไว้ว่าชื่อคอลัมน์สามารถนำหน้า (ชี้แจง) ได้โดยตรงด้วยชื่อตารางหรือใช้นามแฝง ที่นี่คุณสามารถใช้หนึ่งในสองสิ่งนั่นคือ หากคุณตั้งชื่อแทน คุณจะต้องใช้ชื่อนั้น แต่คุณไม่สามารถใช้ชื่อตารางได้อีกต่อไป

เพียงแค่บันทึกใน ORACLE อนุญาตเฉพาะตัวเลือกในการระบุนามแฝงของตารางโดยไม่มีคีย์เวิร์ด AS เท่านั้น

DISTINCT – ละทิ้งแถวที่ซ้ำกัน

คำสำคัญ DISTINCT ใช้เพื่อละทิ้งแถวที่ซ้ำกันออกจากผลลัพธ์แบบสอบถาม โดยคร่าวๆ ลองจินตนาการว่าดำเนินการค้นหาโดยไม่มีตัวเลือก DISTINCT ก่อน จากนั้นจึงละทิ้งรายการที่ซ้ำกันทั้งหมดออกจากผลลัพธ์ ให้เราสาธิตสิ่งนี้เพื่อความชัดเจนยิ่งขึ้นโดยใช้ตัวอย่าง:

มาสร้างตารางชั่วคราวสำหรับการสาธิต สร้างตาราง #Trash(ID int NOT NULL PRIMARY KEY, Col1 varchar(10), Col2 varchar(10), Col3 varchar(10)) - fill ตารางนี้ขยะทุกประเภท INSERT #Trash(ID,Col1,Col2,Col3)VALUES (1,"A", "A", "A"), (2,"A", "B", "C"), ( 3, "C", "A", "B"), (4, "A", "A", "B"), (5, "B", "B", "B"), (6, "ก", "ก", "ข", (7, "ก", "ก", "ก"), (8, "ค", "ก", "ข"), (9, "ค , "A", "B"), (10, "A", "A", "B"), (11, "A", NULL, "B"), (12, "A", NULL, "B ") -- มาดูกันว่าแบบสอบถามส่งคืนอะไรโดยไม่มีตัวเลือก DISTINCT SELECT Col1,Col2,Col3 FROM #Trash -- มาดูกันว่าแบบสอบถามส่งคืนอะไรด้วยตัวเลือก DISTINCT SELECT DISTINCT Col1,Col2,Col3 FROM #Trash -- ลบ ตารางชั่วคราว DROP TABLE #Trash

สายตาจะมีลักษณะเช่นนี้ (รายการที่ซ้ำกันทั้งหมดจะถูกทำเครื่องหมายด้วยสีเดียวกัน):

ตอนนี้เรามาดูกันว่าสิ่งนี้สามารถนำไปใช้ได้ที่ไหน โดยใช้ตัวอย่างที่เป็นประโยชน์มากขึ้น - เราจะส่งคืนเฉพาะตัวระบุแผนกที่ไม่ซ้ำกันจากตารางพนักงาน (เช่น เราจะค้นหา ID ของแผนกที่พนักงานลงทะเบียนไว้):

เลือก DepartmentID ที่แตกต่างจากพนักงาน

ที่นี่เรามี 4 บรรทัดเพราะ... ไม่มีชุดค่าผสมที่ซ้ำกัน (DepartmentID, PositionID) ในตารางของเรา

กลับมาที่ DDL กันสักครู่

เนื่องจากเราเริ่มจะหมดข้อมูลสำหรับตัวอย่างการสาธิต และเราต้องการพูดคุยให้ครอบคลุมและชัดเจนยิ่งขึ้น เรามาขยายตาราง Employess ของเรากันสักหน่อย นอกจากนี้ จำ DDL เล็กๆ น้อยๆ ดังที่พวกเขาพูดว่า “การทำซ้ำเป็นบ่อเกิดของการเรียนรู้” และอีกอย่าง เรามากระโดดไปข้างหน้าอีกครั้งและใช้คำสั่ง UPDATE:

เราสร้างคอลัมน์ใหม่ ALTER TABLE Employees ADD LastName nvarchar(30), -- นามสกุล FirstName nvarchar(30), -- ชื่อจริง MiddleName nvarchar(30), -- ชื่อกลาง เงินเดือนลอยตัว, -- และเงินเดือนแน่นอนในบางหน่วย BonusPercent float -- เปอร์เซ็นต์สำหรับการคำนวณโบนัสจากเงินเดือน GO -- กรอกข้อมูล (ข้อมูลบางส่วนถูกละเว้นโดยเจตนา) อัปเดตพนักงาน SET LastName=N"Ivanov", FirstName=N"Ivan", MiddleName=N"Ivanovich", เงินเดือน=5,000 เปอร์เซ็นต์โบนัส= 50 โดยที่ ID=1,000 -- Ivanov I.I. อัพเดท พนักงาน SET LastName=N"Petrov",FirstName=N"Petr",MiddleName=N"Petrovich", เงินเดือน=1500,BonusPercent= 15 WHERE ID=1001 -- Petrov P.P. อัปเดตพนักงาน SET LastName=N"Sidor",FirstName=N"Sidor",MiddleName=NULL, เงินเดือน=2500,BonusPercent=NULL WHERE ID=1002 -- Sidorov S.S. อัปเดตพนักงาน SET LastName=N"Andreev",FirstName=N"Andrey",MiddleName=NULL, เงินเดือน=2000,BonusPercent= 30 WHERE ID=1003 -- Andreev A.A.

ตรวจสอบให้แน่ใจว่าข้อมูลได้รับการอัปเดตเรียบร้อยแล้ว:

เลือก * จากพนักงาน

บัตรประจำตัวประชาชน ชื่อ นามสกุล ชื่อ ชื่อกลาง เงินเดือน โบนัสเปอร์เซ็นต์
1000 อีวานอฟ ไอ.ไอ. อีวานอฟ อีวาน อิวาโนวิช 5000 50
1001 เปตรอฟ พี.พี. เปตรอฟ ปีเตอร์ เปโตรวิช 1500 15
1002 ซิโดรอฟ เอส.เอส. ซิโดรอฟ ซีดอร์ โมฆะ 2500 โมฆะ
1003 Andreev A.A. อันดรีฟ อันเดรย์ โมฆะ 2000 30

การตั้งค่านามแฝงสำหรับคอลัมน์แบบสอบถาม

ฉันคิดว่าการแสดงที่นี่ง่ายกว่าการเขียน:

SELECT -- ตั้งชื่อให้กับคอลัมน์จากการคำนวณ LastName+" "+FirstName+" "+MiddleName AS Full Name, -- การใช้งาน เครื่องหมายคำพูดคู่, เพราะ มีการใช้ช่องว่าง HireDate AS "วันที่รับ" -- การใช้วงเล็บเหลี่ยม เพราะ ใช้ช่องว่างวันเกิด AS [วันเกิด] -- คำว่า AS ไม่จำเป็น เงินเดือน ZP จากพนักงาน

ชื่อเต็ม วันที่รับสมัคร วันเกิด ซีพี
อีวานอฟ อีวาน อิวาโนวิช 2015-04-08 1955-02-19 5000
เปตรอฟ เปตรอฟ เปโตรวิช 2015-04-08 1983-12-03 1500
โมฆะ 2015-04-08 1976-06-07 2500
โมฆะ 2015-04-08 1982-04-17 2000

ดังที่เราเห็น นามแฝงของคอลัมน์ที่เราระบุจะแสดงอยู่ในส่วนหัวของตารางผลลัพธ์ จริงๆ แล้ว นี่คือจุดประสงค์หลักของชื่อแทนคอลัมน์

โปรดทราบ เพราะ. พนักงาน 2 คนสุดท้ายไม่ได้ระบุชื่อกลาง (ค่า NULL) ดังนั้นผลลัพธ์ของนิพจน์ “LastName+” "+FirstName+" "+MiddleName" ก็ส่งคืน NULL มาให้เราเช่นกัน

หากต้องการรวม (เพิ่ม, ต่อ) สตริงใน MS SQL จะใช้สัญลักษณ์ “+”

โปรดจำไว้ว่านิพจน์ทั้งหมดที่เกี่ยวข้องกับ NULL (เช่น หารด้วย NULL และบวกด้วย NULL) จะส่งคืนค่า NULL

เพียงแค่บันทึก
ในกรณีของ ORACLE ตัวดำเนินการ “||” จะใช้ในการเชื่อมสตริงเข้าด้วยกัน และการต่อข้อมูลจะเป็น "||FirstName||" สำหรับ ORACLE เป็นที่น่าสังเกตว่ามีข้อยกเว้นสำหรับประเภทสตริงสำหรับ NULL และสตริงว่าง "" เป็นสิ่งเดียวกันดังนั้นใน ORACLE นิพจน์ดังกล่าวจะกลับมาสำหรับพนักงาน 2 คนสุดท้าย "Sidorov Sidor" และ "Andrey" อันดรีฟ” สักครู่ เวอร์ชันของออราเคิล 12c เท่าที่ฉันรู้ ไม่มีตัวเลือกที่จะเปลี่ยนแปลงพฤติกรรมนี้ (หากฉันผิด โปรดแก้ไขให้ฉันด้วย) ตรงนี้มันยากสำหรับฉันที่จะตัดสินว่าสิ่งนี้ดีหรือไม่ดี เพราะ... ในบางกรณี ลักษณะการทำงานของสตริง NULL จะสะดวกกว่า เช่น ใน MS SQL และในกรณีอื่นๆ เช่น ใน ORACLE

ใน ORACLE นามแฝงของคอลัมน์ทั้งหมดที่แสดงไว้ด้านบนก็ใช้ได้เช่นกัน ยกเว้น [...]


เพื่อไม่ให้รั้วการก่อสร้างโดยใช้ฟังก์ชัน ISNULL ใน MS SQL เราสามารถใช้ฟังก์ชัน CONCAT ได้ ลองพิจารณาและเปรียบเทียบ 3 ตัวเลือก:

เลือกนามสกุล+" "+FirstName+" "+MiddleName FullName1, -- 2 ตัวเลือกสำหรับการแทนที่ NULL เส้นว่าง"" (เราได้รับพฤติกรรมเช่นเดียวกับใน ORACLE) ISNULL(LastName,"")+" "+ISNULL(FirstName,"")+" "+ISNULL(MiddleName,"") FullName2, CONCAT(LastName," ", ชื่อ, " ",ชื่อกลาง) ชื่อเต็ม3 จากพนักงาน

ชื่อเต็ม1 ชื่อเต็ม2 ชื่อเต็ม3
อีวานอฟ อีวาน อิวาโนวิช อีวานอฟ อีวาน อิวาโนวิช อีวานอฟ อีวาน อิวาโนวิช
เปตรอฟ เปตรอฟ เปโตรวิช เปตรอฟ เปตรอฟ เปโตรวิช เปตรอฟ เปตรอฟ เปโตรวิช
โมฆะ ซิโดรอฟ ซิดอร์ ซิโดรอฟ ซิดอร์
โมฆะ อันดรีฟ อันเดรย์ อันดรีฟ อันเดรย์

ใน MS SQL สามารถระบุนามแฝงได้โดยใช้เครื่องหมายเท่ากับ:

SELECT "Reception date"=HireDate, -- นอกเหนือจาก "..." และ […] คุณสามารถใช้ "..." [วันเกิด]=วันเกิด ZP=เงินเดือน จากพนักงาน

การใช้คีย์เวิร์ด AS หรือเครื่องหมายเท่ากับเพื่อระบุนามแฝงอาจเป็นเรื่องของรสนิยมมากกว่า แต่เมื่อวิเคราะห์คำขอของผู้อื่น ความรู้นี้จะมีประโยชน์

สุดท้ายนี้ฉันจะบอกว่าเป็นการดีกว่าที่จะตั้งชื่อนามแฝงโดยใช้เฉพาะตัวอักษรละตินและตัวเลขเพื่อหลีกเลี่ยงการใช้ “…”, “…” และ […] นั่นคือใช้กฎเดียวกันกับที่เราใช้เมื่อตั้งชื่อตาราง . นอกจากนี้ ในตัวอย่าง ฉันจะใช้เฉพาะชื่อดังกล่าวเท่านั้น และไม่มี “…”, “…” และ […]

ตัวดำเนินการทางคณิตศาสตร์ SQL พื้นฐาน


ลำดับความสำคัญของการดำเนินการ ตัวดำเนินการทางคณิตศาสตร์เช่นเดียวกับในวิชาคณิตศาสตร์ หากจำเป็น สามารถเปลี่ยนลำดับการใช้ตัวดำเนินการได้โดยใช้วงเล็บ - (a+b)*(x/(y-z))

และฉันขอย้ำอีกครั้งว่าการดำเนินการใด ๆ ที่ใช้ NULL จะสร้าง NULL เช่น: 10+NULL, NULL*15/3, 100/NULL - ทั้งหมดนี้จะส่งผลให้เป็น NULL เหล่านั้น. พูดง่ายๆ ไม่ได้กำหนดไม่สามารถให้ผลที่แน่นอนได้ คำนึงถึงสิ่งนี้เมื่อเขียนแบบสอบถามของคุณและหากจำเป็น ให้จัดการค่า NULL โดยใช้ฟังก์ชัน ISNULL และ COALESCE:

เลือก ID,ชื่อ, เงินเดือน/100*BonusPercent AS Result1, -- โดยไม่ต้องประมวลผลค่า NULL เงินเดือน/100*ISNULL(BonusPercent,0) AS Result2, -- ใช้ฟังก์ชัน ISNULL Salary/100*COALESCE(BonusPercent,0) AS Result3 - - ใช้ฟังก์ชัน COALESCE จากพนักงาน

ฉันจะบอกคุณเล็กน้อยเกี่ยวกับฟังก์ชัน COALESCE:

COALESCE (expr1, expr2, ..., exprn) - ส่งกลับค่าแรกที่ไม่ใช่ NULL จากรายการค่า

SELECT COALESCE(f1, f1*f2, f2*f3) val -- ในกรณีนี้ ค่าที่สามจะถูกส่งกลับจาก (SELECT null f1, 2 f2, 3 f3) q

ส่วนใหญ่ฉันจะมุ่งเน้นไปที่การพูดคุยเกี่ยวกับโครงสร้าง DML และส่วนใหญ่ ฉันจะไม่พูดถึงฟังก์ชันที่จะปรากฏในตัวอย่าง หากคุณไม่เข้าใจว่าฟังก์ชันใดฟังก์ชันหนึ่งทำหน้าที่อะไร ให้ค้นหาคำอธิบายของฟังก์ชันนั้นบนอินเทอร์เน็ต คุณสามารถค้นหาข้อมูลตามกลุ่มของฟังก์ชันได้ในคราวเดียว เช่น โดยการถามใน ค้นหาโดย Google“ม.ส. สตริง SQLฟังก์ชั่น", "MS SQL ฟังก์ชันทางคณิตศาสตร์" หรือ "มส ฟังก์ชัน SQLการประมวลผลเป็นโมฆะ" มีข้อมูลมากมายเกี่ยวกับฟังก์ชันต่างๆ และคุณสามารถค้นหาได้ง่าย ตัวอย่างเช่น ในไลบรารี MSDN คุณสามารถดูข้อมูลเพิ่มเติมเกี่ยวกับฟังก์ชัน COALESCE ได้:

การตัดจาก MSDNการเปรียบเทียบ COALESCE และ CASE

นิพจน์ COALESCE เป็นทางลัดทางวากยสัมพันธ์สำหรับนิพจน์ CASE ซึ่งหมายความว่า COALESCE(expression1,...n) ถูกเขียนใหม่โดยเครื่องมือเพิ่มประสิทธิภาพคิวรีเป็นนิพจน์ CASE ต่อไปนี้:

กรณีที่ (expression1 ไม่เป็นโมฆะ) จากนั้น expression1 เมื่อ (expression2 ไม่เป็นโมฆะ) จากนั้น expression2 ... อื่น expressionN END

ตัวอย่างเช่น มาดูกันว่าคุณสามารถใช้ส่วนที่เหลือของการหาร (%) ได้อย่างไร โอเปอเรเตอร์นี้มีประโยชน์มากเมื่อคุณต้องการแบ่งบันทึกออกเป็นกลุ่ม ตัวอย่างเช่น ลองเอาพนักงานทุกคนที่มีคู่ออก หมายเลขบุคลากร(ID) เช่น รหัสเหล่านั้นที่หารด้วย 2:

เลือก ID, ชื่อจากพนักงาน โดยที่ ID%2=0 -- เศษที่เหลือเมื่อหารด้วย 2 คือ 0

ORDER BY – การเรียงลำดับผลลัพธ์ของแบบสอบถาม

ส่วนคำสั่ง ORDER BY ใช้เพื่อเรียงลำดับผลลัพธ์ของแบบสอบถาม

SELECT LastName, FirstName, Salary FROM Employees ORDER BY LastName,FirstName -- เรียงลำดับผลลัพธ์เป็น 2 คอลัมน์ - ตามนามสกุล แล้วตามด้วยชื่อ

สำหรับบันทึกมีคีย์เวิร์ด ASC สำหรับการเรียงลำดับจากน้อยไปหามาก แต่เนื่องจากการเรียงลำดับจากน้อยไปมากเป็นค่าเริ่มต้น คุณจึงลืมตัวเลือกนี้ได้ (ฉันจำไม่ได้ว่าเคยใช้ตัวเลือกนี้เมื่อใด)

เป็นที่น่าสังเกตว่าคำสั่งย่อย ORDER BY ยังสามารถใช้ฟิลด์ที่ไม่อยู่ในรายการในส่วนคำสั่ง SELECT ได้ (ยกเว้นกรณีที่มีการใช้ DISTINCT ซึ่งฉันจะกล่าวถึงด้านล่าง) ตามตัวอย่าง ฉันจะดำเนินการล่วงหน้าเล็กน้อยโดยใช้ตัวเลือก TOP และแสดงให้เห็นว่าคุณสามารถเลือกพนักงาน 3 คนที่มีเงินเดือนสูงสุดได้อย่างไร โดยคำนึงถึงว่าเพื่อวัตถุประสงค์ในการรักษาความลับฉันไม่ควรแสดงเงินเดือน:

SELECT TOP 3 -- ส่งคืนเฉพาะ 3 ระเบียนแรกจาก ID ผลลัพธ์ทั้งหมด, นามสกุล, ชื่อจริงจากพนักงาน ORDER BY Salary DESC -- เรียงลำดับผลลัพธ์จากมากไปหาน้อยของ Salary

บัตรประจำตัวประชาชน นามสกุล ชื่อ
1000 อีวานอฟ อีวาน
1002 ซิโดรอฟ ซีดอร์

แน่นอนว่า มีบางกรณีที่พนักงานหลายคนอาจมีเงินเดือนเท่ากัน และเป็นการยากที่จะบอกว่าคำขอนี้จะส่งกลับพนักงานคนใด ซึ่งจะต้องได้รับการแก้ไขร่วมกับผู้อำนวยการงาน สมมติว่าหลังจากปรึกษาปัญหานี้กับนักออกแบบแล้ว คุณตกลงและตัดสินใจใช้งาน ตัวเลือกถัดไป– ทำการเรียงลำดับเพิ่มเติมตามฟิลด์วันเกิด (เช่น เราให้ความสำคัญกับคนหนุ่มสาว) และหากวันเกิดของพนักงานหลายคนอาจตรงกัน (ซึ่งก็เป็นไปได้เช่นกัน) คุณสามารถทำการเรียงลำดับที่สามตามลำดับจากมากไปน้อย ของค่า ID (สุดท้าย ตัวอย่างจะรวมถึงผู้ที่มี ID สูงสุด - เช่นผู้ที่ได้รับการยอมรับครั้งหลังสมมติว่าเราออกหมายเลขบุคลากรตามลำดับ):

เลือก TOP 3 -- ส่งคืนเฉพาะ 3 ระเบียนแรกจาก ID ผลลัพธ์ทั้งหมด นามสกุล ชื่อจากพนักงาน ORDER BY DESC เงินเดือน -- 1. เรียงลำดับผลลัพธ์จากมากไปน้อยตามวันเกิดเงินเดือน -- 2. จากนั้นตามวันเกิด ID DESC -- 3 และเพื่อความชัดเจนของผลลัพธ์ เราจึงเพิ่มการเรียงลำดับตาม ID

เหล่านั้น. คุณควรพยายามทำให้ผลลัพธ์ของคำขอสามารถคาดเดาได้ เพื่อที่ว่าในกรณีของการซักถาม คุณสามารถอธิบายได้ว่าทำไมบุคคลเหล่านี้จึงถูกรวมอยู่ใน "บัญชีดำ" เช่น ทุกอย่างถูกเลือกอย่างซื่อสัตย์ตามกฎที่กำหนดไว้

คุณยังสามารถเรียงลำดับโดยใช้นิพจน์ที่แตกต่างกันในส่วนคำสั่ง ORDER BY ได้:

เลือกนามสกุล, ชื่อจากพนักงาน ORDER BY CONCAT(LastName," ",FirstName) -- ใช้นิพจน์

คุณยังสามารถใช้นามแฝงที่ระบุสำหรับคอลัมน์ใน ORDER BY:

เลือก CONCAT (นามสกุล, " ", ชื่อ) fi จากพนักงาน ORDER BY fi - ใช้นามแฝง

เป็นที่น่าสังเกตว่าเมื่อใช้คำสั่งย่อย DISTINCT เฉพาะคอลัมน์ที่อยู่ในบล็อก SELECT เท่านั้นที่สามารถใช้ในส่วนคำสั่ง ORDER BY เหล่านั้น. หลังจากใช้การดำเนินการ DISTINCT เราก็จะได้ ชุดใหม่ข้อมูลพร้อมคอลัมน์ชุดใหม่ ด้วยเหตุนี้ ตัวอย่างต่อไปนี้จึงไม่ทำงาน:

SELECT DISTINCT LastName,FirstName,Salary FROM Employees ORDER BY ID -- ID ไม่อยู่ในชุดผลลัพธ์ที่เราได้รับด้วย DISTINCT

เหล่านั้น. คำสั่งย่อย ORDER BY ใช้กับชุดผลลัพธ์ก่อนที่ผลลัพธ์จะถูกส่งกลับไปยังผู้ใช้

หมายเหตุ 1.คุณยังสามารถใช้หมายเลขของคอลัมน์ที่แสดงอยู่ใน SELECT ในส่วนคำสั่ง ORDER BY ได้:

SELECT LastName,FirstName,Salary FROM Employees ORDER BY -- เรียงลำดับ 3 DESC, -- 1. เงินเดือนจากมากไปน้อย 1, -- 2. ตามนามสกุล 2 -- 3. ตามชื่อ

สำหรับผู้เริ่มต้นจะดูสะดวกและน่าดึงดูด แต่เป็นการดีกว่าที่จะลืมและอย่าใช้ตัวเลือกการเรียงลำดับนี้

หากในกรณีนี้ (เมื่อมีการแสดงรายการช่องต่างๆ ไว้อย่างชัดเจน) ตัวเลือกนี้ยังเป็นที่ยอมรับได้ ในกรณีที่ใช้ "*" จะเป็นการดีกว่าที่จะไม่ใช้ตัวเลือกนี้ เพราะเหตุใด - เนื่องจากหากมีคน เช่น เปลี่ยนลำดับของคอลัมน์ในตาราง หรือลบคอลัมน์ (ซึ่งถือเป็นสถานการณ์ปกติ) การสืบค้นของคุณอาจยังใช้งานได้ แต่ไม่ถูกต้อง เนื่องจาก การเรียงลำดับสามารถทำได้โดยคอลัมน์อื่นและนี่เป็นเรื่องร้ายกาจเนื่องจากข้อผิดพลาดนี้อาจไม่ถูกค้นพบในเร็วๆ นี้

หากมีการระบุเสาหลักไว้อย่างชัดเจน ในสถานการณ์ข้างต้น แบบสอบถามจะยังคงทำงานต่อไปแต่ก็ถูกต้องด้วย (เนื่องจากทุกอย่างถูกกำหนดไว้อย่างชัดเจน) หรือเพียงแค่ส่งข้อผิดพลาดที่ ของคอลัมน์นี้ไม่มีอยู่จริง

คุณจึงลืมการเรียงลำดับตามหมายเลขคอลัมน์ไปได้เลย

หมายเหตุ 2
ใน MS SQL เมื่อเรียงลำดับจากน้อยไปหามาก ค่า NULL จะแสดงก่อน

เลือก BonusPercent จากพนักงานเรียงตาม BonusPercent

ดังนั้นเมื่อใช้ DESC มันจะอยู่ที่จุดสิ้นสุด

เลือก BonusPercent จากพนักงานเรียงลำดับตาม BonusPercent DESC

หากคุณต้องการเปลี่ยนตรรกะในการเรียงลำดับค่า NULL ให้ใช้นิพจน์ เช่น:

เลือก BonusPercent จากพนักงาน ORDER BY ISNULL(BonusPercent,100)

ORACLE มีสองตัวเลือกสำหรับจุดประสงค์นี้: NULLS FIRST และ NULLS LAST (ใช้เป็นค่าเริ่มต้น) ตัวอย่างเช่น:

เลือก BonusPercent จากพนักงาน เรียงตาม BonusPercent DESC NULLS LAST

โปรดใส่ใจกับสิ่งนี้เมื่อเปลี่ยนไปใช้ฐานข้อมูลเฉพาะ

TOP – ส่งคืนจำนวนเรคคอร์ดที่ระบุ

สารสกัดจาก MSDN TOP - จำกัดจำนวนแถวที่ส่งคืนในผลลัพธ์แบบสอบถามที่ตั้งไว้ หมายเลขที่กำหนดหรือค่าเปอร์เซ็นต์ เมื่อมีการใช้คำสั่งย่อย TOP ร่วมกับคำสั่งย่อย ORDER BY ชุดผลลัพธ์จะถูกจำกัดไว้ที่ N แถวแรกของผลลัพธ์ที่เรียงลำดับ มิฉะนั้น N แถวแรกจะถูกส่งกลับตามลำดับที่ไม่ได้ระบุ

โดยปกติ การแสดงออกนี้ใช้กับคำสั่งย่อย ORDER BY และเราได้ดูตัวอย่างที่จำเป็นต้องส่งคืน N แถวแรกจากชุดผลลัพธ์แล้ว

หากไม่มี ORDER BY ประโยคนี้มักจะใช้เมื่อเราต้องการดูตารางที่เราไม่รู้จักซึ่งอาจมีบันทึกจำนวนมาก ในกรณีนี้ เราสามารถขอส่งคืนเฉพาะ 10 แถวแรกได้ แต่สำหรับ ความชัดเจนเราจะพูดเพียง 2:

เลือก TOP 2 * จากพนักงาน

คุณยังสามารถระบุคำว่า PERCENT เพื่อส่งคืนเปอร์เซ็นต์ของแถวที่สอดคล้องกันจากชุดผลลัพธ์:

เลือก 25 เปอร์เซนต์สูงสุด * จากพนักงาน

ในทางปฏิบัติของฉัน มักใช้การสุ่มตัวอย่างตามจำนวนแถว

คุณยังสามารถใช้ตัวเลือก WITH TIES กับ TOP ซึ่งจะช่วยส่งคืนแถวทั้งหมดในกรณีที่มีการเรียงลำดับที่ไม่ชัดเจน เช่น ประโยคนี้จะส่งคืนแถวทั้งหมดที่มีองค์ประกอบเท่ากันไปยังแถวที่อยู่ในการเลือก TOP N ส่งผลให้สามารถเลือกได้มากกว่า N แถว เรามาเพิ่ม "โปรแกรมเมอร์" อีกคนด้วยเงินเดือน 1,500 สำหรับการสาธิต:

INSERT Employees(ID,Name,Email,PositionID,DepartmentID,ManagerID,Salary) ค่า(1004,N"Nikolaev N.N."," [ป้องกันอีเมล]",3,3,1003,1500)

และขอเพิ่มพนักงานอีกคนโดยไม่ระบุตำแหน่งและแผนกด้วยเงินเดือน 2,000:

INSERT พนักงาน (ID, ชื่อ, อีเมล, PositionID, DepartmentID, ManagerID, เงินเดือน) ค่า (1005, N "Alexandrov A.A.", [ป้องกันอีเมล]",โมฆะ,โมฆะ,1,000,2000)

ทีนี้มาเลือกใช้ตัวเลือก WITH TIES พนักงานทุกคนที่มีเงินเดือนตรงกับเงินเดือนของพนักงาน 3 คนโดยมีเงินเดือนน้อยที่สุด (ฉันหวังว่าจะชัดเจนยิ่งขึ้นว่าฉันได้รับอะไร):

เลือก 3 อันดับแรกที่มีรหัส TIES, ชื่อ, เงินเดือนจากพนักงานเรียงตามเงินเดือน

ที่นี่แม้ว่าจะมีการระบุ TOP 3 แต่คำขอก็ส่งคืน 4 บันทึกเพราะ มูลค่าเงินเดือนที่ส่งคืน TOP 3 (1,500 และ 2,000) พบในพนักงาน 4 คน สายตามันใช้งานได้ดังนี้:

เพียงแค่บันทึก
TOP ได้รับการปรับใช้ในรูปแบบต่างๆ ในฐานข้อมูลที่แตกต่างกัน ใน MySQL มี LIMIT clause สำหรับสิ่งนี้ ซึ่งคุณสามารถตั้งค่าออฟเซ็ตเริ่มต้นเพิ่มเติมได้

ใน ORACLE 12c พวกเขายังแนะนำอะนาล็อกของตัวเอง โดยผสมผสานฟังก์ชันของ TOP และ LIMIT - ค้นหาคำว่า "ORACLE OFFSET FETCH" ก่อนเวอร์ชัน 12c โดยทั่วไปจะใช้คอลัมน์หลอก ROWNUM เพื่อจุดประสงค์นี้


จะเกิดอะไรขึ้นถ้าคุณใช้ DISTINCT และ TOP clause พร้อมกัน? คำถามดังกล่าวสามารถตอบได้อย่างง่ายดายโดยทำการทดลอง โดยทั่วไปแล้วอย่ากลัวและอย่าเกียจคร้านที่จะทดลองเพราะ... ส่วนใหญ่จะเรียนรู้ผ่านการฝึกฝน ลำดับคำในคำสั่ง SELECT มีดังนี้ DISTINCT มาก่อน ตามด้วย TOP เช่น หากคุณคิดอย่างมีเหตุผลและอ่านจากซ้ายไปขวา ระบบจะใช้รายการแรกที่ทิ้งรายการที่ซ้ำกัน จากนั้น TOP จะถูกสร้างตามชุดนี้ เรามาตรวจสอบและตรวจสอบให้แน่ใจว่าเป็นกรณีนี้:

เลือกเงินเดือน 2 อันดับแรกที่โดดเด่นจากพนักงาน เรียงตามเงินเดือน

เงินเดือน
1500
2000

เหล่านั้น. เป็นผลให้เราได้รับเงินเดือนที่น้อยที่สุด 2 อันดับจากทั้งหมด แน่นอนว่าอาจมีกรณีที่ไม่สามารถระบุเงินเดือนของพนักงานบางคนได้ (NULL) เนื่องจาก โครงการช่วยให้เราทำเช่นนี้ได้ ดังนั้นเราจึงตัดสินใจว่าจะประมวลผลค่า NULL ในส่วนคำสั่ง ORDER BY หรือเพียงแค่ละทิ้งบันทึกทั้งหมดที่เงินเดือนเป็น NULL ขึ้นอยู่กับงานและด้วยเหตุนี้เราจึงดำเนินการศึกษาส่วนคำสั่ง WHERE

WHERE – เงื่อนไขการเลือกแถว

ประโยคนี้ใช้เพื่อกรองบันทึกตามเงื่อนไขที่กำหนด ตัวอย่างเช่น ให้เลือกพนักงานทุกคนที่ทำงานในแผนก "ไอที" (ID=3):

เลือก ID,นามสกุล,ชื่อ,เงินเดือนจากพนักงาน WHERE DepartmentID=3 -- IT ORDER BY LastName,FirstName

บัตรประจำตัวประชาชน นามสกุล ชื่อ เงินเดือน
1004 โมฆะ โมฆะ 1500
1003 อันดรีฟ อันเดรย์ 2000
1001 เปตรอฟ ปีเตอร์ 1500

ส่วนคำสั่ง WHERE ถูกเขียนก่อนคำสั่ง ORDER BY

ลำดับการใช้คำสั่งกับชุดพนักงานเริ่มต้นมีดังนี้:

  1. โดยที่ – หากระบุไว้ ขั้นตอนแรกจากชุดพนักงานทั้งหมดคือการเลือกเฉพาะเรกคอร์ดที่ตรงตามเงื่อนไข
  2. DISTINCT – หากระบุไว้ รายการซ้ำทั้งหมดจะถูกละทิ้ง
  3. ORDER BY – หากระบุ ผลลัพธ์จะถูกจัดเรียง
  4. TOP – หากระบุไว้ ระบบจะส่งกลับเฉพาะจำนวนเรคคอร์ดที่ระบุจากผลลัพธ์ที่เรียงลำดับ

ลองดูตัวอย่างเพื่อความชัดเจน:

เลือกเงินเดือน 1 อันดับแรกที่โดดเด่นจากพนักงาน โดยที่ DepartmentID=3 เรียงตามเงินเดือน

สายตาจะมีลักษณะเช่นนี้:

เป็นที่น่าสังเกตว่าการตรวจสอบค่า NULL ไม่ได้ทำด้วยเครื่องหมายเท่ากับ แต่ใช้ตัวดำเนินการ IS NULL และ IS NOT NULL เพียงจำไว้ว่าคุณไม่สามารถเปรียบเทียบ NULL โดยใช้ตัวดำเนินการ “=” (เครื่องหมายเท่ากับ) ได้ เนื่องจาก ผลลัพธ์ของนิพจน์จะเท่ากับ NULL ด้วย

ตัวอย่างเช่น ให้เลือกพนักงานทั้งหมดที่ไม่ได้ระบุแผนก (เช่น DepartmentID IS NULL):

เลือก ID, ชื่อจากพนักงานโดยที่ DepartmentID เป็นโมฆะ

ในตอนนี้ เป็นตัวอย่าง มาคำนวณโบนัสสำหรับพนักงานทุกคนที่มีค่า BonusPercent ที่ระบุ (เช่น BonusPercent ไม่ใช่ NULL):

เลือก ID, ชื่อ, เงินเดือน/100*BonusPercent เป็นโบนัสจากพนักงาน โดยที่ BonusPercent ไม่ใช่ NULL

ใช่ ยังไงก็ตาม หากคุณลองคิดดู ค่า BonusPercent สามารถเท่ากับศูนย์ (0) และสามารถป้อนค่าด้วยเครื่องหมายลบได้ เนื่องจากเราไม่ได้กำหนดข้อจำกัดใดๆ ในฟิลด์นี้

หลังจากบอกเกี่ยวกับปัญหาแล้ว เราได้รับแจ้งในตอนนี้ให้พิจารณาว่าถ้า (BonusPercent<=0 или BonusPercent IS NULL), то это означает что у сотрудника так же нет бонуса. Для начала, как нам сказали, так и сделаем, реализуем это при помощи логического оператора OR и NOT:

เลือก ID, ชื่อ, เงินเดือน/100*BonusPercent เป็นโบนัสจากพนักงาน โดยที่ไม่ได้ (BonusPercent<=0 OR BonusPercent IS NULL)

เหล่านั้น. ที่นี่เราเริ่มเรียนรู้เกี่ยวกับตัวดำเนินการบูลีน นิพจน์ในวงเล็บ “(BonusPercent<=0 OR BonusPercent IS NULL)» проверяет на то что у сотрудника нет бонуса, а NOT инвертирует это значение, т.е. говорит «верни всех сотрудников которые не сотрудники у которых нет бонуса».

นิพจน์นี้สามารถเขียนใหม่ได้โดยพูดว่า "คืนพนักงานทั้งหมดที่มีโบนัส" ทันทีโดยแสดงสิ่งนี้ด้วยนิพจน์ (BonusPercent>0 และ BonusPercent IS NOT NULL):

เลือก ID, ชื่อ, เงินเดือน/100*BonusPercent เป็นโบนัสจากพนักงาน โดยที่ BonusPercent>0 และ BonusPercent ไม่ใช่ NULL

นอกจากนี้ ในบล็อก WHERE คุณสามารถตรวจสอบนิพจน์ประเภทต่างๆ ได้โดยใช้ตัวดำเนินการและฟังก์ชันทางคณิตศาสตร์ ตัวอย่างเช่น การตรวจสอบที่คล้ายกันสามารถทำได้โดยใช้นิพจน์ที่มีฟังก์ชัน ISNULL:

เลือก ID, ชื่อ, เงินเดือน/100*BonusPercent เป็นโบนัสจากพนักงาน โดยที่ ISNULL(BonusPercent,0)>0

ตัวดำเนินการบูลีนและตัวดำเนินการเปรียบเทียบอย่างง่าย

ใช่ เราไม่สามารถดำเนินการได้หากไม่มีคณิตศาสตร์ที่นี่ ดังนั้น เรามาดูรายละเอียดสั้นๆ เกี่ยวกับบูลีนและตัวดำเนินการเปรียบเทียบแบบง่ายกันดีกว่า

มีตัวดำเนินการบูลีนเพียง 3 ตัวใน SQL - AND, OR และ NOT:

สำหรับตัวดำเนินการบูลีนแต่ละตัว คุณสามารถจัดเตรียมตารางความจริงที่แสดงให้เห็นเพิ่มเติมว่าผลลัพธ์จะเป็นอย่างไรเมื่อเงื่อนไขสามารถเป็น NULL ได้:

มีตัวดำเนินการเปรียบเทียบอย่างง่ายต่อไปนี้ที่ใช้ในการสร้างเงื่อนไข:

นอกจากนี้ยังมีตัวดำเนินการ 2 ตัวสำหรับตรวจสอบค่า/นิพจน์สำหรับ NULL:

เป็นโมฆะ การทดสอบความเท่าเทียมกันของ NULL
ไม่เป็นโมฆะ การทดสอบความไม่เท่าเทียมกันของ NULL

ลำดับความสำคัญ: 1) ตัวดำเนินการเปรียบเทียบทั้งหมด; 2) ไม่; 3) และ; 4) หรือ.

เมื่อสร้างอาคารที่ซับซ้อน การแสดงออกทางตรรกะใช้วงเล็บ:

((เงื่อนไข1 และเงื่อนไข2) หรือไม่(เงื่อนไข3 และเงื่อนไข4 และเงื่อนไข5)) หรือ (...)

นอกจากนี้ คุณสามารถเปลี่ยนลำดับการคำนวณมาตรฐานได้ด้วยการใช้วงเล็บ

ที่นี่ฉันพยายามให้แนวคิดเกี่ยวกับพีชคณิตแบบบูลในปริมาณที่เพียงพอสำหรับการทำงาน อย่างที่คุณเห็น เพื่อที่จะเขียนเงื่อนไขที่ซับซ้อนมากขึ้น คุณไม่สามารถทำได้หากไม่มีตรรกะ แต่ที่นี่มีไม่มากนัก (และ หรือ และไม่ใช่) และมันถูกประดิษฐ์ขึ้นโดยผู้คน ดังนั้นทุกอย่างจึงค่อนข้างสมเหตุสมผล

มาดูตอนท้ายของส่วนที่สองกันดีกว่า

อย่างที่คุณเห็นแม้เกี่ยวกับไวยากรณ์พื้นฐานของตัวดำเนินการ SELECT เราก็สามารถพูดคุยได้เป็นเวลานาน แต่เพื่อให้อยู่ในขอบเขตของบทความในที่สุดฉันก็จะแสดงเพิ่มเติม ตัวดำเนินการเชิงตรรกะ– ระหว่าง ใน และชอบ

BETWEEN – ตรวจสอบการรวมในช่วง

Test_value ระหว่าง start_value และ end_value

นิพจน์สามารถทำหน้าที่เป็นค่าได้

ลองดูตัวอย่าง:

เลือก ID, ชื่อ, เงินเดือนจากพนักงานที่มีเงินเดือนระหว่าง 2,000 ถึง 3,000 - ซึ่งมีเงินเดือนอยู่ในช่วง 2,000-3,000

จริงๆ แล้ว BETWEEN เป็นสัญกรณ์แบบง่ายของแบบฟอร์ม:

เลือก ID, ชื่อ, เงินเดือนจากพนักงาน WHERE เงินเดือน>=2,000 และเงินเดือน<=3000 -- все у кого ЗП в диапозоне 2000-3000

คำว่า NOT สามารถใช้หน้าคำว่า BETWEEN ได้ ซึ่งจะตรวจสอบว่าค่าไม่อยู่ในช่วงที่ระบุหรือไม่:

เลือก ID, ชื่อ, เงินเดือนจากพนักงานโดยที่เงินเดือนไม่อยู่ระหว่าง 2,000 ถึง 3,000 -- คล้ายกับ NOT(เงินเดือน>=2,000 และเงินเดือน<=3000)

ดังนั้น หากคุณใช้ BETWEEN, IN, LIKE คุณสามารถรวมเข้ากับเงื่อนไขอื่นๆ โดยใช้ AND และ OR:

SELECT ID,Name,Salary FROM Employees WHERE Salary BETWEEN 2000 AND 3000 -- ที่มีเงินเดือนอยู่ในช่วง 2000-3000 AND DepartmentID=3 -- คำนึงถึงพนักงานของแผนก 3 เท่านั้น

IN – ตรวจสอบการรวมไว้ในรายการค่า

โอเปอเรเตอร์นี้มีแบบฟอร์มดังต่อไปนี้:

Test_value ใน (value1, value2, ...)

ฉันคิดว่าการแสดงตัวอย่างทำได้ง่ายกว่า:

เลือก ID, ชื่อ, เงินเดือนจากพนักงาน WHERE PositionID IN (3,4) - ซึ่งมีตำแหน่ง 3 หรือ 4

เหล่านั้น. โดยพื้นฐานแล้วจะเหมือนกับนิพจน์ต่อไปนี้:

เลือก ID, ชื่อ, เงินเดือนจากพนักงาน โดยที่ PositionID=3 หรือ PositionID=4 -- ซึ่งมีตำแหน่ง 3 หรือ 4

ในกรณีของ NOT มันจะคล้ายกัน (เราจะได้ทุกคนยกเว้นแผนก 3 และ 4):

เลือก ID, ชื่อ, เงินเดือนจากพนักงานโดยที่ PositionID ไม่อยู่ใน (3,4) -- คล้ายกับ NOT (PositionID=3 หรือ PositionID=4)

แบบสอบถามที่มี NOT IN สามารถแสดงโดยใช้ AND:

เลือก ID, ชื่อ, เงินเดือนจากพนักงาน WHERE PositionID<>3และตำแหน่งID<>4 -- เทียบเท่ากับ PositionID NOT IN(3,4)

โปรดทราบว่าการค้นหาค่า NULL โดยใช้โครงสร้าง IN จะไม่ทำงานเพราะว่า การตรวจสอบ NULL=NULL จะส่งคืนค่า NULL ไม่ใช่ True:

เลือก ID, ชื่อ, DepartmentID จากพนักงาน WHERE DepartmentID IN (1,2, NULL) -- บันทึก NULL จะไม่รวมอยู่ในผลลัพธ์

ในกรณีนี้ ให้แบ่งเช็คออกเป็นหลายเงื่อนไข:

เลือก ID, ชื่อ, DepartmentID จากพนักงานโดยที่ DepartmentID IN (1,2) -- 1 หรือ 2 หรือ DepartmentID เป็น NULL -- หรือ NULL

หรือคุณสามารถเขียนบางอย่างเช่น:

เลือก ID,ชื่อ,DepartmentID จากพนักงาน WHERE ISNULL(DepartmentID,-1) IN(1,2,-1) -- หากคุณแน่ใจว่าไม่มีแผนกที่มี ID=-1

ฉันคิดว่าตัวเลือกแรกในกรณีนี้จะถูกต้องและเชื่อถือได้มากกว่า โอเค นี่เป็นเพียงตัวอย่างเพื่อแสดงให้เห็นว่าโครงสร้างอื่นใดที่สามารถสร้างได้

นอกจากนี้ยังควรกล่าวถึงข้อผิดพลาดที่ร้ายกาจยิ่งกว่าที่เกี่ยวข้องกับ NULL ซึ่งสามารถทำได้เมื่อใช้โครงสร้าง NOT IN ตัวอย่างเช่น ลองเลือกพนักงานทั้งหมด ยกเว้นพนักงานที่มีแผนกเป็น 1 หรือไม่ได้ระบุแผนกเลย เช่น เท่ากับ NULL เพื่อเป็นวิธีแก้ปัญหา ตัวเลือกต่อไปนี้จะแนะนำตัวเอง:

เลือก ID, ชื่อ, DepartmentID จากพนักงานโดยที่ DepartmentID ไม่อยู่ใน (1, NULL)

แต่หลังจากดำเนินการค้นหาแล้ว เราจะไม่ได้รับแถวเดียว แม้ว่าเราคาดว่าจะเห็นสิ่งต่อไปนี้:

อีกครั้ง เรื่องตลกที่นี่เล่นโดย NULL ที่ระบุในรายการค่า

มาดูกันว่าเหตุใดจึงเกิดข้อผิดพลาดเชิงตรรกะในกรณีนี้ มาขยายแบบสอบถามโดยใช้ AND:

เลือก ID, ชื่อ, DepartmentID จากพนักงาน WHERE DepartmentID<>1 และ ID แผนก<>NULL -- ปัญหาเกิดจากการตรวจสอบ NULL นี้ เงื่อนไขนี้จะคืนค่า NULL เสมอ

สภาพถูกต้อง (DepartmentID<>NULL) จะให้ความไม่แน่นอนแก่เราเสมอที่นี่ เช่น โมฆะ. ตอนนี้ จำตารางความจริงสำหรับตัวดำเนินการ AND โดยที่ (TRUE และ NULL) ให้ค่า NULL เหล่านั้น. เมื่อตรงตามเงื่อนไขด้านซ้าย (DepartmentID<>1) เนื่องจากเงื่อนไขสิทธิ์ที่ไม่ได้กำหนดไว้ เราจะได้ค่าที่ไม่ได้กำหนดสำหรับนิพจน์ทั้งหมด (DepartmentID<>1 และ ID แผนก<>NULL) ดังนั้นสตริงจะไม่รวมอยู่ในผลลัพธ์

สามารถเขียนเงื่อนไขใหม่ได้อย่างถูกต้องดังนี้:

เลือก ID, ชื่อ, DepartmentID จากพนักงานโดยที่ DepartmentID ไม่อยู่ใน (1) - หรือในกรณีนี้เพียง DepartmentID<>1 และ DepartmentID ไม่เป็นโมฆะ -- และแยกตรวจสอบว่าไม่เป็นโมฆะ

IN ยังสามารถใช้กับแบบสอบถามย่อยได้ แต่เราจะกลับมาที่แบบฟอร์มนี้ในส่วนต่อๆ ไปของบทช่วยสอนนี้

LIKE – การตรวจสอบสตริงโดยใช้รูปแบบ

ฉันจะพูดถึงโอเปอเรเตอร์นี้เฉพาะในรูปแบบที่ง่ายที่สุดซึ่งเป็นมาตรฐานและได้รับการสนับสนุนโดยภาษา SQL ส่วนใหญ่ แม้จะอยู่ในรูปแบบนี้ ก็สามารถใช้เพื่อแก้ไขปัญหาต่างๆ ที่ต้องตรวจสอบเนื้อหาของสตริงได้

โอเปอเรเตอร์นี้มีแบบฟอร์มดังต่อไปนี้:

Test_string เช่น string_pattern

สามารถใช้อักขระพิเศษต่อไปนี้ใน "pattern_string":

  1. ขีดล่าง “_” หมายความว่าสามารถใช้อักขระตัวเดียวแทนได้
  2. เครื่องหมายเปอร์เซ็นต์ “%” - บอกว่าสามารถแทนที่ด้วยอักขระจำนวนเท่าใดก็ได้ รวมถึงไม่มีด้วย
ลองดูตัวอย่างที่มีสัญลักษณ์ "%" (ในทางปฏิบัติมักใช้บ่อยกว่า):

SELECT ID, ชื่อจากพนักงาน WHERE Name LIKE "Pet%" -- ซึ่งชื่อขึ้นต้นด้วยตัวอักษร "Pet" SELECT ID, LastName FROM Employees WHERE LastName LIKE "%ov" -- ซึ่งนามสกุลลงท้ายด้วย "ov" SELECT ID, นามสกุลจากพนักงาน โดยที่นามสกุลเช่น "%re%" -- ซึ่งนามสกุลประกอบด้วยชุดค่าผสม "re"

ลองดูตัวอย่างที่มีสัญลักษณ์ “_”:

SELECT ID, นามสกุลจากพนักงาน WHERE นามสกุล LIKE "_etrov" -- ซึ่งนามสกุลประกอบด้วยอักขระตัวแรกและตัวอักษรที่ตามมา "etrov" SELECT ID, นามสกุลจากพนักงาน WHERE นามสกุล LIKE "____ov" -- ซึ่งนามสกุลประกอบด้วยอักขระสี่ตัวใดก็ได้ และตัวอักษรต่อมาคือ "ov"

เมื่อใช้ ESCAPE คุณสามารถระบุอักขระ Escape ที่ยกเลิกผลการตรวจสอบของอักขระพิเศษ "_" และ "%" ส่วนคำสั่งนี้ใช้เมื่อคุณต้องการตรวจสอบเครื่องหมายเปอร์เซ็นต์หรือขีดล่างในสตริงโดยตรง

เพื่อสาธิต ESCAPE เรามารวมขยะไว้ในรายการเดียว:

อัปเดตพนักงาน SET FirstName = "นี่คือถังขยะที่มี %" โดยที่ ID = 1005

และมาดูกันว่าแบบสอบถามต่อไปนี้ส่งคืนอะไร:

SELECT * จากพนักงานโดยที่ FirstName เช่น "%!%%" ESCAPE "!" -- บรรทัดมีเครื่องหมาย "%" SELECT * FROM Employees WHERE FirstName LIKE "%!_%" ESCAPE "!" -- บรรทัดมีเครื่องหมาย "_"

หากคุณต้องการตรวจสอบสตริงเพื่อดูการจับคู่ที่สมบูรณ์ แทนที่จะใช้ LIKE ควรใช้เครื่องหมาย “=”:

SELECT * จากพนักงาน WHERE FirstName = "Peter"

เพียงแค่บันทึก
ใน MS SQL ในเทมเพลตตัวดำเนินการ LIKE คุณสามารถระบุการค้นหาโดยใช้นิพจน์ทั่วไปได้ อ่านเกี่ยวกับเรื่องนี้บนอินเทอร์เน็ตหากความสามารถมาตรฐานของตัวดำเนินการนี้ไม่เพียงพอสำหรับคุณ

ORACLE ใช้ฟังก์ชัน REGEXP_LIKE เพื่อค้นหาโดยใช้นิพจน์ทั่วไป

เล็กน้อยเกี่ยวกับสตริง

ในกรณีที่ตรวจสอบสตริงว่ามีอักขระ Unicode หรือไม่ คุณจะต้องวางอักขระ N ก่อนเครื่องหมายคำพูด เช่น น"…". แต่เนื่องจากช่องอักขระทั้งหมดในตารางของเราอยู่ในรูปแบบ Unicode (ประเภท nvarchar) คุณจึงใช้รูปแบบนี้กับช่องเหล่านี้ได้ตลอดเวลา ตัวอย่าง:

เลือก ID, ชื่อจากพนักงาน โดยที่ชื่อ LIKE N"Pet%" เลือก ID, นามสกุลจากพนักงาน WHERE LastName=N"Petrov"

เมื่อทำอย่างถูกต้อง เมื่อเปรียบเทียบกับฟิลด์ประเภท varchar (ASCII) คุณควรลองใช้การทดสอบโดยใช้ "..." และเมื่อเปรียบเทียบฟิลด์กับประเภท nvarchar (Unicode) คุณควรลองใช้การทดสอบโดยใช้ N" …”. ซึ่งทำเพื่อหลีกเลี่ยงการแปลงประเภทโดยนัยระหว่างการดำเนินการค้นหา เราใช้กฎเดียวกันเมื่อแทรกค่า (INSERT) ลงในฟิลด์หรืออัปเดต (UPDATE)

เมื่อเปรียบเทียบสตริง ควรพิจารณาจุดที่ขึ้นอยู่กับการตั้งค่าฐานข้อมูล (การจัดเรียง) การเปรียบเทียบสตริงอาจเป็นแบบคำนึงถึงตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ (เมื่อ "Petrov" = "PETROV") หรือคำนึงถึงตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ (เมื่อ "Petrov"<>"เปตรอฟ").
ในกรณีของการตั้งค่าที่คำนึงถึงตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ หากคุณต้องการค้นหาโดยไม่คำนึงถึงตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ คุณสามารถแปลงนิพจน์ด้านขวาและซ้ายไว้ล่วงหน้าเป็นตัวพิมพ์เดียว - บนหรือล่าง:

เลือก ID, ชื่อจากพนักงาน โดยที่ UPPER(ชื่อ) เช่น UPPER(N"Pet%") -- หรือ LOWER(ชื่อ) เช่น LOWER(N"Pet%") เลือก ID,นามสกุลจากพนักงาน โดยที่ UPPER(LastName)=UPPER( N"Petrov") -- หรือ LOWER(LastName)=LOWER(N"Petrov")

เล็กน้อยเกี่ยวกับวันที่

เมื่อตรวจสอบวันที่ คุณสามารถใช้เครื่องหมายคำพูดเดี่ยว "..." ได้เช่นเดียวกับสตริง

ไม่ว่าการตั้งค่าภูมิภาคใน MS SQL จะเป็นอย่างไร คุณสามารถใช้ไวยากรณ์วันที่ต่อไปนี้ "YYYYMMDD" (ปี เดือน วัน รวมกันโดยไม่ต้องเว้นวรรค) MS SQL จะเข้าใจรูปแบบวันที่นี้เสมอ:

เลือก ID, ชื่อ, วันเกิดจากพนักงานโดยที่วันเกิดระหว่าง "19800101" และ "19891231" - พนักงานในยุค 80 เรียงตามวันเกิด

ในบางกรณี การตั้งวันที่โดยใช้ฟังก์ชัน DATEFROMPARTS จะสะดวกกว่า:

เลือก ID, ชื่อ, วันเกิดจากพนักงานโดยที่วันเกิดระหว่าง DATEFROMPARTS (1980,1,1) และ DATEFROMPARTS (1989,12,31) เรียงตามวันเกิด

นอกจากนี้ยังมีฟังก์ชันที่คล้ายกัน DATETIMEFROMPARTS ซึ่งใช้ในการตั้งค่าวันที่และเวลา (สำหรับประเภทวันที่และเวลา)

คุณยังสามารถใช้ฟังก์ชัน CONVERT ได้หากต้องการแปลงสตริงเป็นค่าวันที่หรือเวลา:

เลือก แปลง(วันที่,"12.03.2015",104), แปลง(วันที่เวลา,"2014-11-30 17:20:15",120)

ค่า 104 และ 120 ระบุรูปแบบวันที่ที่ใช้ในสตริง คุณสามารถค้นหาคำอธิบายของรูปแบบที่ถูกต้องทั้งหมดในไลบรารี MSDN ได้โดยการค้นหา “MS SQL CONVERT”

มีฟังก์ชันมากมายสำหรับการทำงานกับวันที่ใน MS SQL ให้มองหา “ฟังก์ชัน ms sql สำหรับการทำงานกับวันที่”

บันทึก.ภาษา SQL ทุกภาษามีชุดฟังก์ชันของตนเองสำหรับการทำงานกับวันที่และใช้วิธีการของตนเองในการทำงานกับวันที่

เล็กน้อยเกี่ยวกับตัวเลขและการแปลง

ข้อมูลในส่วนนี้อาจเป็นประโยชน์กับผู้เชี่ยวชาญด้านไอทีมากกว่า หากคุณไม่ใช่หนึ่งเดียวและเป้าหมายของคุณคือเพียงเรียนรู้วิธีเขียนแบบสอบถามเพื่อรับข้อมูลที่คุณต้องการจากฐานข้อมูล คุณอาจไม่ต้องการรายละเอียดปลีกย่อยดังกล่าว แต่ในกรณีใด ๆ คุณสามารถอ่านข้อความและจดบันทึกได้อย่างรวดเร็ว , เพราะ . หากคุณได้ศึกษาเกี่ยวกับ SQL แสดงว่าคุณเข้าร่วมงานไอทีแล้ว

ต่างจากฟังก์ชันการแปลง CAST คุณสามารถระบุพารามิเตอร์ที่สามในฟังก์ชัน CONVERT ซึ่งรับผิดชอบรูปแบบการแปลง (รูปแบบ) ประเภทข้อมูลที่แตกต่างกันอาจมีชุดสไตล์ของตัวเอง ซึ่งอาจส่งผลต่อผลลัพธ์ที่ส่งคืน เราได้สัมผัสถึงการใช้สไตล์แล้วเมื่อพิจารณาการแปลงสตริงโดยใช้ฟังก์ชัน CONVERT เป็นประเภทวันที่และเวลา

คุณสามารถอ่านเพิ่มเติมเกี่ยวกับฟังก์ชัน CAST, CONVERT และสไตล์ใน MSDN - “ฟังก์ชัน CAST และ CONVERT (Transact-SQL)”: msdn.microsoft.com/ru-ru/library/ms187928.aspx

เพื่อให้ตัวอย่างง่ายขึ้น จะใช้คำสั่งภาษา Transact-SQL DECLARE และ SET ที่นี่

แน่นอน ในกรณีของการแปลงจำนวนเต็มเป็นจำนวนจริง (ซึ่งฉันได้ให้ไว้ตอนต้นของบทเรียนนี้ เพื่อแสดงให้เห็นความแตกต่างระหว่างจำนวนเต็มและการหารจำนวนจริง) ความรู้เกี่ยวกับความแตกต่างของการแปลงนั้นไม่สำคัญนัก เพราะ ที่นั่นเราได้แปลงจำนวนเต็มเป็นจำนวนจริง (ช่วงซึ่งมากกว่าช่วงของจำนวนเต็มมาก):

ประกาศ @min_int int SET @min_int=-2147483648 ประกาศ @max_int int SET @max_int=2147483647 SELECT -- (-2147483648) @min_int,CAST(@min_int AS float),CONVERT(float,@min_int), -- 2147483647 @max_int ,CAST(@max_int AS float),CONVERT(float,@max_int), -- ตัวเลข(16,6) @min_int/1., -- (-2147483648.000000) @max_int/1. -- 2147483647.000000

บางทีอาจไม่คุ้มค่าที่จะระบุวิธีการแปลงโดยนัยที่ได้จากการหารด้วย (1.) เพราะ ขอแนะนำให้ลองทำการแปลงที่ชัดเจนเพื่อการควบคุมประเภทของผลลัพธ์ที่ได้รับมากขึ้น แม้ว่าเราต้องการได้ผลลัพธ์เป็นประเภทตัวเลข โดยมีจำนวนหลักที่ระบุหลังจุดทศนิยม เราก็สามารถใช้เคล็ดลับใน MS SQL เพื่อคูณค่าจำนวนเต็มด้วย (1., 1.0, 1.00 ฯลฯ) : :

ประกาศ @int int SET @int=123 SELECT @int*1., -- ตัวเลข(12, 0) - ทศนิยม 0 ตำแหน่ง @int*1.0, -- ตัวเลข(13, 1) - ทศนิยม 1 ตำแหน่ง @int*1.00, -- ตัวเลข(14, 2) - 2 ตัวอักษร -- แม้ว่าบางครั้งจะเป็นการดีกว่าหากทำการแปลงอย่างชัดเจน CAST(@int AS numeric(20, 0)) -- 123 CAST(@int AS numeric(20, 1) ), -- 123.0 CAST(@int AS ตัวเลข(20, 2)) -- 123.00

ในบางกรณีรายละเอียดของการแปลงมีความสำคัญมาก เนื่องจาก... ส่งผลต่อความถูกต้องของผลลัพธ์ที่ได้รับ เช่น ในกรณีที่ทำการแปลงจากค่าตัวเลขเป็นสตริง (varchar) ลองดูตัวอย่างการแปลงเงินและค่าลอยตัวเป็น varchar:

พฤติกรรมเมื่อแปลงเงินเป็น varchar DECLARE @money money SET @money = 1025.123456789 -- จะมีการแปลงโดยนัยเป็น 1025.1235 เพราะ ประเภทเงินเก็บเพียง 4 หลักหลังจุดทศนิยม SELECT @money, -- 1025.1235 -- ตามค่าเริ่มต้น CAST และ CONVERT จะทำงานเหมือนกัน (เช่น พูดคร่าวๆ จะใช้สไตล์ 0) CAST(@money as varchar(20)) , -- 1,025.12 CONVERT(varchar(20), @money), -- 1,025.12 CONVERT(varchar(20), @money, 0), -- 1,025.12 (รูปแบบ 0 - ไม่มีตัวคั่นหลักพันและทศนิยม 2 ตำแหน่ง (รูปแบบเริ่มต้น)) CONVERT( varchar(20), @money, 1), -- 1.025.12 (สไตล์ 1 - ใช้ตัวคั่นหนึ่งในพันและทศนิยม 2 ตำแหน่ง) CONVERT(varchar(20), @money, 2) -- 1025.1235 (สไตล์ 2 - ไม่มีตัวคั่นและมีตัวเลข 4 ตัวหลังจุดทศนิยม)

พฤติกรรมเมื่อแปลง float เป็น varchar DECLARE @float1 float SET @float1 = 1025.123456789 DECLARE @float2 float SET @float2 = 1231025.123456789 SELECT @float1, -- 1025.123456789 @float2, -- 1231025 .12345679 -- โดย ค่าเริ่มต้น CAST และ CONVERT จะทำงานเหมือนกัน (กล่าวคือ พูดคร่าวๆ ก็คือใช้สไตล์ 0) -- สไตล์ 0 - ไม่เกิน 6 หลัก สัญลักษณ์เอ็กซ์โพเนนเชียลถูกใช้โดยไม่จำเป็น -- สิ่งที่น่ากลัวจริงๆ เกิดขึ้นที่นี่เมื่อแปลงเป็น varchar CAST(@float1 เป็น varchar(20)), -- 1,025.12 CONVERT(varchar(20), @float1), -- 1,025.12 CONVERT(varchar( 20 ), @float1, 0), -- 1,025.12 CAST(@float2 เป็น varchar(20)), -- 1.23103e+006 CONVERT(varchar(20), @float2), -- 1.23103e+006 CONVERT(varchar( 20 ), @float2, 0), -- 1.23103e+006 -- style 1 - ต้องมี 8 หลักเสมอ มีการใช้สัญลักษณ์ทางวิทยาศาสตร์สำหรับตัวเลขเสมอ

-- สไตล์สำหรับ float นี้ยังไม่ถูกต้องมากนัก CONVERT(varchar(20), @float1, 1), -- 1.0251235e+003 CONVERT(varchar(20), @float2, 1), -- 1.2310251e+006 - - สไตล์ 2 - 16 บิตเสมอ มีการใช้สัญลักษณ์ทางวิทยาศาสตร์สำหรับตัวเลขเสมอ

หากคุณต้องการควบคุมความแม่นยำอย่างชัดเจนจนถึงเครื่องหมายที่กำหนด ซึ่งมากกว่า 4 บางครั้งการใช้ประเภททศนิยม/ตัวเลขในการจัดเก็บข้อมูลก็ดีกว่า หากเพียงพอแล้ว 4 ตัวอักษรคุณสามารถใช้ประเภทเงินได้ - ซึ่งสอดคล้องกับตัวเลขโดยประมาณ(20,4)

ทศนิยมและตัวเลข DECLARE @money money SET @money = 1025.123456789 -- 1025.1235 DECLARE @float1 float SET @float1 = 1025.123456789 DECLARE @float2 float SET @float2 = 1231025.123456789 DECLARE @numer ic(28,9 ) SET @numeric = 1025.123456789 เลือกนักแสดง ( @numeric as varchar(20)), -- 1025.12345679 CONVERT(varchar(20), @numeric), -- 1025.12345679 CAST(@money as numeric(28,9)), -- 1025.123500000 CAST(@float1 as numeric( 28 ,9)), -- 1025.123456789 CAST(@float2 เป็นตัวเลข(28,9)) -- 1231025.123456789

บันทึก.
จากเวอร์ชัน MS SQL 2008 คุณสามารถใช้แทนโครงสร้างได้: เพิ่มป้ายกำกับ

ภาษา SQL ใช้เพื่อดึงข้อมูลจากฐานข้อมูล SQL เป็นภาษาโปรแกรมที่คล้ายกับภาษาอังกฤษมาก แต่มีไว้สำหรับโปรแกรมการจัดการฐานข้อมูล SQL ถูกใช้ในทุกแบบสอบถามใน Access

การทำความเข้าใจวิธีการทำงานของ SQL จะช่วยให้คุณสร้างคิวรีที่แม่นยำยิ่งขึ้น และทำให้แก้ไขคิวรีที่ให้ผลลัพธ์ที่ไม่ถูกต้องได้ง่ายขึ้น

นี่คือบทความจากชุดบทความเกี่ยวกับภาษา SQL สำหรับ Access โดยจะอธิบายพื้นฐานของการใช้ SQL เพื่อดึงข้อมูลและให้ตัวอย่างของไวยากรณ์ SQL

ในบทความนี้

SQL คืออะไร?

SQL เป็นภาษาโปรแกรมที่ออกแบบมาเพื่อทำงานกับชุดข้อเท็จจริงและความสัมพันธ์ระหว่างชุดข้อเท็จจริงเหล่านั้น โปรแกรมการจัดการฐานข้อมูลเชิงสัมพันธ์ เช่น Microsoft Office Access ใช้ SQL เพื่อจัดการข้อมูล ไม่เหมือนกับภาษาการเขียนโปรแกรมอื่นๆ SQL สามารถอ่านและเข้าใจได้แม้กระทั่งสำหรับผู้เริ่มต้น เช่นเดียวกับภาษาการเขียนโปรแกรมอื่นๆ SQL เป็นมาตรฐานสากลที่คณะกรรมการมาตรฐานยอมรับ เช่น ISO และ ANSI

ชุดข้อมูลอธิบายไว้ใน SQL เพื่อช่วยตอบคำถาม เมื่อใช้ SQL คุณต้องใช้ไวยากรณ์ที่ถูกต้อง ไวยากรณ์คือชุดของกฎที่ช่วยให้องค์ประกอบของภาษาสามารถรวมกันได้อย่างถูกต้อง ไวยากรณ์ SQL ขึ้นอยู่กับไวยากรณ์ภาษาอังกฤษและใช้องค์ประกอบหลายอย่างร่วมกับไวยากรณ์ Visual Basic for Applications (VBA)

ตัวอย่างเช่นเรียบง่าย คำสั่ง SQLซึ่งดึงรายการนามสกุลของผู้ติดต่อชื่อ Mary อาจมีลักษณะดังนี้:

เลือกนามสกุล
จากผู้ติดต่อ
โดยที่ First_Name = "แมรี่";

บันทึก:ภาษา SQL ถูกใช้ไม่เพียงแต่ในการดำเนินการกับข้อมูลเท่านั้น แต่ยังใช้เพื่อสร้างและเปลี่ยนแปลงโครงสร้างของวัตถุฐานข้อมูล เช่น ตาราง อีกด้วย ส่วนของ SQL ที่ใช้สร้างและแก้ไขอ็อบเจ็กต์ฐานข้อมูลเรียกว่า DDL DDL ไม่ครอบคลุมอยู่ในบทความนี้ สำหรับข้อมูลเพิ่มเติม ดูสร้างหรือปรับเปลี่ยนตารางหรือดัชนีโดยใช้คิวรีข้อกำหนดข้อมูล

คำสั่ง SELECT

คำสั่ง SELECT ใช้เพื่ออธิบายชุดข้อมูลใน SQL ประกอบด้วยคำอธิบายที่สมบูรณ์ของชุดข้อมูลที่จำเป็นต้องดึงจากฐานข้อมูล รวมถึงสิ่งต่อไปนี้:

    ตารางที่มีข้อมูล

    การเชื่อมต่อระหว่างข้อมูลจากแหล่งต่างๆ

    ฟิลด์หรือการคำนวณตามข้อมูลที่เลือก

    เงื่อนไขการเลือกที่ต้องเป็นไปตามข้อมูลที่รวมอยู่ในผลลัพธ์การสืบค้น

    ความจำเป็นและวิธีการคัดแยก

คำสั่ง SQL

คำสั่ง SQL ประกอบด้วยหลายส่วนที่เรียกว่าคำสั่งย่อย แต่ละคำสั่งย่อยในคำสั่ง SQL มีวัตถุประสงค์ จำเป็นต้องมีข้อเสนอบางอย่าง ตารางด้านล่างแสดงคำสั่ง SQL ที่ใช้บ่อยที่สุด

คำสั่ง SQL

คำอธิบาย

บังคับ

กำหนดฟิลด์ที่มีข้อมูลที่จำเป็น

กำหนดตารางที่มีเขตข้อมูลที่ระบุในส่วนคำสั่ง SELECT

กำหนดเงื่อนไขการเลือกฟิลด์ที่เรกคอร์ดทั้งหมดที่รวมอยู่ในผลลัพธ์ต้องเป็นไปตาม

กำหนดลำดับการจัดเรียงของผลลัพธ์

ในคำสั่ง SQL ที่มีฟังก์ชันการรวม ให้ระบุฟิลด์ที่ไม่ได้คำนวณค่าสรุปในส่วนคำสั่ง SELECT

เฉพาะในกรณีที่มีช่องดังกล่าวอยู่เท่านั้น

คำสั่ง SQL ที่มีฟังก์ชันการรวมจะกำหนดเงื่อนไขที่ใช้กับฟิลด์ที่มีการคำนวณค่าสรุปในส่วนคำสั่ง SELECT

เงื่อนไข SQL

แต่ละประโยค SQL ประกอบด้วยคำศัพท์ที่สามารถเปรียบเทียบได้กับส่วนของคำพูด ตารางด้านล่างแสดงประเภทของคำศัพท์ SQL

คำศัพท์ SQL

ส่วนของคำพูดที่เปรียบเทียบได้

คำนิยาม

ตัวอย่าง

ตัวระบุ

คำนาม

ชื่อที่ใช้ระบุวัตถุฐานข้อมูล เช่น ชื่อฟิลด์

ลูกค้า[หมายเลขโทรศัพท์]

ตัวดำเนินการ

กริยาหรือคำวิเศษณ์

คำสำคัญที่แสดงถึงหรือแก้ไขการกระทำ

คงที่

คำนาม

ค่าที่ไม่เปลี่ยนแปลง เช่น ตัวเลขหรือ NULL

การแสดงออก

คุณศัพท์

การรวมกันของตัวระบุ ตัวดำเนินการ ค่าคงที่ และฟังก์ชันที่ออกแบบมาเพื่อคำนวณค่าเดียว

>= สินค้า[ราคา]

ส่วนคำสั่ง SQL พื้นฐาน: SELECT, FROM และ WHERE

รูปแบบทั่วไปของคำสั่ง SQL คือ:

เลือก field_1
จากตาราง_1
เกณฑ์อยู่ที่ไหน_1
;

หมายเหตุ:

    การเข้าถึงไม่เคารพการแบ่งบรรทัดในคำสั่ง SQL อย่างไรก็ตาม ขอแนะนำให้เริ่มแต่ละประโยคด้วย บรรทัดใหม่เพื่อให้คำสั่ง SQL สามารถอ่านได้ง่ายทั้งสำหรับผู้เขียนและสำหรับคนอื่นๆ

    ทุกคำสั่ง SELECT จะลงท้ายด้วยเครื่องหมายอัฒภาค (;) อัฒภาคสามารถปรากฏที่ส่วนท้ายของประโยคสุดท้ายหรือบนบรรทัดแยกต่างหากที่ส่วนท้ายของคำสั่ง SQL

ตัวอย่างในการเข้าถึง

ตัวอย่างด้านล่างแสดงให้เห็นว่าคำสั่ง SQL อาจมีลักษณะอย่างไรใน Access คำของ่ายๆต่อตัวอย่าง

1. เลือกข้อ

2. จาก ข้อ

3. ข้อ WHERE

ลองดูตัวอย่างทีละประโยคเพื่อทำความเข้าใจว่าไวยากรณ์ SQL ทำงานอย่างไร

ส่วนคำสั่ง SELECT

เลือกบริษัท

นี่คือส่วนคำสั่ง SELECT ประกอบด้วยคำสั่ง (SELECT) ตามด้วยตัวระบุสองตัว ("[ที่อยู่อีเมล]" และ "บริษัท")

หากตัวระบุมีการเว้นวรรคหรือ สัญญาณพิเศษ(เช่น "ที่อยู่อีเมล") จะต้องอยู่ในวงเล็บสี่เหลี่ยม

ส่วนคำสั่ง SELECT ไม่ต้องการให้คุณระบุตารางที่มีเขตข้อมูล และคุณไม่สามารถระบุเงื่อนไขการเลือกที่ข้อมูลที่รวมอยู่ในผลลัพธ์ต้องเป็นไปตามนั้น

ในคำสั่ง SELECT ส่วนคำสั่ง SELECT จะอยู่ก่อนส่วนคำสั่ง FROM เสมอ

จากข้อ

จากผู้ติดต่อ

นี่คือส่วนคำสั่ง FROM ประกอบด้วยคำสั่ง (FROM) ตามด้วยตัวระบุ (ผู้ติดต่อ)

ส่วนคำสั่ง FROM ไม่ได้ระบุฟิลด์ให้เลือก

ข้อไหน

เมืองไหน = "ซีแอตเทิล"

นี่คือส่วนคำสั่ง WHERE ประกอบด้วยคำสั่ง (WHERE) ตามด้วยนิพจน์ (City="Rostov")

มีหลายสิ่งที่คุณสามารถทำได้ด้วยส่วนคำสั่ง SELECT, FROM และ WHERE สำหรับข้อมูลเพิ่มเติมเกี่ยวกับการใช้ข้อเสนอเหล่านี้ ดูบทความต่อไปนี้:

การเรียงลำดับผลลัพธ์: ORDER BY

เช่นเดียวกับ Microsoft Excel Access ช่วยให้คุณสามารถเรียงลำดับผลลัพธ์ของคิวรีในตารางได้ เมื่อใช้ส่วนคำสั่ง ORDER BY คุณยังสามารถระบุวิธีการเรียงลำดับผลลัพธ์เมื่อดำเนินการคิวรีได้ หากใช้คำสั่งย่อย ORDER BY จะต้องปรากฏที่ส่วนท้ายของคำสั่ง SQL

ส่วนคำสั่ง ORDER BY ประกอบด้วยรายการฟิลด์ที่จะเรียงลำดับ ตามลำดับเดียวกับที่จะใช้การเรียงลำดับ

ตัวอย่างเช่น สมมติว่าก่อนอื่นต้องเรียงลำดับผลลัพธ์ตามฟิลด์ "บริษัท" ตามลำดับจากมากไปหาน้อย จากนั้นหากมีบันทึกที่มี ค่าเดียวกันช่อง "บริษัท" - จัดเรียงตามช่อง "ที่อยู่อีเมล" ตามลำดับจากน้อยไปหามาก ส่วนคำสั่ง ORDER BY จะมีลักษณะดังนี้:

สั่งซื้อโดยบริษัท DESC

บันทึก:ตามค่าเริ่มต้น Access จะเรียงลำดับค่าจากน้อยไปหามาก (A ถึง Z น้อยที่สุดไปหาใหญ่ที่สุด) หากต้องการเรียงลำดับค่าจากมากไปหาน้อยแทน คุณต้องระบุคีย์เวิร์ด DESC

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับส่วนคำสั่ง ORDER BY โปรดดูบทความส่วนคำสั่ง ORDER BY

การทำงานกับข้อมูลสรุป: GROUP BY และ HAVING clauses

บางครั้งคุณจำเป็นต้องทำงานกับข้อมูลสรุป เช่น ยอดขายรวมสำหรับเดือนนั้นหรือสินค้าที่แพงที่สุดในสต็อก เมื่อต้องการทำเช่นนี้ ส่วนคำสั่ง SELECT จะใช้ฟังก์ชันการรวมกับฟิลด์ ตัวอย่างเช่น หากคุณต้องเรียกใช้แบบสอบถามเพื่อรับจำนวนที่อยู่อีเมลสำหรับแต่ละบริษัท ส่วนคำสั่ง SELECT อาจมีลักษณะดังนี้:

ความสามารถในการใช้ฟังก์ชันการรวมเฉพาะนั้นขึ้นอยู่กับประเภทของข้อมูลในเขตข้อมูลและนิพจน์ที่ต้องการ สำหรับข้อมูลเพิ่มเติมเกี่ยวกับฟังก์ชันการรวมที่มีอยู่ โปรดดูที่ฟังก์ชันทางสถิติของ SQL

การระบุฟิลด์ที่ไม่ได้ใช้ในฟังก์ชันการรวม: GROUP BY clause

เมื่อใช้ฟังก์ชันรวม คุณจะต้องสร้างส่วนคำสั่ง GROUP BY ส่วนคำสั่ง GROUP BY ระบุฟิลด์ทั้งหมดที่ไม่ได้ใช้ฟังก์ชันการรวม ถ้าฟังก์ชันรวมใช้กับทุกฟิลด์ในแบบสอบถาม คุณไม่จำเป็นต้องสร้างส่วนคำสั่ง GROUP BY

GROUP BY clause ต้องตามหลัง WHERE หรือ FROM clause ทันที หากไม่มี WHERE clause ส่วนคำสั่ง GROUP BY แสดงรายการฟิลด์ในลำดับเดียวกันกับส่วนคำสั่ง SELECT

เรามาต่อจากตัวอย่างก่อนหน้านี้ ในส่วนคำสั่ง SELECT หากฟังก์ชันการรวมใช้กับฟิลด์ [ที่อยู่อีเมล] เท่านั้น ส่วนคำสั่ง GROUP BY จะมีลักษณะดังนี้:

จัดกลุ่มตามบริษัท

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับส่วนคำสั่ง GROUP BY โปรดดูบทความส่วนคำสั่ง GROUP BY

การจำกัดค่ารวมโดยใช้เงื่อนไขการจัดกลุ่ม: ส่วนคำสั่ง HAVING

หากคุณต้องการระบุเงื่อนไขเพื่อจำกัดผลลัพธ์ แต่มีการใช้ฟิลด์ที่คุณต้องการนำไปใช้ ฟังก์ชันรวมไม่สามารถใช้คำสั่ง WHERE ได้ ควรใช้ประโยค HAVING แทน ส่วนคำสั่ง HAVING ทำงานเหมือนกับส่วนคำสั่ง WHERE แต่ใช้สำหรับข้อมูลที่รวบรวมไว้

ตัวอย่างเช่น สมมติว่าฟังก์ชัน AVG (ซึ่งคำนวณค่าเฉลี่ย) ถูกนำไปใช้กับฟิลด์แรกในส่วนคำสั่ง SELECT:

เลือก COUNT() บริษัท

หากคุณต้องการจำกัดผลลัพธ์คิวรีตามค่าของฟังก์ชัน COUNT คุณจะไม่สามารถใช้เงื่อนไขการเลือกกับฟิลด์นี้ในส่วนคำสั่ง WHERE ได้ ควรวางเงื่อนไขไว้ใน HAVING clause แทน ตัวอย่างเช่น หากคุณต้องการให้แบบสอบถามของคุณส่งคืนแถวเฉพาะในกรณีที่บริษัทมีที่อยู่อีเมลหลายรายการ คุณสามารถใช้ส่วนคำสั่ง HAVING ต่อไปนี้:

มี COUNT()>1

บันทึก:แบบสอบถามสามารถมีทั้งส่วนคำสั่ง WHERE และส่วนคำสั่ง HAVING โดยมีเงื่อนไขการเลือกสำหรับเขตข้อมูลที่ไม่ได้ใช้ ฟังก์ชันทางสถิติจะถูกระบุไว้ในส่วนคำสั่ง WHERE และเงื่อนไขสำหรับฟิลด์ที่ใช้ในฟังก์ชันทางสถิติจะถูกระบุในส่วนคำสั่ง HAVING

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับส่วนคำสั่ง HAVING โปรดดูบทความส่วนคำสั่ง HAVING

การรวมผลลัพธ์แบบสอบถาม: ตัวดำเนินการ UNION

ตัวดำเนินการ UNION ใช้ในการดูข้อมูลทั้งหมดที่ส่งคืนโดยแบบสอบถามแบบใช้เลือกข้อมูลที่คล้ายกันหลายรายการพร้อมกันเป็นชุดที่รวมกัน

ตัวดำเนินการ UNION ช่วยให้คุณสามารถรวมคำสั่ง SELECT สองคำสั่งให้เป็นคำสั่งเดียวได้ ต้องมีคำสั่ง SELECT ที่จะรวม หมายเลขเดียวกันและลำดับของฟิลด์เอาต์พุตที่มีชนิดข้อมูลเดียวกันหรือเข้ากันได้ เมื่อดำเนินการค้นหา ข้อมูลจากแต่ละชุดของฟิลด์ที่ตรงกันจะถูกรวมเข้าเป็นฟิลด์เอาต์พุตเดียว ดังนั้นเอาต์พุตของการสืบค้นจะมีฟิลด์มากเท่ากับแต่ละคำสั่ง SELECT แต่ละรายการ

บันทึก:ในแบบสอบถามแบบรวม ชนิดข้อมูลตัวเลขและข้อความจะเข้ากันได้

เมื่อใช้ตัวดำเนินการ UNION คุณสามารถระบุว่าควรรวมแถวที่ซ้ำกัน (ถ้ามี) ไว้ในผลลัพธ์ของคิวรีหรือไม่ เมื่อต้องการทำเช่นนี้ ให้ใช้คำสำคัญทั้งหมด

แบบสอบถามเพื่อรวมคำสั่ง SELECT สองคำสั่งมีไวยากรณ์พื้นฐานดังต่อไปนี้:

เลือก field_1
จากตาราง_1
ยูเนี่ยน
เลือก field_a
จาก table_a
;

ตัวอย่างเช่น สมมติว่าคุณมีตารางสองตารางชื่อ "ผลิตภัณฑ์" และ "บริการ" ทั้งสองตารางประกอบด้วยช่องที่มีชื่อผลิตภัณฑ์หรือบริการ ข้อมูลราคาและการรับประกัน รวมถึงช่องที่บ่งบอกถึงความพิเศษเฉพาะของผลิตภัณฑ์หรือบริการที่นำเสนอ แม้ว่าตาราง "ผลิตภัณฑ์" และ "บริการ" จะมีให้ก็ตาม ประเภทต่างๆการรับประกัน ข้อมูลพื้นฐานจะเหมือนกัน (ไม่ว่าผลิตภัณฑ์หรือบริการบางอย่างจะมีการรับประกันคุณภาพก็ตาม) คุณสามารถใช้แบบสอบถามรวมต่อไปนี้เพื่อรวมสี่เขตข้อมูลจากสองตาราง:

เลือกชื่อ, ราคา, Warranty_available, Exclusive_offer
จากผลิตภัณฑ์
ยูเนี่ยนทั้งหมด
เลือกชื่อ, ราคา, การรับประกัน_พร้อมใช้งาน, ข้อเสนอพิเศษ_ข้อเสนอ
จากบริการ
;

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับการรวมคำสั่ง SELECT โดยใช้ตัวดำเนินการ UNION โปรดดู

เมื่อย้ายจาก MS SQL ไปยัง MySQL นอกเหนือจากการย้ายข้อมูลแล้ว คุณต้องย้ายรหัสแอปพลิเคชันที่อยู่ในฐานข้อมูลด้วย

ก่อนหน้านี้เราได้กล่าวถึงวิธีการใช้เครื่องมือ WorkSQL Workbench

ในส่วนหนึ่งของการย้ายข้อมูล จะแปลงเฉพาะตารางและคัดลอกข้อมูล แต่จะไม่แปลงทริกเกอร์ มุมมอง หรือขั้นตอนการจัดเก็บ คุณต้องแปลงเป็นฐานข้อมูล MySQL ด้วยตนเอง

หากต้องการทำการแปลงด้วยตนเอง คุณต้องเข้าใจความแตกต่างพื้นฐานระหว่างคำสั่ง MS SQL และ MySQL

ระหว่างที่ฉันกลับใจใหม่จาก ไมโครซอฟต์ เอสคิวแอลจากเซิร์ฟเวอร์ไปยังฐานข้อมูล MySQL ฉันเจอคำสั่ง MS SQL และการสืบค้นต่อไปนี้ซึ่งเข้ากันไม่ได้กับ MySQL และฉันต้องแปลงคำสั่งดังต่อไปนี้

1. การสร้างขั้นตอนการจัดเก็บ ไวยากรณ์

ไวยากรณ์พื้นฐานสำหรับการสร้างกระบวนงานที่เก็บไว้จะแตกต่างกัน

MS SQL Stored, ไวยากรณ์การสร้างโพรซีเดอร์:

สร้างขั้นตอน @someString VarChar(150) As BEGIN -- คำสั่ง Sql อยู่ที่นี่ END

สำหรับ MySQL ไวยากรณ์สำหรับการสร้างขั้นตอนคือ:

สร้างขั้นตอนที่เก็บไว้ProcedureName (ใน someString VarChar (150)) BEGIN -- แบบสอบถาม Sql อยู่ที่นี่ END

2. การสร้างตารางชั่วคราว

ในโค้ด MS SQL ฉันได้สร้างตารางชั่วคราวหลายตารางที่จำเป็นสำหรับแอปพลิเคชัน ไวยากรณ์สำหรับการสร้างตารางชั่วคราวจะแตกต่างกันไปตามที่แสดงด้านล่าง

ไวยากรณ์ MS SQL สำหรับการสร้างตารางชั่วคราว:

สร้างตาราง #tableName(emp_id VARCHAR(10)COLLATE Database_Default คีย์หลัก, emp_Name VARCHAR(50) COLLATE Database_Default, emp_Code VARCHAR(30) COLLATE Database_Default, emp_Department VARCHAR(30) COLLATE Database_Default)

ไวยากรณ์ MySQL สำหรับการสร้างตารางชั่วคราวคือ:

สร้างตารางชั่วคราว tableName(emp_id VARCHAR(10), emp_Name VARCHAR(50), emp_Code VARCHAR(30), emp_Department VARCHAR(30));

3. ถ้าไวยากรณ์

ฉันได้ใช้เงื่อนไขหลายประการในขั้นตอนการจัดเก็บและทริกเกอร์ซึ่งไม่ทำงานหลังจากแปลงเป็น MySQL เนื่องจากไวยากรณ์แตกต่างออกไปดังที่แสดงด้านล่าง

MS SQL IF ไวยากรณ์เงื่อนไข:

If(@intSomeVal="") BEGIN SET @intSomeVal=10 END

MySQL IF ไวยากรณ์เงื่อนไข:

ถ้า @intSomeVal=""แล้วตั้งค่า @intSomeVal=10; เอนดิฟ;

4. หากสถานะมีอยู่

การใช้งานทั่วไปอีกอย่างหนึ่งคือ หากเป็นเงื่อนไข เพื่อตรวจสอบว่าแบบสอบถามส่งคืนแถวใดๆ หรือไม่ และถ้ามันส่งคืนหลายแถว ให้ทำอะไรสักอย่าง สำหรับสิ่งนี้ ฉันใช้ IF EXISTS ใน MS SQL ซึ่งจำเป็นต้องแปลงเป็นคำสั่ง MySQL IF ตามที่อธิบายไว้ด้านล่าง

MS SQL ถ้าออกตัวอย่าง:

หากมีอยู่ (เลือก 1 จาก #tableName พร้อม (NOLOCK) โดยที่ ColName="empType") BEGIN -- คำสั่ง Sql อยู่ที่นี่ END

MySQL เทียบเท่ากับที่กล่าวมาข้างต้น โดยใช้เมื่อตรงตามเงื่อนไข:

IF(SELECT count(*) FROM tableName WHERE ColName="empType") > 0 THEN -- คำสั่ง SQL อยู่ที่นี่ END IF;

5. ฟังก์ชั่นวันที่

การใช้ฟังก์ชันข้อมูลภายใน Stored Procedure เป็นเรื่องปกติ ตารางต่อไปนี้แสดงความแตกต่างระหว่าง MS SQL และ ข้อมูลมายเอสคิวแอล, ฟังก์ชันที่เกี่ยวข้อง

เอ็มเอส SQL เซิร์ฟเวอร์เซิร์ฟเวอร์ MySQL
รับวันที่()ตอนนี้()
SYSDATE()
CURRENT_TIMESTAMP()
GETDATE() + 1ตอนนี้() + ช่วงเวลา 1 วัน
CURRENT_TIMESTAMP +ช่วงเวลา 1 วัน
DATEADD(dd, -1, GETDATE())เพิ่ม(ตอนนี้() ช่วงเวลา -1 วัน)
แปลง(VARCHAR(19),GETDATE())DATE_FORMAT(ตอนนี้(),’%b %d %Y %h:%i %p’)
แปลง(VARCHAR(10),GETDATE(),110)DATE_FORMAT(ตอนนี้(),’%m-%d-%Y’)
แปลง(VARCHAR(24),GETDATE(),113)DATE_FORMAT(ตอนนี้(),’%d %b %Y %T:%f’)
แปลง(VARCHAR(11),GETDATE(),6)DATE_FORMAT(ตอนนี้(),’%d %b %y’)

6. การประกาศตัวแปร

ใน MS SQL Stored Procedure คุณสามารถประกาศตัวแปรระหว่าง “Begin” และ “end” ได้

อย่างไรก็ตาม ใน MySql คุณจะต้องประกาศหลังจากประกาศขั้นตอนการจัดเก็บ "เริ่มต้น" เท่านั้น ไม่อนุญาตให้ประกาศตัวแปร ณ จุดใดจุดหนึ่งระหว่างนั้น

7. เลือกระเบียน N แรก

ใน MS SQL คุณจะใช้ SELECT, TOP หากคุณต้องการเลือกเพียงสองสามระเบียนแรก ตัวอย่างเช่น หากต้องการเลือก 10 เรคคอร์ดแรก คุณจะต้องดำเนินการดังต่อไปนี้:

เลือก 10 อันดับแรก * จากตาราง;

ใน MySQL คุณจะต้องใช้ LIMIT แทน TOP ดังที่แสดงด้านล่าง

SELECT * จากตารางจำกัด 10;

8. แปลงจำนวนเต็มเป็นถ่าน

ใน MS SQL คุณจะทำ ขั้นตอนต่อไป(แปลงฟังก์ชัน) เพื่อแปลงจำนวนเต็มให้เป็นอักขระ

แปลง (VARCHAR (50), IntVal บางส่วน)

ใน MySQL คุณจะใช้ฟังก์ชัน CAST เพื่อแปลงจำนวนเต็มเป็นอักขระ ดังที่แสดงด้านล่าง

นักแสดง (IntVal บางส่วนเป็น CHAR)

9. ตัวดำเนินการต่อข้อมูล

หากคุณกำลังจัดการข้อมูลจำนวนมากภายใน Stored Procedure คุณอาจต้องการใช้การต่อสตริงบางส่วน

ใน MS SQL ตัวดำเนินการต่อข้อมูล + สัญลักษณ์ ตัวอย่างของการใช้งานดังกล่าวแสดงไว้ด้านล่าง

SET @someString = "%|" + @someStringVal + "|%"

ใน MySQL หากคุณใช้โหมด AnSi ก็จะเหมือนกับใน MS SQL เหล่านั้น. สัญลักษณ์ + จะใช้สำหรับการต่อข้อมูล

แต่ในโหมดเริ่มต้นใน MySQL เราต้องใช้ฟังก์ชัน CONCAT(“str1”, “str2”, “str3”.. “strN”)

SET someString = CONCAT("%|", someStringVal, "|%");

ในส่วนแรก เราได้สัมผัสภาษา DML เพียงเล็กน้อยแล้ว โดยใช้คำสั่งเกือบทั้งหมด ยกเว้นคำสั่ง MERGE

ฉันจะพูดถึง DML ตามลำดับของฉันเองซึ่งพัฒนาจากประสบการณ์ส่วนตัว ระหว่างทาง ฉันจะพยายามพูดถึงสถานที่ที่ "ลื่น" ที่ควรค่าแก่การมุ่งเน้น สถานที่ "ลื่น" เหล่านี้มีความคล้ายคลึงกันในภาษาท้องถิ่นหลายภาษาของ SQL

เพราะ หนังสือเรียนนี้มีไว้สำหรับผู้อ่านที่หลากหลาย (ไม่เพียง แต่โปรแกรมเมอร์เท่านั้น) ดังนั้นบางครั้งคำอธิบายก็เหมาะสมเช่น ยาวและน่าเบื่อ นี่คือวิสัยทัศน์ของฉันเกี่ยวกับเนื้อหา ซึ่งส่วนใหญ่ได้รับในทางปฏิบัติอันเป็นผลมาจากกิจกรรมทางวิชาชีพ

เป้าหมายหลักของบทช่วยสอนนี้ทีละขั้นตอนคือการพัฒนาความเข้าใจที่สมบูรณ์ในสาระสำคัญของภาษา SQL และสอนวิธีใช้โครงสร้างอย่างถูกต้อง ผู้เชี่ยวชาญในสาขานี้อาจสนใจที่จะอ่านเนื้อหานี้ บางทีพวกเขาอาจจะสามารถเรียนรู้สิ่งใหม่ๆ สำหรับตัวเอง หรือบางทีมันอาจจะมีประโยชน์ในการอ่านเพื่อฟื้นฟูความทรงจำ ฉันหวังว่าทุกคนจะพบว่ามันน่าสนใจ

เพราะ DML ในภาษาถิ่นฐานข้อมูล MS SQL มีความสัมพันธ์อย่างใกล้ชิดกับไวยากรณ์ของโครงสร้าง SELECT ดังนั้นฉันจะเริ่มพูดถึง DML ด้วย ในความคิดของฉัน โครงสร้าง SELECT เป็นโครงสร้างที่สำคัญที่สุดในภาษา DML เพราะ เนื่องจากข้อมูลหรือชิ้นส่วนข้อมูลที่จำเป็นจึงถูกดึงมาจากฐานข้อมูล

ภาษา DML มีโครงสร้างดังต่อไปนี้:

  • เลือก – การเลือกข้อมูล
  • INSERT – การแทรกข้อมูลใหม่
  • อัปเดต – อัปเดตข้อมูล
  • DELETE – การลบข้อมูล
  • MERGE – การรวมข้อมูล

ในส่วนนี้ เราจะดูเฉพาะไวยากรณ์พื้นฐานของคำสั่ง SELECT ซึ่งมีลักษณะดังนี้:

เลือก column_list หรือ * จากแหล่งที่มา โดยที่ตัวกรอง ORDER BY sort_expression
หัวข้อของคำสั่ง SELECT นั้นกว้างมาก ดังนั้นในส่วนนี้ ฉันจะเน้นเฉพาะโครงสร้างพื้นฐานเท่านั้น ฉันเชื่อว่าหากไม่รู้พื้นฐานดีพอ คุณจะไม่สามารถเริ่มศึกษาโครงสร้างที่ซับซ้อนกว่านี้ได้ เพราะ... จากนั้นทุกอย่างจะหมุนรอบการออกแบบพื้นฐานนี้ (แบบสอบถามย่อย การรวม ฯลฯ)

นอกจากนี้ ในส่วนนี้ ฉันจะพูดถึงข้อเสนอ TOP ด้วย ฉันไม่ได้ตั้งใจระบุประโยคนี้ในรูปแบบพื้นฐานเพราะ... มันถูกนำไปใช้แตกต่างกันในภาษา SQL ที่ต่างกัน

หากภาษา DDL มีความคงที่มากกว่านี้ เช่น ด้วยความช่วยเหลือ โครงสร้างที่เข้มงวดจะถูกสร้างขึ้น (ตาราง ความสัมพันธ์ ฯลฯ) จากนั้นภาษา DML มีลักษณะเป็นไดนามิก ที่นี่คุณจะได้รับผลลัพธ์ที่ถูกต้องในรูปแบบต่างๆ

การฝึกอบรมจะดำเนินต่อไปในโหมดทีละขั้นตอน เช่น เมื่ออ่านคุณควรพยายามทำตัวอย่างด้วยมือของคุณเองทันที จากนั้นคุณวิเคราะห์ผลลัพธ์ที่ได้รับและพยายามทำความเข้าใจอย่างสังหรณ์ใจ หากมีบางสิ่งยังไม่ชัดเจน เช่น ความหมายของฟังก์ชัน ให้ขอความช่วยเหลือจากอินเทอร์เน็ต

ตัวอย่างจะแสดงอยู่ในฐานข้อมูล Test ซึ่งสร้างขึ้นโดยใช้ DDL+DML ในส่วนแรก

สำหรับผู้ที่ไม่ได้สร้างฐานข้อมูลในส่วนแรก (เนื่องจากไม่ใช่ทุกคนอาจสนใจภาษา DDL) จึงสามารถใช้สคริปต์ต่อไปนี้:

ทดสอบสคริปต์สร้างฐานข้อมูล

การสร้างฐานข้อมูล CREATE DATABASE Test GO -- ทำให้ฐานข้อมูล Test ปัจจุบัน USE Test GO -- สร้างตารางอ้างอิง CREATE TABLE Positions(ID int IDENTITY(1,1) NOT NULL CONSTRAINT PK_Positions PRIMARY KEY, Name nvarchar(30) NOT NULL) CREATE แผนกของตาราง (ID int IDENTITY(1,1) NOT NULL CONSTRAINT PK_Departments PRIMARY KEY, Name nvarchar(30) NOT NULL) GO -- กรอกตารางอ้างอิงด้วยข้อมูล SET IDENTITY_INSERT Positions ON INSERT Positions(ID,Name)VALUES (1, N"นักบัญชี" ), (2,N"ผู้อำนวยการ"), (3,N"โปรแกรมเมอร์"), (4,N"โปรแกรมเมอร์อาวุโส") SET IDENTITY_INSERT Positions OFF GO SET IDENTITY_INSERT Departments ON INSERT Departments(ID,Name)VALUES (1,N "การบริหาร"), (2,N"การบัญชี"), (3,N"IT") SET IDENTITY_INSERT แผนก OFF GO -- สร้างตารางที่มีพนักงาน สร้างตาราง พนักงาน(ID int NOT NULL, ชื่อ nvarchar( 30), วันเกิด, อีเมล nvarchar(30), PositionID int, DepartmentID int, HireDate date NOT NULL CONSTRAINT DF_Employees_HireDate DEFAULT SYSDATETIME(), ManagerID int, CONSTRAINT PK_Employees PRIMARY KEY (ID), CONSTRAINT FK_Employees_DepartmentID FOREIGN KEY(DepartmentID) REFERENCES ( ID), TRAINT FK_Employees_PositionID คีย์ต่างประเทศ (ID ตำแหน่ง) ตำแหน่งอ้างอิง (ID), CONSTRAINT FK_Employees_ManagerID คีย์ต่างประเทศ (ID ผู้จัดการ) อ้างอิงพนักงาน (ID), CONSTRAINT UQ_Employees_Email UNIQUE (อีเมล), CONSTRAINT CK_Employees_ID CHECK (ID ระหว่าง 100 0 และ 1999), INDEX IDX_Emplo yes_Name (ชื่อ)) ไป - - กรอกข้อมูลด้วยข้อมูล INSERT Employees (ID,Name,Birthday,Email,PositionID,DepartmentID,ManagerID)VALUES (1,000,N"Ivanov I.I.","19550219"," [ป้องกันอีเมล]",2,1,NULL), (1001,N"เปตรอฟ พี.พี.","19831203"," [ป้องกันอีเมล]",3,3,1003), (1002,N"Sidorov S.S.","19760607"," [ป้องกันอีเมล]",1,2,1000), (1003,น"อันดรีฟ เอ.เอ.","19820417"," [ป้องกันอีเมล]",4,3,1000)

เพียงเท่านี้เราก็พร้อมที่จะเริ่มเรียนรู้ภาษา DML แล้ว

SELECT – ตัวดำเนินการเลือกข้อมูล

ก่อนอื่น สำหรับตัวแก้ไขแบบสอบถามที่ใช้งานอยู่ ให้ทำการทดสอบฐานข้อมูลปัจจุบันโดยเลือกฐานข้อมูลในรายการแบบเลื่อนลงหรือใช้คำสั่ง "USE Test"

เริ่มจากรูปแบบพื้นฐานที่สุดของ SELECT:

เลือก * จากพนักงาน
ในแบบสอบถามนี้ เราขอให้ส่งคืนคอลัมน์ทั้งหมด (ระบุด้วย "*") จากตารางพนักงาน - คุณสามารถอ่านได้ว่า "เลือก all_fields จากตารางพนักงาน" หากมีดัชนีแบบคลัสเตอร์ข้อมูลที่ส่งคืนมักจะเรียงลำดับตามนั้น ในกรณีนี้ตามคอลัมน์ ID (แต่สิ่งนี้ไม่สำคัญเนื่องจากในกรณีส่วนใหญ่เราจะระบุการเรียงลำดับอย่างชัดเจนโดยใช้ ORDER BY ... ) : :

บัตรประจำตัวประชาชน ชื่อ วันเกิด อีเมล รหัสตำแหน่ง รหัสแผนก HireDate รหัสผู้จัดการ
1000 อีวานอฟ ไอ.ไอ. 1955-02-19 [ป้องกันอีเมล] 2 1 2015-04-08 โมฆะ
1001 เปตรอฟ พี.พี. 1983-12-03 [ป้องกันอีเมล] 3 3 2015-04-08 1003
1002 ซิโดรอฟ เอส.เอส. 1976-06-07 [ป้องกันอีเมล] 1 2 2015-04-08 1000
1003 Andreev A.A. 1982-04-17 [ป้องกันอีเมล] 4 3 2015-04-08 1000

โดยทั่วไป ควรกล่าวว่าในภาษาถิ่น MS SQL รูปแบบที่ง่ายที่สุดของแบบสอบถาม SELECT อาจไม่มีบล็อก FROM ซึ่งในกรณีนี้คุณสามารถใช้เพื่อรับค่าบางค่าได้:

SELECT 5550/100*15, SYSDATETIME() - รับวันที่ของระบบฐานข้อมูล SIN(0)+COS(0)

(ไม่มีชื่อคอลัมน์) (ไม่มีชื่อคอลัมน์) (ไม่มีชื่อคอลัมน์)
825 2015-04-11 12:12:36.0406743 1

โปรดทราบว่านิพจน์ (5550/100*15) ให้ผลลัพธ์ 825 แม้ว่าเราจะคำนวณด้วยเครื่องคิดเลข ค่าก็จะเป็น (832.5) ผลลัพธ์ที่ได้คือ 825 เนื่องจากในนิพจน์ของเราตัวเลขทั้งหมดเป็นจำนวนเต็ม ดังนั้นผลลัพธ์จึงเป็นจำนวนเต็ม เช่น (5550/100) ให้ 55 ไม่ใช่ (55.5)

โปรดจำไว้ว่าตรรกะต่อไปนี้ใช้งานได้ใน MS SQL:

  • จำนวนเต็ม / จำนวนเต็ม = จำนวนเต็ม (เช่น ในกรณีนี้เกิดการหารจำนวนเต็ม)
  • จริง / จำนวนเต็ม = จริง
  • จำนวนเต็ม / จริง = จริง
เหล่านั้น. ผลลัพธ์จะถูกแปลงเป็นประเภทที่ใหญ่กว่า ดังนั้นใน 2 กรณีสุดท้าย เราได้จำนวนจริง (คิดเหมือนในคณิตศาสตร์ - ช่วงของจำนวนจริงมากกว่าช่วงของจำนวนเต็ม ดังนั้นผลลัพธ์จึงถูกแปลงเป็นค่านั้น):

เลือก 123/10, -- 12 123./10, -- 12.3 123/10 --12.3
ในที่นี้ (123.) = (123.0) ในกรณีนี้ 0 สามารถละทิ้งได้ และเหลือเพียงจุดเท่านั้น

ตรรกะเดียวกันนี้ใช้กับการดำเนินการทางคณิตศาสตร์อื่นๆ แต่ในกรณีของการหาร ความแตกต่างนี้จะมีความเกี่ยวข้องมากกว่า

ดังนั้นควรคำนึงถึงชนิดข้อมูลของคอลัมน์ตัวเลขด้วย หากเป็นจำนวนเต็มและคุณต้องการผลลัพธ์ที่แท้จริง ให้ใช้การแปลงหรือใส่จุดหลังตัวเลขที่ระบุเป็นค่าคงที่ (123.)

คุณสามารถใช้ฟังก์ชัน CAST หรือ CONVERT เพื่อแปลงฟิลด์ได้ ตัวอย่างเช่น ลองใช้ช่อง ID ซึ่งเป็นประเภท int:

SELECT ID, ID/100, -- การหารจำนวนเต็มจะเกิดขึ้นที่นี่ CAST(ID AS float)/100 -- ใช้ฟังก์ชัน CAST เพื่อแปลงเป็นประเภท float CONVERT(float,ID)/100 -- ใช้ฟังก์ชัน CONVERT เพื่อแปลงเป็นประเภท float ID/100 -- ใช้การแปลงโดยระบุว่าตัวส่วนเป็นจำนวนจริงจากพนักงาน

บัตรประจำตัวประชาชน (ไม่มีชื่อคอลัมน์) (ไม่มีชื่อคอลัมน์) (ไม่มีชื่อคอลัมน์) (ไม่มีชื่อคอลัมน์)
1000 10 10 10 10.000000
1001 10 10.01 10.01 10.010000
1002 10 10.02 10.02 10.020000
1003 10 10.03 10.03 10.030000

เพียงแค่บันทึกในฐานข้อมูล ORACLE ไม่สามารถยอมรับไวยากรณ์ที่ไม่มีบล็อก FROM ได้ เพื่อจุดประสงค์นี้ จะใช้ตารางระบบ DUAL ซึ่งมีหนึ่งบรรทัด:

SELECT 5550/100*15, -- และใน ORACLE ผลลัพธ์จะเท่ากับ 832.5 sysdate, sin(0)+cos(0) FROM DUAL


บันทึก.ชื่อตารางใน RDB หลายรายการอาจนำหน้าด้วยชื่อสคีมา:

SELECT * FROM dbo.Employees -- dbo – ชื่อสคีมา

สคีมาเป็นหน่วยทางลอจิคัลของฐานข้อมูลซึ่งมีชื่อเป็นของตัวเอง และช่วยให้คุณสามารถจัดกลุ่มอ็อบเจ็กต์ฐานข้อมูล เช่น ตาราง มุมมอง ฯลฯ ภายในตัวมันเองได้

คำจำกัดความของสคีมาในฐานข้อมูลที่แตกต่างกันอาจแตกต่างกัน ในบางกรณี สคีมาจะเกี่ยวข้องโดยตรงกับผู้ใช้ฐานข้อมูล เช่น ในกรณีนี้ เราสามารถพูดได้ว่าสคีมาและผู้ใช้เป็นคำพ้องความหมาย และวัตถุทั้งหมดที่สร้างขึ้นในสคีมานั้นเป็นวัตถุของผู้ใช้รายนี้ ใน MS SQL สคีมาเป็นหน่วยลอจิคัลอิสระที่สามารถสร้างได้ด้วยตัวเอง (ดู CREATE SCHEMA)

ตามค่าเริ่มต้น สคีมาหนึ่งจะถูกสร้างขึ้นในฐานข้อมูล MS SQL ด้วยชื่อ dbo (เจ้าของฐานข้อมูล) และออบเจ็กต์ที่สร้างขึ้นทั้งหมดจะถูกสร้างขึ้นตามค่าเริ่มต้นในสคีมานี้ ดังนั้น หากเราระบุชื่อของตารางในการสืบค้น ตารางนั้นก็จะถูกค้นหาใน dbo schema ของฐานข้อมูลปัจจุบัน หากเราต้องการสร้างวัตถุในสคีมาเฉพาะ เราจะต้องเติมชื่อวัตถุด้วยชื่อสคีมา เช่น “CREATE TABLE schema_name.table_name(...)”

ในกรณีของ MS SQL ชื่อสคีมาอาจนำหน้าด้วยชื่อของฐานข้อมูลที่มีสคีมาอยู่:

เลือก * จาก Test.dbo.Employees --database_name.schema_name.table
คำชี้แจงนี้จะมีประโยชน์ ตัวอย่างเช่น หาก:

  • ในคำขอเดียว เราเข้าถึงออบเจ็กต์ที่อยู่ในสคีมาหรือฐานข้อมูลที่แตกต่างกัน
  • คุณต้องถ่ายโอนข้อมูลจากสคีมาหรือฐานข้อมูลหนึ่งไปยังอีกสคีมาหรือฐานข้อมูลอื่น
  • เมื่ออยู่ในฐานข้อมูลเดียว คุณจะต้องขอข้อมูลจากฐานข้อมูลอื่น
  • ฯลฯ
สคีมาเป็นเครื่องมือที่สะดวกมากซึ่งมีประโยชน์ในการพัฒนาสถาปัตยกรรมฐานข้อมูล โดยเฉพาะฐานข้อมูลขนาดใหญ่

นอกจากนี้ อย่าลืมว่าในข้อความคำขอ เราสามารถใช้ความคิดเห็นทั้งบรรทัดเดียว “-- ... ” และความคิดเห็นหลายบรรทัด “/* ... */” หากคำขอมีขนาดใหญ่และซับซ้อน ความคิดเห็นสามารถช่วยให้คุณหรือบุคคลอื่นจดจำหรือเข้าใจโครงสร้างของคำขอได้อย่างมาก

หากมีคอลัมน์จำนวนมากในตาราง และโดยเฉพาะอย่างยิ่งหากยังมีแถวจำนวนมากในตาราง บวกกับหากเรากำลังทำการสืบค้นไปยังฐานข้อมูลผ่านเครือข่าย ก็ควรจะเลือกด้วยรายการโดยตรงของ ฟิลด์ที่คุณต้องการ คั่นด้วยเครื่องหมายจุลภาค:

เลือก ID ชื่อจากพนักงาน

เหล่านั้น. ที่นี่เราบอกว่าเราเพียงต้องส่งคืนฟิลด์ ID และชื่อจากตารางเท่านั้น ผลลัพธ์จะเป็นดังนี้ (โดยวิธีการเพิ่มประสิทธิภาพที่นี่ตัดสินใจใช้ดัชนีที่สร้างโดยฟิลด์ชื่อ):

บัตรประจำตัวประชาชน ชื่อ
1003 Andreev A.A.
1000 อีวานอฟ ไอ.ไอ.
1001 เปตรอฟ พี.พี.
1002 ซิโดรอฟ เอส.เอส.

เพียงแค่บันทึกบางครั้งการดูวิธีการดึงข้อมูลอาจมีประโยชน์ เช่น การค้นหาว่ามีการใช้ดัชนีใดบ้าง สามารถทำได้โดยคลิกปุ่ม “แสดงแผนการดำเนินการโดยประมาณ” หรือตั้งค่า “รวมแผนการดำเนินการจริง - รวมแผนการดำเนินการแบบสอบถามจริงในผลลัพธ์” (ในกรณีนี้เราจะเห็นแผนจริงตามลำดับเท่านั้น หลังจากดำเนินการตามคำขอแล้ว):

การวิเคราะห์แผนการดำเนินการมีประโยชน์มากเมื่อปรับแบบสอบถามให้เหมาะสม ช่วยให้คุณค้นหาดัชนีที่ขาดหายไปหรือดัชนีใดที่ไม่ได้ใช้เลยและสามารถลบออกได้

หากคุณเพิ่งเริ่มเรียนรู้ DML ตอนนี้สิ่งนี้ไม่สำคัญสำหรับคุณ เพียงจดไว้และคุณสามารถลืมมันได้อย่างปลอดภัย (บางทีคุณอาจไม่ต้องการมันเลย) - เป้าหมายเริ่มแรกของเราคือการเรียนรู้พื้นฐานของภาษา DML และ เรียนรู้วิธีใช้อย่างถูกต้อง และการเพิ่มประสิทธิภาพเป็นศิลปะที่แยกจากกันอยู่แล้ว บางครั้ง สิ่งที่สำคัญกว่านั้นคือคุณเพียงแค่มีคำถามที่เขียนอย่างถูกต้องซึ่งส่งคืนผลลัพธ์ที่ถูกต้องจากมุมมองของหัวเรื่อง และบุคคลแต่ละคนก็ได้ปรับให้เหมาะสมแล้ว ขั้นแรก คุณต้องเรียนรู้วิธีเขียนแบบสอบถามอย่างถูกต้อง โดยใช้วิธีใดก็ได้เพื่อให้บรรลุเป้าหมาย เป้าหมายหลักที่คุณต้องบรรลุในตอนนี้คือเพื่อให้ข้อความค้นหาของคุณแสดงผลลัพธ์ที่ถูกต้อง

การตั้งค่านามแฝงของตาราง

เมื่อแสดงรายการคอลัมน์ สามารถนำหน้าด้วยชื่อของตารางที่อยู่ในบล็อก FROM:

เลือก Employees.ID, Employees.Name จากพนักงาน

แต่ไวยากรณ์นี้มักจะใช้งานไม่สะดวกเพราะว่า ชื่อตารางอาจยาวได้ เพื่อวัตถุประสงค์เหล่านี้ โดยปกติจะระบุและใช้ชื่อที่สั้นกว่า - นามแฝง:

เลือก emp.ID,emp.Name จากพนักงาน AS emp
หรือ

SELECT emp.ID,emp.Name จาก Employees emp -- สามารถละคีย์เวิร์ด AS ได้ (ฉันชอบตัวเลือกนี้มากกว่า)

emp ในที่นี้คือนามแฝงสำหรับตารางพนักงานที่สามารถใช้ในบริบทของคำสั่ง SELECT นี้ เหล่านั้น. เราสามารถพูดได้ว่าในบริบทของคำสั่ง SELECT นี้ เราจะตั้งชื่อใหม่ให้กับตาราง

แน่นอน ในกรณีนี้ ผลลัพธ์การสืบค้นจะเหมือนกับ "SELECT ID,Name FROM Employees" ทุกประการ เหตุใดจึงจำเป็นจะชัดเจนในภายหลัง (ไม่แม้แต่ในส่วนนี้) สำหรับตอนนี้เราเพียงจำไว้ว่าชื่อคอลัมน์สามารถนำหน้า (ชี้แจง) ได้โดยตรงด้วยชื่อตารางหรือใช้นามแฝง ที่นี่คุณสามารถใช้หนึ่งในสองสิ่งนั่นคือ หากคุณตั้งชื่อแทน คุณจะต้องใช้ชื่อนั้น แต่คุณไม่สามารถใช้ชื่อตารางได้อีกต่อไป

เพียงแค่บันทึกใน ORACLE อนุญาตเฉพาะตัวเลือกในการระบุนามแฝงของตารางโดยไม่มีคีย์เวิร์ด AS เท่านั้น

DISTINCT – ละทิ้งแถวที่ซ้ำกัน

คำสำคัญ DISTINCT ใช้เพื่อละทิ้งแถวที่ซ้ำกันออกจากผลลัพธ์แบบสอบถาม โดยคร่าวๆ ลองจินตนาการว่าดำเนินการค้นหาโดยไม่มีตัวเลือก DISTINCT ก่อน จากนั้นจึงละทิ้งรายการที่ซ้ำกันทั้งหมดออกจากผลลัพธ์ ให้เราสาธิตสิ่งนี้เพื่อความชัดเจนยิ่งขึ้นโดยใช้ตัวอย่าง:

มาสร้างตารางชั่วคราวสำหรับการสาธิตกันเถอะ สร้างตาราง #Trash(ID int NOT NULL PRIMARY KEY, Col1 varchar(10), Col2 varchar(10), Col3 varchar(10)) -- เติมตารางนี้ด้วยขยะทุกประเภท INSERT #Trash (ID,Col1, Col2,Col3)ค่า (1,"A", "A", "A"), (2, "A", "B", "C"), (3, "C" A", "B "), (4, "A", "A", "B"), (5, "B", "B", "B"), (6, "A", "A" ,"B") , (7,"A", "A", "A"), (8,"C", "A", "B"), (9,"C", "A" B"), ( 10,"A", "A", "B"), (11, "A", NULL, "B"), (12, "A", NULL, "B") - มาดูกัน สิ่งที่คำขอส่งคืนโดยไม่มีตัวเลือก DISTINCT SELECT Col1,Col2,Col3 FROM #Trash -- มาดูกันว่าแบบสอบถามส่งคืนอะไรด้วยตัวเลือก DISTINCT SELECT DISTINCT Col1,Col2,Col3 FROM #Trash -- ลบตารางชั่วคราว DROP TABLE #Trash

สายตาจะมีลักษณะเช่นนี้ (รายการที่ซ้ำกันทั้งหมดจะถูกทำเครื่องหมายด้วยสีเดียวกัน):

ตอนนี้เรามาดูกันว่าสิ่งนี้สามารถนำไปใช้ได้ที่ไหน โดยใช้ตัวอย่างที่เป็นประโยชน์มากขึ้น - เราจะส่งคืนเฉพาะตัวระบุแผนกที่ไม่ซ้ำกันจากตารางพนักงาน (เช่น เราจะค้นหา ID ของแผนกที่พนักงานลงทะเบียนไว้):

เลือก DepartmentID ที่แตกต่างจากพนักงาน

ที่นี่เรามี 4 บรรทัดเพราะ... ไม่มีชุดค่าผสมที่ซ้ำกัน (DepartmentID, PositionID) ในตารางของเรา

กลับมาที่ DDL กันสักครู่

เนื่องจากเราเริ่มจะหมดข้อมูลสำหรับตัวอย่างการสาธิต และเราต้องการพูดคุยให้ครอบคลุมและชัดเจนยิ่งขึ้น เรามาขยายตาราง Employess ของเรากันสักหน่อย นอกจากนี้ จำ DDL เล็กๆ น้อยๆ ดังที่พวกเขาพูดว่า “การทำซ้ำเป็นบ่อเกิดของการเรียนรู้” และอีกอย่าง เรามากระโดดไปข้างหน้าอีกครั้งและใช้คำสั่ง UPDATE:

เราสร้างคอลัมน์ใหม่ ALTER TABLE Employees ADD LastName nvarchar(30), -- นามสกุล FirstName nvarchar(30), -- ชื่อจริง MiddleName nvarchar(30), -- ชื่อกลาง เงินเดือนลอยตัว, -- และเงินเดือนแน่นอนในบางหน่วย BonusPercent float -- เปอร์เซ็นต์สำหรับการคำนวณโบนัสจากเงินเดือน GO -- กรอกข้อมูล (ข้อมูลบางส่วนถูกละเว้นโดยเจตนา) อัปเดตพนักงาน SET LastName=N"Ivanov", FirstName=N"Ivan", MiddleName=N"Ivanovich", เงินเดือน=5,000 เปอร์เซ็นต์โบนัส= 50 โดยที่ ID=1,000 -- Ivanov I.I. อัพเดท พนักงาน SET LastName=N"Petrov",FirstName=N"Petr",MiddleName=N"Petrovich", เงินเดือน=1500,BonusPercent= 15 WHERE ID=1001 -- Petrov P.P. อัปเดตพนักงาน SET LastName=N"Sidor",FirstName=N"Sidor",MiddleName=NULL, เงินเดือน=2500,BonusPercent=NULL WHERE ID=1002 -- Sidorov S.S. อัปเดตพนักงาน SET LastName=N"Andreev",FirstName=N"Andrey",MiddleName=NULL, เงินเดือน=2000,BonusPercent= 30 WHERE ID=1003 -- Andreev A.A.

ตรวจสอบให้แน่ใจว่าข้อมูลได้รับการอัปเดตเรียบร้อยแล้ว:

เลือก * จากพนักงาน

บัตรประจำตัวประชาชน ชื่อ นามสกุล ชื่อ ชื่อกลาง เงินเดือน โบนัสเปอร์เซ็นต์
1000 อีวานอฟ ไอ.ไอ. อีวานอฟ อีวาน อิวาโนวิช 5000 50
1001 เปตรอฟ พี.พี. เปตรอฟ ปีเตอร์ เปโตรวิช 1500 15
1002 ซิโดรอฟ เอส.เอส. ซิโดรอฟ ซีดอร์ โมฆะ 2500 โมฆะ
1003 Andreev A.A. อันดรีฟ อันเดรย์ โมฆะ 2000 30

การตั้งค่านามแฝงสำหรับคอลัมน์แบบสอบถาม

ฉันคิดว่าการแสดงที่นี่ง่ายกว่าการเขียน:

SELECT -- ตั้งชื่อให้กับคอลัมน์จากการคำนวณ LastName+" "+FirstName+" "+MiddleName AS Full Name -- ใช้เครื่องหมายคำพูดคู่ เนื่องจาก มีการใช้ช่องว่าง HireDate AS "วันที่รับ" -- การใช้วงเล็บเหลี่ยม เพราะ ใช้ช่องว่างวันเกิด AS [วันเกิด] -- คำว่า AS ไม่จำเป็น เงินเดือน ZP จากพนักงาน

ชื่อเต็ม วันที่รับสมัคร วันเกิด ซีพี
อีวานอฟ อีวาน อิวาโนวิช 2015-04-08 1955-02-19 5000
เปตรอฟ เปตรอฟ เปโตรวิช 2015-04-08 1983-12-03 1500
โมฆะ 2015-04-08 1976-06-07 2500
โมฆะ 2015-04-08 1982-04-17 2000

ดังที่เราเห็น นามแฝงของคอลัมน์ที่เราระบุจะแสดงอยู่ในส่วนหัวของตารางผลลัพธ์ จริงๆ แล้ว นี่คือจุดประสงค์หลักของชื่อแทนคอลัมน์

โปรดทราบ เพราะ. พนักงาน 2 คนสุดท้ายไม่ได้ระบุชื่อกลาง (ค่า NULL) ดังนั้นผลลัพธ์ของนิพจน์ “LastName+” "+FirstName+" "+MiddleName" ก็ส่งคืน NULL มาให้เราเช่นกัน

หากต้องการรวม (เพิ่ม, ต่อ) สตริงใน MS SQL จะใช้สัญลักษณ์ “+”

โปรดจำไว้ว่านิพจน์ทั้งหมดที่เกี่ยวข้องกับ NULL (เช่น หารด้วย NULL และบวกด้วย NULL) จะส่งคืนค่า NULL

เพียงแค่บันทึก
ในกรณีของ ORACLE ตัวดำเนินการ “||” จะใช้ในการเชื่อมสตริงเข้าด้วยกัน และการต่อข้อมูลจะเป็น "||FirstName||" สำหรับ ORACLE เป็นที่น่าสังเกตว่ามีข้อยกเว้นสำหรับประเภทสตริงสำหรับ NULL และสตริงว่าง "" เป็นสิ่งเดียวกันดังนั้นใน ORACLE นิพจน์ดังกล่าวจะกลับมาสำหรับพนักงาน 2 คนสุดท้าย "Sidorov Sidor" และ "Andrey" อันดรีฟ” เท่าที่ฉันรู้ในช่วงเวลาของ ORACLE 12c ไม่มีตัวเลือกที่จะเปลี่ยนแปลงพฤติกรรมนี้ (หากฉันผิด โปรดแก้ไขให้ฉันด้วย) ตรงนี้มันยากสำหรับฉันที่จะตัดสินว่าสิ่งนี้ดีหรือไม่ดี เพราะ... ในบางกรณี ลักษณะการทำงานของสตริง NULL จะสะดวกกว่า เช่น ใน MS SQL และในกรณีอื่นๆ เช่น ใน ORACLE

ใน ORACLE นามแฝงของคอลัมน์ทั้งหมดที่แสดงไว้ด้านบนก็ใช้ได้เช่นกัน ยกเว้น [...]


เพื่อไม่ให้รั้วการก่อสร้างโดยใช้ฟังก์ชัน ISNULL ใน MS SQL เราสามารถใช้ฟังก์ชัน CONCAT ได้ ลองพิจารณาและเปรียบเทียบ 3 ตัวเลือก:

SELECT LastName+" "+FirstName+" "+MiddleName FullName1, -- 2 ตัวเลือกสำหรับการแทนที่ NULL ด้วยสตริงว่าง "" (เราได้รับพฤติกรรมเช่นเดียวกับใน ORACLE) ISNULL(LastName,"")+" "+ISNULL(FirstName," ")+ " "+ISNULL(MiddleName,"") FullName2, CONCAT(LastName," ",FirstName," ",MiddleName) FullName3 จากพนักงาน

ชื่อเต็ม1 ชื่อเต็ม2 ชื่อเต็ม3
อีวานอฟ อีวาน อิวาโนวิช อีวานอฟ อีวาน อิวาโนวิช อีวานอฟ อีวาน อิวาโนวิช
เปตรอฟ เปตรอฟ เปโตรวิช เปตรอฟ เปตรอฟ เปโตรวิช เปตรอฟ เปตรอฟ เปโตรวิช
โมฆะ ซิโดรอฟ ซิดอร์ ซิโดรอฟ ซิดอร์
โมฆะ อันดรีฟ อันเดรย์ อันดรีฟ อันเดรย์

ใน MS SQL สามารถระบุนามแฝงได้โดยใช้เครื่องหมายเท่ากับ:

SELECT "Reception date"=HireDate, -- นอกเหนือจาก "..." และ […] คุณสามารถใช้ "..." [วันเกิด]=วันเกิด ZP=เงินเดือน จากพนักงาน

การใช้คีย์เวิร์ด AS หรือเครื่องหมายเท่ากับเพื่อระบุนามแฝงอาจเป็นเรื่องของรสนิยมมากกว่า แต่เมื่อวิเคราะห์คำขอของผู้อื่น ความรู้นี้จะมีประโยชน์

สุดท้ายนี้ฉันจะบอกว่าเป็นการดีกว่าที่จะตั้งชื่อนามแฝงโดยใช้เฉพาะตัวอักษรละตินและตัวเลขเพื่อหลีกเลี่ยงการใช้ “…”, “…” และ […] นั่นคือใช้กฎเดียวกันกับที่เราใช้เมื่อตั้งชื่อตาราง . นอกจากนี้ ในตัวอย่าง ฉันจะใช้เฉพาะชื่อดังกล่าวเท่านั้น และไม่มี “…”, “…” และ […]

ตัวดำเนินการทางคณิตศาสตร์ SQL พื้นฐาน


ลำดับความสำคัญในการดำเนินการของตัวดำเนินการทางคณิตศาสตร์จะเหมือนกับในคณิตศาสตร์ หากจำเป็น สามารถเปลี่ยนลำดับการใช้ตัวดำเนินการได้โดยใช้วงเล็บ - (a+b)*(x/(y-z))

และฉันขอย้ำอีกครั้งว่าการดำเนินการใด ๆ ที่ใช้ NULL จะสร้าง NULL เช่น: 10+NULL, NULL*15/3, 100/NULL - ทั้งหมดนี้จะส่งผลให้เป็น NULL เหล่านั้น. พูดง่ายๆ คือ ค่าที่ไม่ได้กำหนดไม่สามารถให้ผลลัพธ์ที่แน่นอนได้ คำนึงถึงสิ่งนี้เมื่อเขียนแบบสอบถามของคุณและหากจำเป็น ให้จัดการค่า NULL โดยใช้ฟังก์ชัน ISNULL และ COALESCE:

เลือก ID,ชื่อ, เงินเดือน/100*BonusPercent AS Result1, -- โดยไม่ต้องประมวลผลค่า NULL เงินเดือน/100*ISNULL(BonusPercent,0) AS Result2, -- ใช้ฟังก์ชัน ISNULL Salary/100*COALESCE(BonusPercent,0) AS Result3 - - ใช้ฟังก์ชัน COALESCE จากพนักงาน

ฉันจะบอกคุณเล็กน้อยเกี่ยวกับฟังก์ชัน COALESCE:

COALESCE (expr1, expr2, ..., exprn) - ส่งกลับค่าแรกที่ไม่ใช่ NULL จากรายการค่า

SELECT COALESCE(f1, f1*f2, f2*f3) val -- ในกรณีนี้ ค่าที่สามจะถูกส่งกลับจาก (SELECT null f1, 2 f2, 3 f3) q

ส่วนใหญ่ฉันจะมุ่งเน้นไปที่การพูดคุยเกี่ยวกับโครงสร้าง DML และส่วนใหญ่ ฉันจะไม่พูดถึงฟังก์ชันที่จะปรากฏในตัวอย่าง หากคุณไม่เข้าใจว่าฟังก์ชันใดทำหน้าที่อะไร ให้ค้นหาคำอธิบายบนอินเทอร์เน็ต คุณสามารถค้นหาข้อมูลตามกลุ่มของฟังก์ชันได้ในคราวเดียว เช่น โดยการค้นหาใน Google “ฟังก์ชันสตริง MS SQL”, “MS SQL ฟังก์ชันทางคณิตศาสตร์” หรือ “ฟังก์ชัน MS SQL” การประมวลผล NULL" มีข้อมูลมากมายเกี่ยวกับฟังก์ชันต่างๆ และคุณสามารถค้นหาได้ง่าย ตัวอย่างเช่น ในไลบรารี MSDN คุณสามารถดูข้อมูลเพิ่มเติมเกี่ยวกับฟังก์ชัน COALESCE ได้:

การตัดจาก MSDNการเปรียบเทียบ COALESCE และ CASE

นิพจน์ COALESCE เป็นทางลัดทางวากยสัมพันธ์สำหรับนิพจน์ CASE ซึ่งหมายความว่า COALESCE(expression1,...n) ถูกเขียนใหม่โดยเครื่องมือเพิ่มประสิทธิภาพคิวรีเป็นนิพจน์ CASE ต่อไปนี้:

กรณีที่ (expression1 ไม่เป็นโมฆะ) จากนั้น expression1 เมื่อ (expression2 ไม่เป็นโมฆะ) จากนั้น expression2 ... อื่น expressionN END

ตัวอย่างเช่น มาดูกันว่าคุณสามารถใช้ส่วนที่เหลือของการหาร (%) ได้อย่างไร โอเปอเรเตอร์นี้มีประโยชน์มากเมื่อคุณต้องการแบ่งบันทึกออกเป็นกลุ่ม ตัวอย่างเช่น ดึงพนักงานทั้งหมดที่มีหมายเลขบุคลากร (ID) ออกมา เช่น รหัสเหล่านั้นที่หารด้วย 2:

เลือก ID, ชื่อจากพนักงาน โดยที่ ID%2=0 -- เศษที่เหลือเมื่อหารด้วย 2 คือ 0

ORDER BY – การเรียงลำดับผลลัพธ์ของแบบสอบถาม

ส่วนคำสั่ง ORDER BY ใช้เพื่อเรียงลำดับผลลัพธ์ของแบบสอบถาม

SELECT LastName, FirstName, Salary FROM Employees ORDER BY LastName,FirstName -- เรียงลำดับผลลัพธ์เป็น 2 คอลัมน์ - ตามนามสกุล แล้วตามด้วยชื่อ

สำหรับบันทึกมีคีย์เวิร์ด ASC สำหรับการเรียงลำดับจากน้อยไปหามาก แต่เนื่องจากการเรียงลำดับจากน้อยไปมากเป็นค่าเริ่มต้น คุณจึงลืมตัวเลือกนี้ได้ (ฉันจำไม่ได้ว่าเคยใช้ตัวเลือกนี้เมื่อใด)

เป็นที่น่าสังเกตว่าคำสั่งย่อย ORDER BY ยังสามารถใช้ฟิลด์ที่ไม่อยู่ในรายการในส่วนคำสั่ง SELECT ได้ (ยกเว้นกรณีที่มีการใช้ DISTINCT ซึ่งฉันจะกล่าวถึงด้านล่าง) ตามตัวอย่าง ฉันจะดำเนินการล่วงหน้าเล็กน้อยโดยใช้ตัวเลือก TOP และแสดงให้เห็นว่าคุณสามารถเลือกพนักงาน 3 คนที่มีเงินเดือนสูงสุดได้อย่างไร โดยคำนึงถึงว่าเพื่อวัตถุประสงค์ในการรักษาความลับฉันไม่ควรแสดงเงินเดือน:

SELECT TOP 3 -- ส่งคืนเฉพาะ 3 ระเบียนแรกจาก ID ผลลัพธ์ทั้งหมด, นามสกุล, ชื่อจริงจากพนักงาน ORDER BY Salary DESC -- เรียงลำดับผลลัพธ์จากมากไปหาน้อยของ Salary

บัตรประจำตัวประชาชน นามสกุล ชื่อ
1000 อีวานอฟ อีวาน
1002 ซิโดรอฟ ซีดอร์

แน่นอนว่า มีบางกรณีที่พนักงานหลายคนอาจมีเงินเดือนเท่ากัน และเป็นการยากที่จะบอกว่าคำขอนี้จะส่งกลับพนักงานคนใด ซึ่งจะต้องได้รับการแก้ไขร่วมกับผู้อำนวยการงาน สมมติว่าหลังจากหารือเกี่ยวกับงานนี้กับผู้จัดการแล้ว คุณตกลงและตัดสินใจใช้ตัวเลือกต่อไปนี้ - เพื่อทำการเรียงลำดับเพิ่มเติมตามฟิลด์วันเดือนปีเกิด (เช่น เราให้ความสำคัญกับคนหนุ่มสาว) และหากวันเกิดของพนักงานหลายคนอาจตรงกัน (ท้ายที่สุดก็ไม่รวมอยู่ด้วย) จากนั้นคุณสามารถทำการเรียงลำดับที่สามโดยเรียงลำดับค่า ID จากมากไปหาน้อย (สุดท้ายในกลุ่มตัวอย่างจะเป็นค่าที่มี ID สูงสุด - ตัวอย่างเช่นผู้ที่ได้รับการยอมรับเป็นอันดับสุดท้ายสมมติว่า มีการออกหมายเลขบุคลากรตามลำดับ):

เลือก TOP 3 -- ส่งคืนเฉพาะ 3 ระเบียนแรกจาก ID ผลลัพธ์ทั้งหมด นามสกุล ชื่อจากพนักงาน ORDER BY DESC เงินเดือน -- 1. เรียงลำดับผลลัพธ์จากมากไปน้อยตามวันเกิดเงินเดือน -- 2. จากนั้นตามวันเกิด ID DESC -- 3 และเพื่อความชัดเจนของผลลัพธ์ เราจึงเพิ่มการเรียงลำดับตาม ID

เหล่านั้น. คุณควรพยายามทำให้ผลลัพธ์ของคำขอสามารถคาดเดาได้ เพื่อที่ว่าในกรณีของการซักถาม คุณสามารถอธิบายได้ว่าทำไมบุคคลเหล่านี้จึงถูกรวมอยู่ใน "บัญชีดำ" เช่น ทุกอย่างถูกเลือกอย่างซื่อสัตย์ตามกฎที่กำหนดไว้

คุณยังสามารถเรียงลำดับโดยใช้นิพจน์ที่แตกต่างกันในส่วนคำสั่ง ORDER BY ได้:

เลือกนามสกุล, ชื่อจากพนักงาน ORDER BY CONCAT(LastName," ",FirstName) -- ใช้นิพจน์

คุณยังสามารถใช้นามแฝงที่ระบุสำหรับคอลัมน์ใน ORDER BY:

เลือก CONCAT (นามสกุล, " ", ชื่อ) fi จากพนักงาน ORDER BY fi - ใช้นามแฝง

เป็นที่น่าสังเกตว่าเมื่อใช้คำสั่งย่อย DISTINCT เฉพาะคอลัมน์ที่อยู่ในบล็อก SELECT เท่านั้นที่สามารถใช้ในส่วนคำสั่ง ORDER BY เหล่านั้น. หลังจากใช้การดำเนินการ DISTINCT เราจะได้ชุดข้อมูลใหม่พร้อมคอลัมน์ชุดใหม่ ด้วยเหตุนี้ ตัวอย่างต่อไปนี้จึงไม่ทำงาน:

SELECT DISTINCT LastName,FirstName,Salary FROM Employees ORDER BY ID -- ID ไม่อยู่ในชุดผลลัพธ์ที่เราได้รับด้วย DISTINCT

เหล่านั้น. คำสั่งย่อย ORDER BY ใช้กับชุดผลลัพธ์ก่อนที่ผลลัพธ์จะถูกส่งกลับไปยังผู้ใช้

หมายเหตุ 1.คุณยังสามารถใช้หมายเลขของคอลัมน์ที่แสดงอยู่ใน SELECT ในส่วนคำสั่ง ORDER BY ได้:

SELECT LastName,FirstName,Salary FROM Employees ORDER BY -- เรียงลำดับ 3 DESC, -- 1. เงินเดือนจากมากไปน้อย 1, -- 2. ตามนามสกุล 2 -- 3. ตามชื่อ

สำหรับผู้เริ่มต้นจะดูสะดวกและน่าดึงดูด แต่เป็นการดีกว่าที่จะลืมและอย่าใช้ตัวเลือกการเรียงลำดับนี้

หากในกรณีนี้ (เมื่อมีการแสดงรายการช่องต่างๆ ไว้อย่างชัดเจน) ตัวเลือกนี้ยังเป็นที่ยอมรับได้ ในกรณีที่ใช้ "*" จะเป็นการดีกว่าที่จะไม่ใช้ตัวเลือกนี้ เพราะเหตุใด - เนื่องจากหากมีคน เช่น เปลี่ยนลำดับของคอลัมน์ในตาราง หรือลบคอลัมน์ (ซึ่งถือเป็นสถานการณ์ปกติ) การสืบค้นของคุณอาจยังใช้งานได้ แต่ไม่ถูกต้อง เนื่องจาก การเรียงลำดับสามารถทำได้โดยคอลัมน์อื่นและนี่เป็นเรื่องร้ายกาจเนื่องจากข้อผิดพลาดนี้อาจไม่ถูกค้นพบในเร็วๆ นี้

หากมีการระบุคอลัมน์ไว้อย่างชัดเจน ในสถานการณ์ข้างต้น คิวรีจะยังคงทำงานต่อไปแต่ก็ถูกต้องเช่นกัน (เนื่องจากทุกอย่างถูกกำหนดไว้อย่างชัดเจน) หรืออาจเพียงแสดงข้อผิดพลาดที่ไม่มีคอลัมน์นี้อยู่

คุณจึงลืมการเรียงลำดับตามหมายเลขคอลัมน์ไปได้เลย

หมายเหตุ 2
ใน MS SQL เมื่อเรียงลำดับจากน้อยไปหามาก ค่า NULL จะแสดงก่อน

เลือก BonusPercent จากพนักงานเรียงตาม BonusPercent

ดังนั้นเมื่อใช้ DESC มันจะอยู่ที่จุดสิ้นสุด

เลือก BonusPercent จากพนักงานเรียงลำดับตาม BonusPercent DESC

หากคุณต้องการเปลี่ยนตรรกะในการเรียงลำดับค่า NULL ให้ใช้นิพจน์ เช่น:

เลือก BonusPercent จากพนักงาน ORDER BY ISNULL(BonusPercent,100)

ORACLE มีสองตัวเลือกสำหรับจุดประสงค์นี้: NULLS FIRST และ NULLS LAST (ใช้เป็นค่าเริ่มต้น) ตัวอย่างเช่น:

เลือก BonusPercent จากพนักงาน เรียงตาม BonusPercent DESC NULLS LAST

โปรดใส่ใจกับสิ่งนี้เมื่อเปลี่ยนไปใช้ฐานข้อมูลเฉพาะ

TOP – ส่งคืนจำนวนเรคคอร์ดที่ระบุ

สารสกัดจาก MSDN TOP—จำกัดจำนวนแถวที่ส่งคืนในผลลัพธ์การค้นหาที่ตั้งค่าเป็นตัวเลขหรือเปอร์เซ็นต์ที่ระบุ เมื่อมีการใช้คำสั่งย่อย TOP ร่วมกับคำสั่งย่อย ORDER BY ชุดผลลัพธ์จะถูกจำกัดไว้ที่ N แถวแรกของผลลัพธ์ที่เรียงลำดับ มิฉะนั้น N แถวแรกจะถูกส่งกลับตามลำดับที่ไม่ได้ระบุ

โดยทั่วไปนิพจน์นี้จะใช้กับส่วนคำสั่ง ORDER BY และเราได้ดูตัวอย่างที่จำเป็นต้องส่งคืน N แถวแรกจากชุดผลลัพธ์แล้ว

หากไม่มี ORDER BY ประโยคนี้มักจะใช้เมื่อเราต้องการดูตารางที่เราไม่รู้จักซึ่งอาจมีบันทึกจำนวนมาก ในกรณีนี้ เราสามารถขอส่งคืนเฉพาะ 10 แถวแรกได้ แต่สำหรับ ความชัดเจนเราจะพูดเพียง 2:

เลือก TOP 2 * จากพนักงาน

คุณยังสามารถระบุคำว่า PERCENT เพื่อส่งคืนเปอร์เซ็นต์ของแถวที่สอดคล้องกันจากชุดผลลัพธ์:

เลือก 25 เปอร์เซนต์สูงสุด * จากพนักงาน

ในทางปฏิบัติของฉัน มักใช้การสุ่มตัวอย่างตามจำนวนแถว

คุณยังสามารถใช้ตัวเลือก WITH TIES กับ TOP ซึ่งจะช่วยส่งคืนแถวทั้งหมดในกรณีที่มีการเรียงลำดับที่ไม่ชัดเจน เช่น ประโยคนี้จะส่งคืนแถวทั้งหมดที่มีองค์ประกอบเท่ากันไปยังแถวที่อยู่ในการเลือก TOP N ส่งผลให้สามารถเลือกได้มากกว่า N แถว เรามาเพิ่ม "โปรแกรมเมอร์" อีกคนด้วยเงินเดือน 1,500 สำหรับการสาธิต:

INSERT Employees(ID,Name,Email,PositionID,DepartmentID,ManagerID,Salary) ค่า(1004,N"Nikolaev N.N."," [ป้องกันอีเมล]",3,3,1003,1500)

และขอเพิ่มพนักงานอีกคนโดยไม่ระบุตำแหน่งและแผนกด้วยเงินเดือน 2,000:

INSERT พนักงาน (ID, ชื่อ, อีเมล, PositionID, DepartmentID, ManagerID, เงินเดือน) ค่า (1005, N "Alexandrov A.A.", [ป้องกันอีเมล]",โมฆะ,โมฆะ,1,000,2000)

ทีนี้มาเลือกใช้ตัวเลือก WITH TIES พนักงานทุกคนที่มีเงินเดือนตรงกับเงินเดือนของพนักงาน 3 คนโดยมีเงินเดือนน้อยที่สุด (ฉันหวังว่าจะชัดเจนยิ่งขึ้นว่าฉันได้รับอะไร):

เลือก 3 อันดับแรกที่มีรหัส TIES, ชื่อ, เงินเดือนจากพนักงานเรียงตามเงินเดือน

ที่นี่แม้ว่าจะมีการระบุ TOP 3 แต่คำขอก็ส่งคืน 4 บันทึกเพราะ มูลค่าเงินเดือนที่ส่งคืน TOP 3 (1,500 และ 2,000) พบในพนักงาน 4 คน สายตามันใช้งานได้ดังนี้:

เพียงแค่บันทึก
TOP ได้รับการปรับใช้ในรูปแบบต่างๆ ในฐานข้อมูลที่แตกต่างกัน ใน MySQL มี LIMIT clause สำหรับสิ่งนี้ ซึ่งคุณสามารถตั้งค่าออฟเซ็ตเริ่มต้นเพิ่มเติมได้

ใน ORACLE 12c พวกเขายังแนะนำอะนาล็อกของตัวเอง โดยผสมผสานฟังก์ชันของ TOP และ LIMIT - ค้นหาคำว่า "ORACLE OFFSET FETCH" ก่อนเวอร์ชัน 12c โดยทั่วไปจะใช้คอลัมน์หลอก ROWNUM เพื่อจุดประสงค์นี้


จะเกิดอะไรขึ้นถ้าคุณใช้ DISTINCT และ TOP clause พร้อมกัน? คำถามดังกล่าวสามารถตอบได้อย่างง่ายดายโดยทำการทดลอง โดยทั่วไปแล้วอย่ากลัวและอย่าเกียจคร้านที่จะทดลองเพราะ... ส่วนใหญ่จะเรียนรู้ผ่านการฝึกฝน ลำดับคำในคำสั่ง SELECT มีดังนี้ DISTINCT มาก่อน ตามด้วย TOP เช่น หากคุณคิดอย่างมีเหตุผลและอ่านจากซ้ายไปขวา ระบบจะใช้รายการแรกที่ทิ้งรายการที่ซ้ำกัน จากนั้น TOP จะถูกสร้างตามชุดนี้ เรามาตรวจสอบและตรวจสอบให้แน่ใจว่าเป็นกรณีนี้:

เลือกเงินเดือน 2 อันดับแรกที่โดดเด่นจากพนักงาน เรียงตามเงินเดือน

เงินเดือน
1500
2000

เหล่านั้น. เป็นผลให้เราได้รับเงินเดือนที่น้อยที่สุด 2 อันดับจากทั้งหมด แน่นอนว่าอาจมีกรณีที่ไม่สามารถระบุเงินเดือนของพนักงานบางคนได้ (NULL) เนื่องจาก โครงการช่วยให้เราทำเช่นนี้ได้ ดังนั้นเราจึงตัดสินใจว่าจะประมวลผลค่า NULL ในส่วนคำสั่ง ORDER BY หรือเพียงแค่ละทิ้งบันทึกทั้งหมดที่เงินเดือนเป็น NULL ขึ้นอยู่กับงานและด้วยเหตุนี้เราจึงดำเนินการศึกษาส่วนคำสั่ง WHERE

WHERE – เงื่อนไขการเลือกแถว

ประโยคนี้ใช้เพื่อกรองบันทึกตามเงื่อนไขที่กำหนด ตัวอย่างเช่น ให้เลือกพนักงานทุกคนที่ทำงานในแผนก "ไอที" (ID=3):

เลือก ID,นามสกุล,ชื่อ,เงินเดือนจากพนักงาน WHERE DepartmentID=3 -- IT ORDER BY LastName,FirstName

บัตรประจำตัวประชาชน นามสกุล ชื่อ เงินเดือน
1004 โมฆะ โมฆะ 1500
1003 อันดรีฟ อันเดรย์ 2000
1001 เปตรอฟ ปีเตอร์ 1500

ส่วนคำสั่ง WHERE ถูกเขียนก่อนคำสั่ง ORDER BY

ลำดับการใช้คำสั่งกับชุดพนักงานเริ่มต้นมีดังนี้:

  1. โดยที่ – หากระบุไว้ ขั้นตอนแรกจากชุดพนักงานทั้งหมดคือการเลือกเฉพาะเรกคอร์ดที่ตรงตามเงื่อนไข
  2. DISTINCT – หากระบุไว้ รายการซ้ำทั้งหมดจะถูกละทิ้ง
  3. ORDER BY – หากระบุ ผลลัพธ์จะถูกจัดเรียง
  4. TOP – หากระบุไว้ ระบบจะส่งกลับเฉพาะจำนวนเรคคอร์ดที่ระบุจากผลลัพธ์ที่เรียงลำดับ

ลองดูตัวอย่างเพื่อความชัดเจน:

เลือกเงินเดือน 1 อันดับแรกที่โดดเด่นจากพนักงาน โดยที่ DepartmentID=3 เรียงตามเงินเดือน

สายตาจะมีลักษณะเช่นนี้:

เป็นที่น่าสังเกตว่าการตรวจสอบค่า NULL ไม่ได้ทำด้วยเครื่องหมายเท่ากับ แต่ใช้ตัวดำเนินการ IS NULL และ IS NOT NULL เพียงจำไว้ว่าคุณไม่สามารถเปรียบเทียบ NULL โดยใช้ตัวดำเนินการ “=” (เครื่องหมายเท่ากับ) ได้ เนื่องจาก ผลลัพธ์ของนิพจน์จะเท่ากับ NULL ด้วย

ตัวอย่างเช่น ให้เลือกพนักงานทั้งหมดที่ไม่ได้ระบุแผนก (เช่น DepartmentID IS NULL):

เลือก ID, ชื่อจากพนักงานโดยที่ DepartmentID เป็นโมฆะ

ในตอนนี้ เป็นตัวอย่าง มาคำนวณโบนัสสำหรับพนักงานทุกคนที่มีค่า BonusPercent ที่ระบุ (เช่น BonusPercent ไม่ใช่ NULL):

เลือก ID, ชื่อ, เงินเดือน/100*BonusPercent เป็นโบนัสจากพนักงาน โดยที่ BonusPercent ไม่ใช่ NULL

ใช่ ยังไงก็ตาม หากคุณลองคิดดู ค่า BonusPercent สามารถเท่ากับศูนย์ (0) และสามารถป้อนค่าด้วยเครื่องหมายลบได้ เนื่องจากเราไม่ได้กำหนดข้อจำกัดใดๆ ในฟิลด์นี้

หลังจากบอกเกี่ยวกับปัญหาแล้ว เราได้รับแจ้งในตอนนี้ให้พิจารณาว่าถ้า (BonusPercent<=0 или BonusPercent IS NULL), то это означает что у сотрудника так же нет бонуса. Для начала, как нам сказали, так и сделаем, реализуем это при помощи логического оператора OR и NOT:

เลือก ID, ชื่อ, เงินเดือน/100*BonusPercent เป็นโบนัสจากพนักงาน โดยที่ไม่ได้ (BonusPercent<=0 OR BonusPercent IS NULL)

เหล่านั้น. ที่นี่เราเริ่มเรียนรู้เกี่ยวกับตัวดำเนินการบูลีน นิพจน์ในวงเล็บ “(BonusPercent<=0 OR BonusPercent IS NULL)» проверяет на то что у сотрудника нет бонуса, а NOT инвертирует это значение, т.е. говорит «верни всех сотрудников которые не сотрудники у которых нет бонуса».

นิพจน์นี้สามารถเขียนใหม่ได้โดยพูดว่า "คืนพนักงานทั้งหมดที่มีโบนัส" ทันทีโดยแสดงสิ่งนี้ด้วยนิพจน์ (BonusPercent>0 และ BonusPercent IS NOT NULL):

เลือก ID, ชื่อ, เงินเดือน/100*BonusPercent เป็นโบนัสจากพนักงาน โดยที่ BonusPercent>0 และ BonusPercent ไม่ใช่ NULL

นอกจากนี้ ในบล็อก WHERE คุณสามารถตรวจสอบนิพจน์ประเภทต่างๆ ได้โดยใช้ตัวดำเนินการและฟังก์ชันทางคณิตศาสตร์ ตัวอย่างเช่น การตรวจสอบที่คล้ายกันสามารถทำได้โดยใช้นิพจน์ที่มีฟังก์ชัน ISNULL:

เลือก ID, ชื่อ, เงินเดือน/100*BonusPercent เป็นโบนัสจากพนักงาน โดยที่ ISNULL(BonusPercent,0)>0

ตัวดำเนินการบูลีนและตัวดำเนินการเปรียบเทียบอย่างง่าย

ใช่ เราไม่สามารถดำเนินการได้หากไม่มีคณิตศาสตร์ที่นี่ ดังนั้น เรามาดูรายละเอียดสั้นๆ เกี่ยวกับบูลีนและตัวดำเนินการเปรียบเทียบแบบง่ายกันดีกว่า

มีตัวดำเนินการบูลีนเพียง 3 ตัวใน SQL - AND, OR และ NOT:

สำหรับตัวดำเนินการบูลีนแต่ละตัว คุณสามารถจัดเตรียมตารางความจริงที่แสดงให้เห็นเพิ่มเติมว่าผลลัพธ์จะเป็นอย่างไรเมื่อเงื่อนไขสามารถเป็น NULL ได้:

มีตัวดำเนินการเปรียบเทียบอย่างง่ายต่อไปนี้ที่ใช้ในการสร้างเงื่อนไข:

นอกจากนี้ยังมีตัวดำเนินการ 2 ตัวสำหรับตรวจสอบค่า/นิพจน์สำหรับ NULL:

เป็นโมฆะ การทดสอบความเท่าเทียมกันของ NULL
ไม่เป็นโมฆะ การทดสอบความไม่เท่าเทียมกันของ NULL

ลำดับความสำคัญ: 1) ตัวดำเนินการเปรียบเทียบทั้งหมด; 2) ไม่; 3) และ; 4) หรือ.

เมื่อสร้างนิพจน์เชิงตรรกะที่ซับซ้อน จะใช้วงเล็บ:

((เงื่อนไข1 และเงื่อนไข2) หรือไม่(เงื่อนไข3 และเงื่อนไข4 และเงื่อนไข5)) หรือ (...)

นอกจากนี้ คุณสามารถเปลี่ยนลำดับการคำนวณมาตรฐานได้ด้วยการใช้วงเล็บ

ที่นี่ฉันพยายามให้แนวคิดเกี่ยวกับพีชคณิตแบบบูลในปริมาณที่เพียงพอสำหรับการทำงาน อย่างที่คุณเห็น เพื่อที่จะเขียนเงื่อนไขที่ซับซ้อนมากขึ้น คุณไม่สามารถทำได้หากไม่มีตรรกะ แต่ที่นี่มีไม่มากนัก (และ หรือ และไม่ใช่) และมันถูกประดิษฐ์ขึ้นโดยผู้คน ดังนั้นทุกอย่างจึงค่อนข้างสมเหตุสมผล

มาดูตอนท้ายของส่วนที่สองกันดีกว่า

อย่างที่คุณเห็นแม้เกี่ยวกับไวยากรณ์พื้นฐานของตัวดำเนินการ SELECT เราก็สามารถพูดคุยได้เป็นเวลานาน แต่เพื่อให้อยู่ในขอบเขตของบทความในที่สุดฉันก็จะแสดงตัวดำเนินการเชิงตรรกะเพิ่มเติม - BETWEEN, IN และ LIKE

BETWEEN – ตรวจสอบการรวมในช่วง

Test_value ระหว่าง start_value และ end_value

นิพจน์สามารถทำหน้าที่เป็นค่าได้

ลองดูตัวอย่าง:

เลือก ID, ชื่อ, เงินเดือนจากพนักงานที่มีเงินเดือนระหว่าง 2,000 ถึง 3,000 - ซึ่งมีเงินเดือนอยู่ในช่วง 2,000-3,000

จริงๆ แล้ว BETWEEN เป็นสัญกรณ์แบบง่ายของแบบฟอร์ม:

เลือก ID, ชื่อ, เงินเดือนจากพนักงาน WHERE เงินเดือน>=2,000 และเงินเดือน<=3000 -- все у кого ЗП в диапозоне 2000-3000

คำว่า NOT สามารถใช้หน้าคำว่า BETWEEN ได้ ซึ่งจะตรวจสอบว่าค่าไม่อยู่ในช่วงที่ระบุหรือไม่:

เลือก ID, ชื่อ, เงินเดือนจากพนักงานโดยที่เงินเดือนไม่อยู่ระหว่าง 2,000 ถึง 3,000 -- คล้ายกับ NOT(เงินเดือน>=2,000 และเงินเดือน<=3000)

ดังนั้น หากคุณใช้ BETWEEN, IN, LIKE คุณสามารถรวมเข้ากับเงื่อนไขอื่นๆ โดยใช้ AND และ OR:

SELECT ID,Name,Salary FROM Employees WHERE Salary BETWEEN 2000 AND 3000 -- ที่มีเงินเดือนอยู่ในช่วง 2000-3000 AND DepartmentID=3 -- คำนึงถึงพนักงานของแผนก 3 เท่านั้น

IN – ตรวจสอบการรวมไว้ในรายการค่า

โอเปอเรเตอร์นี้มีแบบฟอร์มดังต่อไปนี้:

Test_value ใน (value1, value2, ...)

ฉันคิดว่าการแสดงตัวอย่างทำได้ง่ายกว่า:

เลือก ID, ชื่อ, เงินเดือนจากพนักงาน WHERE PositionID IN (3,4) - ซึ่งมีตำแหน่ง 3 หรือ 4

เหล่านั้น. โดยพื้นฐานแล้วจะเหมือนกับนิพจน์ต่อไปนี้:

เลือก ID, ชื่อ, เงินเดือนจากพนักงาน โดยที่ PositionID=3 หรือ PositionID=4 -- ซึ่งมีตำแหน่ง 3 หรือ 4

ในกรณีของ NOT มันจะคล้ายกัน (เราจะได้ทุกคนยกเว้นแผนก 3 และ 4):

เลือก ID, ชื่อ, เงินเดือนจากพนักงานโดยที่ PositionID ไม่อยู่ใน (3,4) -- คล้ายกับ NOT (PositionID=3 หรือ PositionID=4)

แบบสอบถามที่มี NOT IN สามารถแสดงโดยใช้ AND:

เลือก ID, ชื่อ, เงินเดือนจากพนักงาน WHERE PositionID<>3และตำแหน่งID<>4 -- เทียบเท่ากับ PositionID NOT IN(3,4)

โปรดทราบว่าการค้นหาค่า NULL โดยใช้โครงสร้าง IN จะไม่ทำงานเพราะว่า การตรวจสอบ NULL=NULL จะส่งคืนค่า NULL ไม่ใช่ True:

เลือก ID, ชื่อ, DepartmentID จากพนักงาน WHERE DepartmentID IN (1,2, NULL) -- บันทึก NULL จะไม่รวมอยู่ในผลลัพธ์

ในกรณีนี้ ให้แบ่งเช็คออกเป็นหลายเงื่อนไข:

เลือก ID, ชื่อ, DepartmentID จากพนักงานโดยที่ DepartmentID IN (1,2) -- 1 หรือ 2 หรือ DepartmentID เป็น NULL -- หรือ NULL

หรือคุณสามารถเขียนบางอย่างเช่น:

เลือก ID,ชื่อ,DepartmentID จากพนักงาน WHERE ISNULL(DepartmentID,-1) IN(1,2,-1) -- หากคุณแน่ใจว่าไม่มีแผนกที่มี ID=-1

ฉันคิดว่าตัวเลือกแรกในกรณีนี้จะถูกต้องและเชื่อถือได้มากกว่า โอเค นี่เป็นเพียงตัวอย่างเพื่อแสดงให้เห็นว่าโครงสร้างอื่นใดที่สามารถสร้างได้

นอกจากนี้ยังควรกล่าวถึงข้อผิดพลาดที่ร้ายกาจยิ่งกว่าที่เกี่ยวข้องกับ NULL ซึ่งสามารถทำได้เมื่อใช้โครงสร้าง NOT IN ตัวอย่างเช่น ลองเลือกพนักงานทั้งหมด ยกเว้นพนักงานที่มีแผนกเป็น 1 หรือไม่ได้ระบุแผนกเลย เช่น เท่ากับ NULL เพื่อเป็นวิธีแก้ปัญหา ตัวเลือกต่อไปนี้จะแนะนำตัวเอง:

เลือก ID, ชื่อ, DepartmentID จากพนักงานโดยที่ DepartmentID ไม่อยู่ใน (1, NULL)

แต่หลังจากดำเนินการค้นหาแล้ว เราจะไม่ได้รับแถวเดียว แม้ว่าเราคาดว่าจะเห็นสิ่งต่อไปนี้:

อีกครั้ง เรื่องตลกที่นี่เล่นโดย NULL ที่ระบุในรายการค่า

มาดูกันว่าเหตุใดจึงเกิดข้อผิดพลาดเชิงตรรกะในกรณีนี้ มาขยายแบบสอบถามโดยใช้ AND:

เลือก ID, ชื่อ, DepartmentID จากพนักงาน WHERE DepartmentID<>1 และ ID แผนก<>NULL -- ปัญหาเกิดจากการตรวจสอบ NULL นี้ เงื่อนไขนี้จะคืนค่า NULL เสมอ

สภาพถูกต้อง (DepartmentID<>NULL) จะให้ความไม่แน่นอนแก่เราเสมอที่นี่ เช่น โมฆะ. ตอนนี้ จำตารางความจริงสำหรับตัวดำเนินการ AND โดยที่ (TRUE และ NULL) ให้ค่า NULL เหล่านั้น. เมื่อตรงตามเงื่อนไขด้านซ้าย (DepartmentID<>1) เนื่องจากเงื่อนไขสิทธิ์ที่ไม่ได้กำหนดไว้ เราจะได้ค่าที่ไม่ได้กำหนดสำหรับนิพจน์ทั้งหมด (DepartmentID<>1 และ ID แผนก<>NULL) ดังนั้นสตริงจะไม่รวมอยู่ในผลลัพธ์

สามารถเขียนเงื่อนไขใหม่ได้อย่างถูกต้องดังนี้:

เลือก ID, ชื่อ, DepartmentID จากพนักงานโดยที่ DepartmentID ไม่อยู่ใน (1) - หรือในกรณีนี้เพียง DepartmentID<>1 และ DepartmentID ไม่เป็นโมฆะ -- และแยกตรวจสอบว่าไม่เป็นโมฆะ

IN ยังสามารถใช้กับแบบสอบถามย่อยได้ แต่เราจะกลับมาที่แบบฟอร์มนี้ในส่วนต่อๆ ไปของบทช่วยสอนนี้

LIKE – การตรวจสอบสตริงโดยใช้รูปแบบ

ฉันจะพูดถึงโอเปอเรเตอร์นี้เฉพาะในรูปแบบที่ง่ายที่สุดซึ่งเป็นมาตรฐานและได้รับการสนับสนุนโดยภาษา SQL ส่วนใหญ่ แม้จะอยู่ในรูปแบบนี้ ก็สามารถใช้เพื่อแก้ไขปัญหาต่างๆ ที่ต้องตรวจสอบเนื้อหาของสตริงได้

โอเปอเรเตอร์นี้มีแบบฟอร์มดังต่อไปนี้:

Test_string เช่น string_pattern

สามารถใช้อักขระพิเศษต่อไปนี้ใน "pattern_string":

  1. ขีดล่าง “_” หมายความว่าสามารถใช้อักขระตัวเดียวแทนได้
  2. เครื่องหมายเปอร์เซ็นต์ “%” - บอกว่าสามารถแทนที่ด้วยอักขระจำนวนเท่าใดก็ได้ รวมถึงไม่มีด้วย
ลองดูตัวอย่างที่มีสัญลักษณ์ "%" (ในทางปฏิบัติมักใช้บ่อยกว่า):

SELECT ID, ชื่อจากพนักงาน WHERE Name LIKE "Pet%" -- ซึ่งชื่อขึ้นต้นด้วยตัวอักษร "Pet" SELECT ID, LastName FROM Employees WHERE LastName LIKE "%ov" -- ซึ่งนามสกุลลงท้ายด้วย "ov" SELECT ID, นามสกุลจากพนักงาน โดยที่นามสกุลเช่น "%re%" -- ซึ่งนามสกุลประกอบด้วยชุดค่าผสม "re"

ลองดูตัวอย่างที่มีสัญลักษณ์ “_”:

SELECT ID, นามสกุลจากพนักงาน WHERE นามสกุล LIKE "_etrov" -- ซึ่งนามสกุลประกอบด้วยอักขระตัวแรกและตัวอักษรที่ตามมา "etrov" SELECT ID, นามสกุลจากพนักงาน WHERE นามสกุล LIKE "____ov" -- ซึ่งนามสกุลประกอบด้วยอักขระสี่ตัวใดก็ได้ และตัวอักษรต่อมาคือ "ov"

เมื่อใช้ ESCAPE คุณสามารถระบุอักขระ Escape ที่ยกเลิกผลการตรวจสอบของอักขระพิเศษ "_" และ "%" ส่วนคำสั่งนี้ใช้เมื่อคุณต้องการตรวจสอบเครื่องหมายเปอร์เซ็นต์หรือขีดล่างในสตริงโดยตรง

เพื่อสาธิต ESCAPE เรามารวมขยะไว้ในรายการเดียว:

อัปเดตพนักงาน SET FirstName = "นี่คือถังขยะที่มี %" โดยที่ ID = 1005

และมาดูกันว่าแบบสอบถามต่อไปนี้ส่งคืนอะไร:

SELECT * จากพนักงานโดยที่ FirstName เช่น "%!%%" ESCAPE "!" -- บรรทัดมีเครื่องหมาย "%" SELECT * FROM Employees WHERE FirstName LIKE "%!_%" ESCAPE "!" -- บรรทัดมีเครื่องหมาย "_"

หากคุณต้องการตรวจสอบสตริงเพื่อดูการจับคู่ที่สมบูรณ์ แทนที่จะใช้ LIKE ควรใช้เครื่องหมาย “=”:

SELECT * จากพนักงาน WHERE FirstName = "Peter"

เพียงแค่บันทึก
ใน MS SQL ในเทมเพลตตัวดำเนินการ LIKE คุณสามารถระบุการค้นหาโดยใช้นิพจน์ทั่วไปได้ อ่านเกี่ยวกับเรื่องนี้บนอินเทอร์เน็ตหากความสามารถมาตรฐานของตัวดำเนินการนี้ไม่เพียงพอสำหรับคุณ

ORACLE ใช้ฟังก์ชัน REGEXP_LIKE เพื่อค้นหาโดยใช้นิพจน์ทั่วไป

เล็กน้อยเกี่ยวกับสตริง

ในกรณีที่ตรวจสอบสตริงว่ามีอักขระ Unicode หรือไม่ คุณจะต้องวางอักขระ N ก่อนเครื่องหมายคำพูด เช่น น"…". แต่เนื่องจากช่องอักขระทั้งหมดในตารางของเราอยู่ในรูปแบบ Unicode (ประเภท nvarchar) คุณจึงใช้รูปแบบนี้กับช่องเหล่านี้ได้ตลอดเวลา ตัวอย่าง:

เลือก ID, ชื่อจากพนักงาน โดยที่ชื่อ LIKE N"Pet%" เลือก ID, นามสกุลจากพนักงาน WHERE LastName=N"Petrov"

เมื่อทำอย่างถูกต้อง เมื่อเปรียบเทียบกับฟิลด์ประเภท varchar (ASCII) คุณควรลองใช้การทดสอบโดยใช้ "..." และเมื่อเปรียบเทียบฟิลด์กับประเภท nvarchar (Unicode) คุณควรลองใช้การทดสอบโดยใช้ N" …”. ซึ่งทำเพื่อหลีกเลี่ยงการแปลงประเภทโดยนัยระหว่างการดำเนินการค้นหา เราใช้กฎเดียวกันเมื่อแทรกค่า (INSERT) ลงในฟิลด์หรืออัปเดต (UPDATE)

เมื่อเปรียบเทียบสตริง ควรพิจารณาจุดที่ขึ้นอยู่กับการตั้งค่าฐานข้อมูล (การจัดเรียง) การเปรียบเทียบสตริงอาจเป็นแบบคำนึงถึงตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ (เมื่อ "Petrov" = "PETROV") หรือคำนึงถึงตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ (เมื่อ "Petrov"<>"เปตรอฟ").
ในกรณีของการตั้งค่าที่คำนึงถึงตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ หากคุณต้องการค้นหาโดยไม่คำนึงถึงตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ คุณสามารถแปลงนิพจน์ด้านขวาและซ้ายไว้ล่วงหน้าเป็นตัวพิมพ์เดียว - บนหรือล่าง:

เลือก ID, ชื่อจากพนักงาน โดยที่ UPPER(ชื่อ) เช่น UPPER(N"Pet%") -- หรือ LOWER(ชื่อ) เช่น LOWER(N"Pet%") เลือก ID,นามสกุลจากพนักงาน โดยที่ UPPER(LastName)=UPPER( N"Petrov") -- หรือ LOWER(LastName)=LOWER(N"Petrov")

เล็กน้อยเกี่ยวกับวันที่

เมื่อตรวจสอบวันที่ คุณสามารถใช้เครื่องหมายคำพูดเดี่ยว "..." ได้เช่นเดียวกับสตริง

ไม่ว่าการตั้งค่าภูมิภาคใน MS SQL จะเป็นอย่างไร คุณสามารถใช้ไวยากรณ์วันที่ต่อไปนี้ "YYYYMMDD" (ปี เดือน วัน รวมกันโดยไม่ต้องเว้นวรรค) MS SQL จะเข้าใจรูปแบบวันที่นี้เสมอ:

เลือก ID, ชื่อ, วันเกิดจากพนักงานโดยที่วันเกิดระหว่าง "19800101" และ "19891231" - พนักงานในยุค 80 เรียงตามวันเกิด

ในบางกรณี การตั้งวันที่โดยใช้ฟังก์ชัน DATEFROMPARTS จะสะดวกกว่า:

เลือก ID, ชื่อ, วันเกิดจากพนักงานโดยที่วันเกิดระหว่าง DATEFROMPARTS (1980,1,1) และ DATEFROMPARTS (1989,12,31) เรียงตามวันเกิด

นอกจากนี้ยังมีฟังก์ชันที่คล้ายกัน DATETIMEFROMPARTS ซึ่งใช้ในการตั้งค่าวันที่และเวลา (สำหรับประเภทวันที่และเวลา)

คุณยังสามารถใช้ฟังก์ชัน CONVERT ได้หากต้องการแปลงสตริงเป็นค่าวันที่หรือเวลา:

เลือก แปลง(วันที่,"12.03.2015",104), แปลง(วันที่เวลา,"2014-11-30 17:20:15",120)

ค่า 104 และ 120 ระบุรูปแบบวันที่ที่ใช้ในสตริง คุณสามารถค้นหาคำอธิบายของรูปแบบที่ถูกต้องทั้งหมดในไลบรารี MSDN ได้โดยการค้นหา “MS SQL CONVERT”

มีฟังก์ชันมากมายสำหรับการทำงานกับวันที่ใน MS SQL ให้มองหา “ฟังก์ชัน ms sql สำหรับการทำงานกับวันที่”

บันทึก.ภาษา SQL ทุกภาษามีชุดฟังก์ชันของตนเองสำหรับการทำงานกับวันที่และใช้วิธีการของตนเองในการทำงานกับวันที่

เล็กน้อยเกี่ยวกับตัวเลขและการแปลง

ข้อมูลในส่วนนี้อาจเป็นประโยชน์กับผู้เชี่ยวชาญด้านไอทีมากกว่า หากคุณไม่ใช่หนึ่งเดียวและเป้าหมายของคุณคือเพียงเรียนรู้วิธีเขียนแบบสอบถามเพื่อรับข้อมูลที่คุณต้องการจากฐานข้อมูล คุณอาจไม่ต้องการรายละเอียดปลีกย่อยดังกล่าว แต่ในกรณีใด ๆ คุณสามารถอ่านข้อความและจดบันทึกได้อย่างรวดเร็ว , เพราะ . หากคุณได้ศึกษาเกี่ยวกับ SQL แสดงว่าคุณเข้าร่วมงานไอทีแล้ว

ต่างจากฟังก์ชันการแปลง CAST คุณสามารถระบุพารามิเตอร์ที่สามในฟังก์ชัน CONVERT ซึ่งรับผิดชอบรูปแบบการแปลง (รูปแบบ) ประเภทข้อมูลที่แตกต่างกันอาจมีชุดสไตล์ของตัวเอง ซึ่งอาจส่งผลต่อผลลัพธ์ที่ส่งคืน เราได้สัมผัสถึงการใช้สไตล์แล้วเมื่อพิจารณาการแปลงสตริงโดยใช้ฟังก์ชัน CONVERT เป็นประเภทวันที่และเวลา

คุณสามารถอ่านเพิ่มเติมเกี่ยวกับฟังก์ชัน CAST, CONVERT และสไตล์ใน MSDN - “ฟังก์ชัน CAST และ CONVERT (Transact-SQL)”: msdn.microsoft.com/ru-ru/library/ms187928.aspx

เพื่อให้ตัวอย่างง่ายขึ้น จะใช้คำสั่งภาษา Transact-SQL DECLARE และ SET ที่นี่

แน่นอน ในกรณีของการแปลงจำนวนเต็มเป็นจำนวนจริง (ซึ่งฉันได้ให้ไว้ตอนต้นของบทเรียนนี้ เพื่อแสดงให้เห็นความแตกต่างระหว่างจำนวนเต็มและการหารจำนวนจริง) ความรู้เกี่ยวกับความแตกต่างของการแปลงนั้นไม่สำคัญนัก เพราะ ที่นั่นเราได้แปลงจำนวนเต็มเป็นจำนวนจริง (ช่วงซึ่งมากกว่าช่วงของจำนวนเต็มมาก):

ประกาศ @min_int int SET @min_int=-2147483648 ประกาศ @max_int int SET @max_int=2147483647 SELECT -- (-2147483648) @min_int,CAST(@min_int AS float),CONVERT(float,@min_int), -- 2147483647 @max_int ,CAST(@max_int AS float),CONVERT(float,@max_int), -- ตัวเลข(16,6) @min_int/1., -- (-2147483648.000000) @max_int/1. -- 2147483647.000000

บางทีอาจไม่คุ้มค่าที่จะระบุวิธีการแปลงโดยนัยที่ได้จากการหารด้วย (1.) เพราะ ขอแนะนำให้ลองทำการแปลงที่ชัดเจนเพื่อการควบคุมประเภทของผลลัพธ์ที่ได้รับมากขึ้น แม้ว่าเราต้องการได้ผลลัพธ์เป็นประเภทตัวเลข โดยมีจำนวนหลักที่ระบุหลังจุดทศนิยม เราก็สามารถใช้เคล็ดลับใน MS SQL เพื่อคูณค่าจำนวนเต็มด้วย (1., 1.0, 1.00 ฯลฯ) : :

ประกาศ @int int SET @int=123 SELECT @int*1., -- ตัวเลข(12, 0) - ทศนิยม 0 ตำแหน่ง @int*1.0, -- ตัวเลข(13, 1) - ทศนิยม 1 ตำแหน่ง @int*1.00, -- ตัวเลข(14, 2) - 2 ตัวอักษร -- แม้ว่าบางครั้งจะเป็นการดีกว่าหากทำการแปลงอย่างชัดเจน CAST(@int AS numeric(20, 0)) -- 123 CAST(@int AS numeric(20, 1) ), -- 123.0 CAST(@int AS ตัวเลข(20, 2)) -- 123.00

ในบางกรณีรายละเอียดของการแปลงมีความสำคัญมาก เนื่องจาก... ส่งผลต่อความถูกต้องของผลลัพธ์ที่ได้รับ เช่น ในกรณีที่ทำการแปลงจากค่าตัวเลขเป็นสตริง (varchar) ลองดูตัวอย่างการแปลงเงินและค่าลอยตัวเป็น varchar:

พฤติกรรมเมื่อแปลงเงินเป็น varchar DECLARE @money money SET @money = 1025.123456789 -- จะมีการแปลงโดยนัยเป็น 1025.1235 เพราะ ประเภทเงินเก็บเพียง 4 หลักหลังจุดทศนิยม SELECT @money, -- 1025.1235 -- ตามค่าเริ่มต้น CAST และ CONVERT จะทำงานเหมือนกัน (เช่น พูดคร่าวๆ จะใช้สไตล์ 0) CAST(@money as varchar(20)) , -- 1,025.12 CONVERT(varchar(20), @money), -- 1,025.12 CONVERT(varchar(20), @money, 0), -- 1,025.12 (รูปแบบ 0 - ไม่มีตัวคั่นหลักพันและทศนิยม 2 ตำแหน่ง (รูปแบบเริ่มต้น)) CONVERT( varchar(20), @money, 1), -- 1.025.12 (สไตล์ 1 - ใช้ตัวคั่นหนึ่งในพันและทศนิยม 2 ตำแหน่ง) CONVERT(varchar(20), @money, 2) -- 1025.1235 (สไตล์ 2 - ไม่มีตัวคั่นและมีตัวเลข 4 ตัวหลังจุดทศนิยม)

พฤติกรรมเมื่อแปลง float เป็น varchar DECLARE @float1 float SET @float1 = 1025.123456789 DECLARE @float2 float SET @float2 = 1231025.123456789 SELECT @float1, -- 1025.123456789 @float2, -- 1231025 .12345679 -- โดย ค่าเริ่มต้น CAST และ CONVERT จะทำงานเหมือนกัน (กล่าวคือ พูดคร่าวๆ ก็คือใช้สไตล์ 0) -- สไตล์ 0 - ไม่เกิน 6 หลัก สัญลักษณ์เอ็กซ์โพเนนเชียลถูกใช้โดยไม่จำเป็น -- สิ่งที่น่ากลัวจริงๆ เกิดขึ้นที่นี่เมื่อแปลงเป็น varchar CAST(@float1 เป็น varchar(20)), -- 1,025.12 CONVERT(varchar(20), @float1), -- 1,025.12 CONVERT(varchar( 20 ), @float1, 0), -- 1,025.12 CAST(@float2 เป็น varchar(20)), -- 1.23103e+006 CONVERT(varchar(20), @float2), -- 1.23103e+006 CONVERT(varchar( 20 ), @float2, 0), -- 1.23103e+006 -- style 1 - ต้องมี 8 หลักเสมอ มีการใช้สัญลักษณ์ทางวิทยาศาสตร์สำหรับตัวเลขเสมอ

-- สไตล์สำหรับ float นี้ยังไม่ถูกต้องมากนัก CONVERT(varchar(20), @float1, 1), -- 1.0251235e+003 CONVERT(varchar(20), @float2, 1), -- 1.2310251e+006 - - สไตล์ 2 - 16 บิตเสมอ มีการใช้สัญลักษณ์ทางวิทยาศาสตร์สำหรับตัวเลขเสมอ

หากคุณต้องการควบคุมความแม่นยำอย่างชัดเจนจนถึงเครื่องหมายที่กำหนด ซึ่งมากกว่า 4 บางครั้งการใช้ประเภททศนิยม/ตัวเลขในการจัดเก็บข้อมูลก็ดีกว่า หากเพียงพอแล้ว 4 ตัวอักษรคุณสามารถใช้ประเภทเงินได้ - ซึ่งสอดคล้องกับตัวเลขโดยประมาณ(20,4)

ทศนิยมและตัวเลข DECLARE @money money SET @money = 1025.123456789 -- 1025.1235 DECLARE @float1 float SET @float1 = 1025.123456789 DECLARE @float2 float SET @float2 = 1231025.123456789 DECLARE @numer ic(28,9 ) SET @numeric = 1025.123456789 เลือกนักแสดง ( @numeric as varchar(20)), -- 1025.12345679 CONVERT(varchar(20), @numeric), -- 1025.12345679 CAST(@money as numeric(28,9)), -- 1025.123500000 CAST(@float1 as numeric( 28 ,9)), -- 1025.123456789 CAST(@float2 เป็นตัวเลข(28,9)) -- 1231025.123456789

บันทึก.
ตั้งแต่เวอร์ชัน MS SQL 2008 คุณสามารถใช้โครงสร้างต่อไปนี้แทน:
  • เซิร์ฟเวอร์ ms sql
  • เพิ่มแท็ก