รูปแบบการต่อต้าน SQL ที่พบมากที่สุดคืออะไร [ปิด]


232

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


นี่เป็นคำถามที่ไม่เป็นไปตามมาตรฐานที่ใหม่กว่าเกี่ยวกับประเภทของคำถามที่เหมาะสมสำหรับ Stack Overflow เมื่อถูกถามสิ่งนี้อาจไม่เป็นจริง
David Manheim

@casperOne ไม่มีประโยค "นัยสำคัญทางประวัติศาสตร์" ที่ปู่จะทำให้คำถามนี้เป็นที่ยอมรับได้หรือไม่
Amy B

26
ฉันคิดว่ามันเศร้าที่หนึ่งในคำถามที่มีประโยชน์ที่สุดในเว็บไซต์ wohole นั้นปิดอย่างไม่สร้างสรรค์
HLGEM

11
@ HLGEM ฉันเห็นด้วยทั้งหมด คำถามนี้เป็นตัวอย่างที่สมบูรณ์แบบของสิ่งผิดปกติกับ StackExchange
Kevin Morse

1
หัวข้อนี้มีความสำคัญและเกี่ยวข้องอย่างยิ่ง แต่คำถามนั้นเปิดกว้างเกินไปซึ่งเป็นเหตุผลที่แต่ละคำตอบอธิบายถึงข้อผิดพลาดต่อต้านแพทเทิร์นรูปแบบของวิศวกรแต่ละคน
เชน

คำตอบ:


156

ฉันผิดหวังอย่างต่อเนื่องโดยโปรแกรมเมอร์ส่วนใหญ่มีแนวโน้มที่จะผสม UI- ตรรกะของพวกเขาในชั้นการเข้าถึงข้อมูล:

SELECT
    FirstName + ' ' + LastName as "Full Name",
    case UserRole
        when 2 then "Admin"
        when 1 then "Moderator"
        else "User"
    end as "User's Role",
    case SignedIn
        when 0 then "Logged in"
        else "Logged out"
    end as "User signed in?",
    Convert(varchar(100), LastSignOn, 101) as "Last Sign On",
    DateDiff('d', LastSignOn, getDate()) as "Days since last sign on",
    AddrLine1 + ' ' + AddrLine2 + ' ' + AddrLine3 + ' ' +
        City + ', ' + State + ' ' + Zip as "Address",
    'XXX-XX-' + Substring(
        Convert(varchar(9), SSN), 6, 4) as "Social Security #"
FROM Users

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

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


10
รูปแบบโปสเตอร์เด็กดีสำหรับการมีเพศสัมพันธ์สูงสุดในจำนวนชั้นที่เป็นไปได้ที่ใหญ่ที่สุด
dkretz

3
มันอาจจะไม่ดีสำหรับการยกเลิกการเชื่อมต่อ แต่ด้วยเหตุผลด้านประสิทธิภาพที่ฉันได้ทำสิ่งต่าง ๆ เช่นนั้นบ่อยครั้งการเปลี่ยนแปลงซ้ำ ๆ ที่ทำโดย SQL Server นั้นเร็วกว่าการเขียนโค้ดในระดับกลาง ฉันไม่ได้รับจุดที่คุณสามารถนำกลับมาใช้ใหม่ได้ - ไม่มีอะไรทำให้คุณไม่สามารถรัน SP และเปลี่ยนชื่อคอลัมน์ได้หากคุณต้องการ
Joe Pineda

54
สิ่งที่ฉันชอบคือเมื่อมีคนฝัง HTML และ javascript เช่น SELECT '<a href=... onclick="">' + ชื่อ '</a>'
Matt Rogish

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

4
@ Matt Rogish - พระเยซูมีคนทำอย่างนั้นจริงหรือ
Axarydax

118

นี่คือ 3 อันดับแรกของฉัน

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

SELECT *
Insert Into blah SELECT *

ควรจะเป็น

SELECT fieldlist
Insert Into blah (fieldlist) SELECT fieldlist

หมายเลข 2 การใช้เคอร์เซอร์และ while loop เมื่อ a ขณะที่ loop กับตัวแปร loop จะทำ

DECLARE @LoopVar int

SET @LoopVar = (SELECT MIN(TheKey) FROM TheTable)
WHILE @LoopVar is not null
BEGIN
  -- Do Stuff with current value of @LoopVar
  ...
  --Ok, done, now get the next value
  SET @LoopVar = (SELECT MIN(TheKey) FROM TheTable
    WHERE @LoopVar < TheKey)
END

หมายเลข 3 DateLogic ผ่านชนิดสตริง

--Trim the time
Convert(Convert(theDate, varchar(10), 121), datetime)

ควรจะเป็น

--Trim the time
DateAdd(dd, DateDiff(dd, 0, theDate), 0)

ฉันเคยเห็น "ล่าสุดหนึ่งคำค้นหาดีกว่าสองคำ,

SELECT *
FROM blah
WHERE (blah.Name = @name OR @name is null)
  AND (blah.Purpose = @Purpose OR @Purpose is null)

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


7
อืมฉันจะให้ +1 กับคุณสำหรับจุด 2 และ 3 เพียงอย่างเดียว แต่กฎของนักพัฒนาโอเวอร์เลย์ 1 มันมีอยู่ในบางครั้ง
annakata

1
อะไรคือเหตุผลเบื้องหลัง # 1
jalf

29
เมื่อคุณใช้ select * คุณจะได้สิ่งที่อยู่ในตาราง คอลัมน์เหล่านั้นอาจเปลี่ยนชื่อและคำสั่งซื้อ รหัสลูกค้ามักขึ้นอยู่กับชื่อและคำสั่งซื้อ ทุก ๆ 6 เดือนฉันจะถามวิธีรักษาลำดับคอลัมน์เมื่อแก้ไขตาราง หากปฏิบัติตามกฎแล้วจะไม่สำคัญ
เอมี่ B

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

4
... แต่แน่นอนเคอร์เซอร์แน่นอนเกือบจะเป็นทางเลือกสุดท้ายหลังจากล้มเหลวในการหาวิธีการทำงานกับ SQL ที่ตั้งค่าไว้ ฉันใช้เวลาประมาณ 45 นาทีในการตัดเคอร์เซอร์ PL / SQL ที่น่ากลัวขนาดมหึมาอย่างระมัดระวังในขั้นตอนการจัดเก็บ (ดึงไดอะแกรมของสิ่งที่เน่าเสีย) ซึ่งบรรจุตารางชั่วคราวขนาดใหญ่จากนั้นเลือกเนื้อหาของตารางอุณหภูมิกลับไปยังผู้โทรเพื่อแสดง รายงาน. ใช้เวลา 8.5 นาทีในการทำงานบนฮาร์ดแวร์ที่สำคัญ หลังจากสร้างแผนภาพทั้งหมดฉันก็สามารถแทนที่ด้วยข้อความค้นหาเดี่ยวซึ่งให้ผลลัพธ์แบบเดียวกันภายใน 2 วินาที เคอร์เซอร์มนุษย์ ...
เครก

71
  • ฟิลด์รหัสผ่านที่มนุษย์สามารถอ่านได้เช่น eg อธิบายตนเอง

  • ใช้LIKE กับ คอลัมน์ที่มีการจัดทำดัชนีและฉันเกือบถูกล่อลวงเพียงแค่พูดว่า LIKE โดยทั่วไป

  • รีไซเคิลค่า PK ที่สร้างโดย SQL

  • ไม่มีใครแปลกใจที่กล่าวถึงพระเจ้าโต๊ะเลย ไม่มีอะไรบอกว่า "อินทรีย์" เช่น 100 คอลัมน์ของค่าสถานะบิตสตริงขนาดใหญ่และจำนวนเต็ม

  • จากนั้นก็มีรูปแบบ "ฉันคิดถึงไฟล์. ini" : การจัดเก็บ CSVs สตริงที่คั่นด้วยไพพ์หรือการแยกวิเคราะห์ข้อมูลอื่น ๆ ที่จำเป็นในฟิลด์ข้อความขนาดใหญ่

  • และสำหรับเซิร์ฟเวอร์ MS SQL การใช้งานของเคอร์เซอร์ที่ทั้งหมด มีวิธีที่ดีกว่าในการทำภารกิจเคอร์เซอร์ใด ๆ

แก้ไขเพราะมีมากมาย!


19
ผิดเกี่ยวกับเม้าส์, ฉันจะลังเลเกี่ยวกับการพูดการทำสิ่งใด ๆ เป็น 100% ถูกหรือผิด 100%
Shawn

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

3
@tuinstoel: LIKE '% blah%' ใช้ดัชนีอย่างไร การจัดทำดัชนีอาศัยการสั่งซื้อและตัวอย่างนี้ค้นหาตำแหน่งกึ่งกลางแบบสุ่มของสตริง (ดัชนีสั่งซื้อโดย 1 ตัวละครที่ 1 และเพื่อให้มองไปที่กลาง 4 ตัวอักษรได้มีคำสั่งสุ่มจริง ... )
MatBailie

12
บนเซิร์ฟเวอร์ฐานข้อมูลส่วนใหญ่ (อย่างน้อยที่ฉันเคยใช้) LIKE สามารถใช้ดัชนี .. ตราบใดที่มันเป็นการค้นหาคำนำหน้า (เช่น 'xxx%') - นั่นคือตราบใดที่อักขระตัวแทนไม่ได้ มาก่อนในสตริงการค้นหา ฉันคิดว่าคุณอาจจะพูดคุยข้ามจุดประสงค์เล็กน้อยที่นี่
Cowan

10
LIKE '%LIKE'มันก็เหมือนกับการที่คุณไม่ชอบ
Johan

62

ไม่ต้องขุดลึกลงไป: ไม่ใช้คำสั่งที่เตรียมไว้


3
ได้. ติดตามอย่างใกล้ชิดในบริบทเดียวกันในประสบการณ์ของฉันด้วย "ไม่ดักข้อผิดพลาด"
dkretz

1
@stesch: นี่คือไม่มีอะไรเทียบกับการใช้มุมมองและมีวันที่รายงานตัวแปร จำนวนการดูเป็น antipattern หากคุณมีวันที่รายงานที่เปลี่ยนแปลงได้ จะเพิ่มในคำตอบที่แยกต่างหาก แต่มันปิดน่าเสียดาย
Stefan Steiger

56

ใช้นามแฝงตารางที่ไม่มีความหมาย:

from employee t1,
department t2,
job t3,
...

ทำให้การอ่านคำสั่ง SQL ที่มีขนาดใหญ่นั้นยากกว่าที่ควรจะเป็น


49
นามแฝง? นรกฉันเห็นชื่อคอลัมน์จริงเช่นนั้น
annakata

10
นามแฝง terse นั้นใช้ได้ หากคุณต้องการชื่อที่มีความหมายก็อย่าใช้ชื่อแทนเลย
Joel Coehoorn

43
เขาไม่ได้พูดว่า "สั้น" เขาพูดว่า "ไร้ความหมาย" ในหนังสือของฉันจะไม่มีอะไรผิดปกติกับการใช้ e, d และ j เป็นนามแฝงในแบบสอบถามตัวอย่าง
Robert Rossney

11
อย่างแน่นอน Robert - e, d, และ j จะดีกับฉัน
Tony Andrews

8
ผมจะใช้ EMP สำหรับพนักงาน, DEP สำหรับแผนกและงานหางาน (หรืออาจ JB) :)
อังเดรRînea

53
var query = "select COUNT(*) from Users where UserName = '" 
            + tbUser.Text 
            + "' and Password = '" 
            + tbPassword.Text +"'";
  1. การป้อนข้อมูลผู้ใช้ที่เชื่อถือได้แบบสุ่ม
  2. ไม่ได้ใช้ สืบค้นแบบมีพารามิเตอร์
  3. รหัสผ่านที่ชัดเจน

ซึ่งทั้งหมดสามารถจัดการได้อย่างมีประโยชน์โดยใช้ abstract นามธรรมชั้นในบางชนิด (ใด ๆ )
dkretz

@doofledorfer: เห็นด้วยระดับกลางจะดีกว่าแน่นอนในกรณีเช่นนี้รวมทั้งให้ผลการแคชเป็นผลข้างเคียงที่ดี
Joe Pineda

ตัวอย่างที่ดีเลิศ หาก dev ทำการค้นหาวิธีการแทนที่ด้วยโซลูชันที่ดีพวกเขาจะกลายเป็น SQL dev ที่เหมาะสม
Steve McLeod

46

Bugbears ของฉันคือตาราง Access 450 คอลัมน์ที่ได้รับการรวบรวมโดยลูกชายวัย 8 ขวบของ Dog Groomer เพื่อนที่ดีที่สุดของกรรมการผู้จัดการและตารางการค้นหาแบบหลบซึ่งมีอยู่เพราะใครบางคนไม่ทราบวิธีทำให้โครงสร้างข้อมูลเป็นปกติ

โดยทั่วไปตารางการค้นหานี้จะมีลักษณะดังนี้:

ID INT
ชื่อ NVARCHAR (132),
IntValue1 INT,
IntValue2 INT,
CharValue1 NVARCHAR (255),
CharValue2 NVARCHAR (255),
วันที่ 1 DATETIME
วันที่ 2 DATETIME

ฉันสูญเสียจำนวนลูกค้าที่ฉันเห็นว่ามีระบบที่พึ่งพาสิ่งที่น่ารังเกียจเช่นนี้


1
ยิ่งไปกว่านั้นฉันได้อ่านว่าใน Access รุ่นใหม่ล่าสุดที่รองรับโดยอัตโนมัติซึ่งฉันกลัวว่าจะกระตุ้นให้เกิดการเพิ่มเติมของ Value1, Value2, Value3 นี้ ... คอลัมน์ fetichism
Joe Pineda

เดี๋ยวก่อน - ดังนั้นลูกชายวัย 8 ขวบจึงเป็นลูกชายของสุนัขกรูมมิ่ง?
barrypicker

28

สิ่งที่ฉันไม่ชอบมากที่สุดคือ

  1. การใช้ช่องว่างเมื่อสร้างตาราง, sprocs ฯลฯ ฉันสบายดีกับ CamelCase หรือ under_scores และเอกพจน์หรือพหูพจน์และ UPPERCASE หรือตัวพิมพ์เล็ก แต่ต้องอ้างถึงตารางหรือคอลัมน์ [กับช่องว่าง] โดยเฉพาะอย่างยิ่งถ้ามีระยะห่างแปลก ๆ (ใช่ ฉันเจอสิ่งนี้) ทำให้ฉันรำคาญจริงๆ

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

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

  4. เข้าไป. โปรแกรมสามารถเป็นรูปแบบการต่อต้านได้หรือไม่? เรามี SQL Server ในที่ทำงานของฉัน แต่ผู้คนจำนวนมากใช้การเข้าถึงเนื่องจากมีประโยชน์ "ใช้งานง่าย" และ "เป็นมิตร" กับผู้ใช้ที่ไม่ใช่ด้านเทคนิค มีมากเกินไปที่จะเข้าไป แต่ถ้าคุณอยู่ในสภาพแวดล้อมที่คล้ายกันคุณก็รู้


2
# 4 - มีเธรดอื่นสำหรับ <a href=' stackoverflow.com/questions/327199/…> :)
dkretz

4
การเข้าถึงไม่ใช่ DBMS มันเป็นสภาพแวดล้อม RAD โดยมีตัวจัดการฐานข้อมูลที่ง่ายมาก SQL Server, Oracle และอื่น ๆ จะไม่แทนที่เว้นแต่ว่าคุณจะเพิ่มภาษาที่เหมือน VB และสิ่งที่คล้ายกับ Crystal Reports
Joe Pineda

26

ใช้ SP เป็นคำนำหน้าของชื่อขั้นตอนการจัดเก็บเพราะจะค้นหาในตำแหน่งขั้นตอนระบบแทนการใช้แบบกำหนดเอง


1
นอกจากนี้ยังสามารถขยายไปยังการใช้คำนำหน้าทั่วไปอื่น ๆ สำหรับขั้นตอนการจัดเก็บทั้งหมดทำให้ยากต่อการเลือกผ่านรายการที่เรียงลำดับ
dkretz

7
+1 สำหรับความคิดเห็น doofledorfer !! ฉันเห็นมันเยอะมากฉันพบว่ามันงี่เง่าและทำให้การค้นหา SP โดยเฉพาะยากมาก !!! ขยายไปยัง "vw_" สำหรับการดู "tbl_" สำหรับตารางและสิ่งที่ชอบฉันจะเกลียดพวกเขาอย่างไร!
Joe Pineda

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

1
ทำไมบนโลกจะมีประโยชน์ที่จะนำหน้าทุกขั้นตอนการจัดเก็บด้วย sp หรือ usp มันทำให้การสแกนรายการที่คุณต้องการนั้นยากขึ้น
Ryan Lundy

25

การใช้ตารางและเคอร์เซอร์ชั่วคราวมากเกินไป


2
หลักฐานที่ดีว่า "สิ่งที่ฉันรู้ก็คือภาษาเชิงดำเนินการ"
dkretz

2
การใช้มากเกินไปของสิ่งใดโดยนิยามที่ไม่ต้องการ ตัวอย่างที่เฉพาะเจาะจงของการใช้ตาราง / เคอร์เซอร์ที่ไม่ต้องการจะเป็นประโยชน์
Jace Rhea

6
ส่วนใหญ่ฉันเห็นตารางชั่วคราวที่ไม่ได้ใช้ ด้วย SQL Server บ่อยครั้งที่คุณได้รับประสิทธิภาพจากการทำสิ่งต่าง ๆ ด้วยตาราง temp แทนการสืบค้นแบบ monolithic
Cervo

24

สำหรับการเก็บค่าเวลาควรใช้เขตเวลา UTC เท่านั้น ไม่ควรใช้เวลาท้องถิ่น


3
ฉันยังไม่พบโซลูชันที่ง่ายสำหรับการแปลงจาก UTC เป็นเวลาท้องถิ่นสำหรับวันที่ในอดีตเมื่อต้องพิจารณาการปรับเวลาตามฤดูกาลด้วยวันที่เปลี่ยนแปลงที่แตกต่างกันไปตามปีและประเทศรวมถึงข้อยกเว้นทั้งหมดภายในประเทศ ดังนั้น UTC ไม่ได้ช่วยคุณในการแปลงที่ซับซ้อน อย่างไรก็ตามสิ่งสำคัญคือต้องมีวิธีการทราบเขตเวลาของทุกวันที่เก็บไว้
ckarras

1
@CsongorHalmai หลายแห่งฝึกฝนการออมแสงในเวลากลางวันดังนั้นค่าเวลาภายในหนึ่งชั่วโมงของการเลื่อนเวลาอาจไม่ชัดเจน
Frank Schwieterman

นั่นเหมาะสมกับปัจจุบันและอดีต แต่สำหรับอนาคตโดยเฉพาะอย่างยิ่งในอนาคตที่ค่อนข้างไกลโซนเวลาที่ชัดเจนมักเป็นสิ่งจำเป็น หากคุณมีตัวเลือก 30 ปีที่เพิ่งเขียนและหมดอายุใน 2049-09-27T17: 00: 00 เวลานิวยอร์กคุณไม่สามารถคาดเดาได้ว่าจะเป็น 21: 00: 00Z รัฐสภาคองเกรสแห่งสหรัฐอเมริกาอาจเปลี่ยนกฎ DST คุณต้องแยกเวลาท้องถิ่นและโซนเวลาจริง (อเมริกา / New_York) ออกจากกัน
John Cowan

23

ใช้ @@ IDENTITYแทน SCOPE_IDENTITY ()

อ้างจากคำตอบนี้ :

  • @@ IDENTITYส่งคืนค่าตัวตนสุดท้ายที่สร้างขึ้นสำหรับตารางใด ๆ ในเซสชันปัจจุบันข้ามขอบเขตทั้งหมด คุณต้องระวังที่นี่เพราะมันข้ามขอบเขต คุณสามารถรับค่าจากทริกเกอร์แทนที่จะเป็นคำสั่งปัจจุบันของคุณ
  • SCOPE_IDENTITYส่งคืนค่าเอกลักษณ์ล่าสุดที่สร้างขึ้นสำหรับตารางใด ๆ ในเซสชันปัจจุบันและขอบเขตปัจจุบัน โดยทั่วไปสิ่งที่คุณต้องการใช้
  • IDENT_CURRENTส่งคืนค่าเอกลักษณ์ล่าสุดที่สร้างขึ้นสำหรับตารางที่ระบุในเซสชันใด ๆ และขอบเขตใด ๆ สิ่งนี้ช่วยให้คุณระบุตารางที่คุณต้องการค่าในกรณีที่ทั้งสองข้างต้นไม่ได้เป็นสิ่งที่คุณต้องการ คุณสามารถใช้สิ่งนี้หากคุณต้องการรับค่าตัวตนปัจจุบันสำหรับตารางที่คุณยังไม่ได้แทรกบันทึก

+1 จริงมากอาจทำให้เกิดข้อบกพร่องที่ยากต่อการกำจัด
Axarydax

23

การใช้ฟิลด์ 'ตาย' อีกครั้งสำหรับบางสิ่งที่ไม่ได้มีไว้สำหรับ (เช่นการจัดเก็บข้อมูลผู้ใช้ในฟิลด์ 'แฟกซ์') - ดึงดูดอย่างมากว่าเป็นการแก้ไขอย่างรวดเร็ว!


21
select some_column, ...
from some_table
group by some_column

และสมมติว่าผลลัพธ์จะถูกจัดเรียงตาม some_column ฉันได้เห็นสิ่งนี้เล็กน้อยกับ Sybase ซึ่งมีการสันนิษฐาน (ตอนนี้)


1
upvote for EVER โดยสมมติว่ามีการเรียงลำดับเพียงเพราะเป็นวิธีที่ปรากฏในเครื่องมือ Query ที่ครั้งหนึ่ง
Joel Coehoorn

3
ฉันเคยเห็นสิ่งนี้รายงานว่าเป็นข้อผิดพลาดมากกว่าหนึ่งครั้ง
dkretz

6
ใน MySQL มันเป็นเอกสารที่จะจัดเรียง < dev.mysql.com/doc/refman/5.0/en/select.html > ดังนั้นโทษ MySQL (อีกครั้ง)
Derobert

1
ใน Oracle ผลลัพธ์ที่ไม่เรียงลำดับ (เกือบ) จะจับคู่กับการจัดกลุ่มเสมอ - จนถึงรุ่น 10G ทำใหม่มากมายสำหรับนักพัฒนาที่เคยลาออกจากคำสั่งซื้อ!
Tony Andrews

1
ฉันยังอยู่ในชั้นเรียนการฝึกอบรมซึ่งนี่เป็นข้อเท็จจริงสำหรับ SQL Server ฉันต้องประท้วงเสียงดังจริงๆ สำหรับการบันทึกเพียงแค่พิมพ์ 20 ตัวอักษรคุณต้องพึ่งพาพฤติกรรมที่ไม่ชัดเจนหรือไม่มีเอกสาร
erikkallen

20
SELECT FirstName + ' ' + LastName as "Full Name", case UserRole when 2 then "Admin" when 1 then "Moderator" else "User" end as "User's Role", case SignedIn when 0 then "Logged in" else "Logged out" end as "User signed in?", Convert(varchar(100), LastSignOn, 101) as "Last Sign On", DateDiff('d', LastSignOn, getDate()) as "Days since last sign on", AddrLine1 + ' ' + AddrLine2 + ' ' + AddrLine3 + ' ' + City + ', ' + State + ' ' + Zip as "Address", 'XXX-XX-' + Substring(Convert(varchar(9), SSN), 6, 4) as "Social Security #" FROM Users

หรืออัดทุกอย่างไว้ในบรรทัดเดียว


ใช้แบบสอบถามของความคิดเห็นก่อนหน้าเพียงเพราะนั่นเป็นคำสั่ง SQL แรกที่ฉันมีอยู่
Jasper Bekkers

17
  • FROM TableA, TableB WHEREไวยากรณ์สำหรับจับมากกว่าFROM TableA INNER JOIN TableB ON

  • การตั้งสมมติฐานว่าแบบสอบถามจะถูกส่งกลับเรียงลำดับบางวิธีโดยไม่ต้องใส่คำสั่ง ORDER BY เพียงเพราะนั่นเป็นวิธีที่ปรากฏในระหว่างการทดสอบในเครื่องมือคิวรี


5
Oracle DBA ของฉันมักจะบ่นว่าฉันใช้ "ANSI รวม" นั่นคือสิ่งที่คุณนำเสนอเป็นวิธีที่ถูกต้อง แต่ฉันก็ทำไปเรื่อย ๆ และฉันก็สงสัยว่าพวกเขารู้ดียิ่งขึ้น
Steve McLeod

1
ฉันสงสัยว่า Oracle หวังว่า SQL มาตรฐานจะหายไป :-) นอกจากนี้คุณไม่สามารถผสมการเข้าร่วมโดยนัยและชัดเจน (aka ANSI JOINs) ใน MySQL 5 - มันไม่ทำงาน ซึ่งเป็นอีกเหตุผลหนึ่งสำหรับ JIONs ที่ชัดเจน
staticsan

3
ฉันจะบอกว่าแม้แต่ผู้เข้าร่วม A เข้าร่วม B ON ก็เป็นรูปแบบต่อต้าน ฉันชอบ A INNER JOIN B ที่ใช้
John Nilsson

Oracle รองรับไวยากรณ์ ANSI ในขณะนี้ แต่พวกเขาเคยมีไวยากรณ์แปลก ๆ นี้สำหรับการรวมภายนอกในอดีตและมีคนจำนวนมากที่ยังคงใช้งานอยู่
Cervo

ดี ... Oracle ยังคงไม่ยอมให้คุณใช้ ANSI เข้าร่วมเพื่อการรีเฟรชได้อย่างรวดเร็วพร้อมรับชม Materialized Views
Gerrat

14

การเรียนรู้ SQL ในช่วงหกเดือนแรกของอาชีพของพวกเขาและไม่เคยเรียนรู้อะไรเลยในอีก 10 ปีข้างหน้า โดยเฉพาะอย่างยิ่งไม่ได้เรียนรู้หรือใช้งานอย่างมีประสิทธิภาพโดยใช้ฟีเจอร์ SQL ของ Window / วิเคราะห์ โดยเฉพาะอย่างยิ่งการใช้เกิน () และพาร์ทิชันโดย

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

ดูO'Reilly SQL Cookbook ภาคผนวก Aสำหรับภาพรวมที่ดีของฟังก์ชั่นหน้าต่าง


12

ฉันต้องการทำให้รายการโปรดปัจจุบันของฉันอยู่ที่นี่เพื่อทำให้รายการสมบูรณ์ antipattern ที่ฉันชอบคือไม่ได้ทดสอบการค้นหาของคุณ

สิ่งนี้ใช้เมื่อ:

  1. แบบสอบถามของคุณเกี่ยวข้องกับมากกว่าหนึ่งตาราง
  2. คุณคิดว่าคุณมีการออกแบบที่ดีที่สุดสำหรับการสืบค้น แต่อย่ากังวลที่จะทดสอบสมมติฐานของคุณ
  3. คุณยอมรับข้อความค้นหาแรกที่ใช้งานได้โดยไม่มีเงื่อนงำว่าจะใกล้เคียงกับการเพิ่มประสิทธิภาพหรือไม่

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


เทคนิคที่มีประโยชน์มากสำหรับการทดสอบ T-SQL ขั้นต่ำ: ในไฟล์. SQL ที่คุณกำหนด SP, UDF, ฯลฯ ทันทีหลังจากสร้างการทดสอบบล็อกเช่น IF 1 = 2 BEGIN (ตัวอย่างกรณีสำหรับรหัสของคุณพร้อมผลลัพธ์ที่คาดหวัง ตามความคิดเห็น) END
Joe Pineda

SQL Server แยกวิเคราะห์รหัสภายในบล็อกทดสอบถึงแม้ว่าจะไม่เคยดำเนินการ ดังนั้นเมื่อวัตถุของคุณได้รับการแก้ไขและรับพารามิเตอร์มากขึ้นหรือประเภทที่แตกต่างกัน ฯลฯ หรือวัตถุที่ขึ้นอยู่กับการแก้ไขคุณจะได้รับข้อผิดพลาดเพียงแค่ขอแผนปฏิบัติการ!
Joe Pineda

ไม่สามารถทำการทดสอบด้วยข้อมูลจริงได้เสมอไป บ่อยครั้งที่เซิร์ฟเวอร์ dev / "ทดสอบ" เซิร์ฟเวอร์ได้รับค่าจ้างต่ำและได้รับเศษส่วนของเซิร์ฟเวอร์จริง โดยทั่วไปการทดสอบจะขมวดคิ้วกับเซิร์ฟเวอร์ที่ใช้งานจริง สถานที่บางแห่งดีกว่าและมีเซิร์ฟเวอร์ทดสอบหรือเซิร์ฟเวอร์ทดสอบพร้อมข้อมูลสด
Cervo

11

การละเมิดตารางชั่วคราว

สิ่งเหล่านี้โดยเฉพาะ:

SELECT personid, firstname, lastname, age
INTO #tmpPeople
FROM People
WHERE lastname like 's%'

DELETE FROM #tmpPeople
WHERE firstname = 'John'

DELETE FROM #tmpPeople
WHERE firstname = 'Jon'

DELETE FROM #tmpPeople
WHERE age > 35

UPDATE People
SET firstname = 'Fred'
WHERE personid IN (SELECT personid from #tmpPeople)

อย่าสร้างตารางชั่วคราวจากแบบสอบถามเพียงเพื่อลบแถวที่คุณไม่ต้องการ

และใช่ฉันเห็นหน้ารหัสในรูปแบบนี้ในฐานข้อมูลการผลิต


1
+1 ฉันเห็นด้วย แม้ว่าฉันจะพบอย่างน้อยหนึ่งหรือสองกรณีที่เทคนิคนี้มีการปรับปรุงประสิทธิภาพ - แบบสอบถามที่เกี่ยวข้องมีความซับซ้อนในการพูดอย่างน้อย
a'r

1
ทรู - พวกเขาจะมีสถานที่เพียงแค่ไม่ได้อยู่ในการค้นหาทุก :)
geofftnz

1
บางครั้งคุณต้องทำอย่างนั้นถ้าเงื่อนไขมีความซับซ้อนมาก จริงมันสามารถถูกทารุณกรรมให้สุดขั้ว แต่หลายครั้งที่การลบแบบง่าย ๆ นั้นง่ายกว่าตรรกะในการทำให้เคสในคิวรีเริ่มต้น นอกจากนี้บางครั้งหากข้อไม่ได้รับการจัดเรียงแบบสอบถามเริ่มต้นจะช้าลง แต่การทำมันบนโต๊ะอุณหภูมิที่เล็กกว่านั้นมีประสิทธิภาพมากกว่า และเวลาอื่น ๆ ที่คุณเพิ่มกรณีที่นักธุรกิจยังเพิ่มหลังจากข้อเท็จจริง
Cervo

9

มุมมองที่แตก: ครอบงำจิตใจด้วยการทำให้เป็นมาตรฐาน

ระบบ SQL / RBDBs ส่วนใหญ่มีคุณสมบัติมากมาย (ธุรกรรมการจำลองแบบ) ที่มีประโยชน์มากแม้จะมีข้อมูลที่ผิดปกติ พื้นที่ดิสก์มีราคาถูกและบางครั้งมันอาจจะง่ายกว่า (รหัสง่ายขึ้นเวลาในการพัฒนาที่เร็วขึ้น) เพื่อจัดการ / กรอง / ค้นหาข้อมูลที่ดึงมาได้มากกว่าที่จะเขียน schema 1NF และจัดการกับสิ่งที่ยุ่งยากทั้งหมด ฯลฯ )

ฉันพบว่าระบบที่ใช้งานเกินปกติมักจะปรับให้เหมาะสมก่อนเวลาอันควรโดยเฉพาะในช่วงเริ่มต้นของการพัฒนา

(คิดเพิ่มเติมเกี่ยวกับมัน ... http://writeonly.wordpress.com/2008/12/05/simple-object-db-using-json-and-python-sqlite/ )


22
ฉันคิดว่าการไม่ทำให้เป็นมาตรฐานมักเป็นการปรับให้เหมาะสมก่อนเวลาอันควร
tuinstoel

บางครั้งมันเป็นบางครั้งมันไม่ได้เป็น โชคดีที่มันมักจะทดสอบได้ง่ายและตัวเลือกที่แตกต่างกันทำงานกับความต้องการฐานข้อมูลที่แตกต่างกัน
Gregg Lind

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

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

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

9

ฉันเพิ่งรวมมันเข้าด้วยกันโดยอิงจากการตอบสนองของ SQL ที่นี่ใน SO

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

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


8

ขั้นตอนหรือฟังก์ชันที่เก็บไว้โดยไม่มีความคิดเห็นใด ๆ ...


และมุมมอง;) ฟังก์ชันจริงยกเว้นฟังก์ชันที่มีค่าเป็นตาราง (= มุมมองพร้อมพารามิเตอร์)
Stefan Steiger

7

1) ฉันไม่รู้ว่ามันเป็นรูปแบบต่อต้าน "เป็นทางการ" แต่ฉันไม่ชอบและพยายามหลีกเลี่ยงการใช้ตัวอักษรสตริงเป็นค่าเวทมนต์ในคอลัมน์ฐานข้อมูล

ตัวอย่างจาก 'ภาพ' ตารางของ MediaWiki:

img_media_type ENUM("UNKNOWN", "BITMAP", "DRAWING", "AUDIO", "VIDEO", 
    "MULTIMEDIA", "OFFICE", "TEXT", "EXECUTABLE", "ARCHIVE") default NULL,
img_major_mime ENUM("unknown", "application", "audio", "image", "text", 
    "video", "message", "model", "multipart") NOT NULL default "unknown",

(ฉันเพิ่งสังเกตเห็นปลอกที่แตกต่างกันสิ่งอื่นที่ควรหลีกเลี่ยง)

ฉันออกแบบเคสเช่นการค้นหา int ลงในตาราง ImageMediaType และ ImageMajorMime ด้วยคีย์หลัก int

2) การแปลงวันที่ / สตริงที่ขึ้นอยู่กับการตั้งค่า NLS เฉพาะ

CONVERT(NVARCHAR, GETDATE())

ไม่มีตัวระบุรูปแบบ


และไม่มีการเยื้องประโยคด้วยเช่นกัน Argghh
dkretz

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

@JackRyan: นี่เป็นสิ่งที่ไม่ดีเพราะเมื่อคุณเปลี่ยนรายการ enum ในภายหลังคุณต้องจำไว้ว่าให้เปลี่ยนเป็นสองแห่งตอนนี้ มันละเมิดแห้ง ฐานข้อมูลควรเป็นแหล่งแห่งความจริงเดียว
Gerrat

7

แบบสอบถามย่อยที่เหมือนกันในแบบสอบถาม


10
แต่น่าเสียดายที่บางครั้งคุณก็ไม่สามารถหลีกเลี่ยงที่ - ใน SQL 2000 ไม่มี "กับ" คำหลักและการใช้ UDF ของการ encapsulate subqueries ร่วมกันนำไปสู่การลงโทษบางครั้งการทำงาน, MS โทษว่า ...
โจ Pineda

หวังว่าพวกเขาจะได้เพิ่มอีกหนึ่งวัน
EvilTeach

ใน SQL 2000 คุณสามารถใช้ตัวแปรตารางได้
recursive

@recursive: คุณไม่สามารถมีดัชนีในตัวแปรตารางซึ่งมักจะทำให้มันช้ากว่าเคียวรีย่อย อย่างไรก็ตามคุณสามารถใช้ตารางชั่วคราวกับดัชนีที่กำหนดเองได้
ริก

เยี่ยมมากทำงานกับ SQL มาหลายปีแล้วและไม่รู้ด้วยซ้ำว่า Common Table Expressions (แม้ว่าฉันจะต้องการใช้) ตอนนี้ฉันทำ! ขอบคุณ!
sleske

7
  • The Altered View - มุมมองที่เปลี่ยนแปลงบ่อยเกินไปและไม่มีการแจ้งเตือนหรือเหตุผล การเปลี่ยนแปลงจะถูกสังเกตในเวลาที่ไม่เหมาะสมที่สุดหรือแย่กว่านั้นคือผิดและไม่เคยสังเกตเห็น บางทีใบสมัครของคุณอาจแตกเพราะมีคนคิดว่าชื่อที่ดีกว่าสำหรับคอลัมน์นั้น ตามมุมมองของกฎควรขยายประโยชน์ของตารางฐานในขณะที่รักษาสัญญากับผู้บริโภค แก้ไขปัญหา แต่อย่าเพิ่มฟีเจอร์หรือพฤติกรรมการเปลี่ยนแปลงที่แย่ลงสำหรับการสร้างมุมมองใหม่ ในการบรรเทาไม่แชร์มุมมองกับโครงการอื่นและใช้CTEเมื่อแพลตฟอร์มอนุญาต หากร้านค้าของคุณมี DBA คุณอาจไม่สามารถเปลี่ยนมุมมองได้ แต่มุมมองทั้งหมดของคุณจะล้าสมัยและไม่มีประโยชน์ในกรณีนี้

  • The! Paramed - แบบสอบถามสามารถมีมากกว่าหนึ่งวัตถุประสงค์ได้หรือไม่ อาจเป็นไปได้ แต่คนต่อไปที่อ่านมันจะไม่รู้จนกระทั่งการทำสมาธิลึก แม้ว่าคุณจะไม่ต้องการโอกาสในตอนนี้คุณก็จะทำได้แม้ว่าจะเป็น "เพียงแค่" ในการดีบัก การเพิ่มพารามิเตอร์จะช่วยลดเวลาในการบำรุงรักษาและทำให้สิ่งต่าง ๆ แห้ง หากคุณมีส่วนคำสั่งที่คุณควรมีพารามิเตอร์

  • กรณีที่ไม่มีกรณี -

    SELECT  
    CASE @problem  
      WHEN 'Need to replace column A with this medium to large collection of strings hanging out in my code.'  
        THEN 'Create a table for lookup and add to your from clause.'  
      WHEN 'Scrubbing values in the result set based on some business rules.'  
        THEN 'Fix the data in the database'  
      WHEN 'Formating dates or numbers.'   
        THEN 'Apply formating in the presentation layer.'  
      WHEN 'Createing a cross tab'  
        THEN 'Good, but in reporting you should probably be using cross tab, matrix or pivot templates'   
    ELSE 'You probably found another case for no CASE but now I have to edit my code instead of enriching the data...' END  

ชอบอันที่สาม ฉันใช้มันในเครื่องอยู่แล้ว ...
alphadogg

ขอบคุณสำหรับอุปกรณ์ประกอบฉาก :)
jason saldo

5

ทั้งสองฉันพบมากที่สุดและสามารถมีค่าใช้จ่ายที่สำคัญในแง่ของประสิทธิภาพคือ:

  • การใช้เคอร์เซอร์แทนการแสดงออกตามชุด ฉันคิดว่าอันนี้เกิดขึ้นบ่อยครั้งเมื่อโปรแกรมเมอร์คิดอย่างเป็นระเบียบ

  • การใช้คิวรีย่อยที่สัมพันธ์กันเมื่อการเข้าร่วมกับตารางที่ได้รับมาสามารถทำงานได้


ฉันเห็นด้วยถ้าคุณหมายถึงสิ่งที่ฉันคิดว่าคุณหมายถึง; แม้ว่าเคียวรีย่อยที่สัมพันธ์กันจะเป็นประเภทของตาราง IIRC ที่ได้รับมา
dkretz

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

สองสามปีที่ผ่านมาฉันรู้สึกประหลาดใจที่ SQL S. นั้นได้รับการปรับให้เหมาะสมสำหรับการจัดการคิวรีที่มีความสัมพันธ์: สำหรับแบบธรรมดาคุณจะได้รับแผนการดำเนินการเช่นเดียวกับแบบสอบถามที่มีเหตุผลเทียบเท่าโดยใช้ JOIN! นอกจากนี้เคียวรีที่สัมพันธ์กันซึ่งนำออราเคิลมาที่หัวเข่าของตนนั้นจะรันบน SQL S. ช้าเท่านั้น!
Joe Pineda

นั่นเป็นเหตุผลที่ฉันทดสอบทั้งสองวิธีเสมอ และฉัน <i> ทำ </> มักจะลองทั้งสองวิธี ในทางปฏิบัติสำหรับ SQL Server ต่อไปฉันมักจะพบว่า sq ที่สัมพันธ์กันจะไม่ช้าลง
dkretz

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

5

การวางสิ่งต่าง ๆ ลงในตารางชั่วคราวโดยเฉพาะผู้ที่เปลี่ยนจาก SQL Server เป็น Oracle มีนิสัยที่ใช้ตารางชั่วคราวมากเกินไป เพียงใช้คำสั่ง select ที่ซ้อนกัน


5

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

  • กลยุทธ์การลดขนาด I / O จริงเนื่องจากคอขวดของข้อความค้นหาส่วนใหญ่คือ I / O ไม่ใช่ CPU
  • ผลกระทบที่สมบูรณ์แบบจากการเข้าถึงที่เก็บทางกายภาพประเภทต่าง ๆ (เช่น I / O ต่อเนื่องจำนวนมากจะเร็วกว่า I / O สุ่มขนาดเล็กจำนวนมากแม้ว่าจะน้อยกว่าดังนั้นหากที่เก็บข้อมูลทางกายภาพของคุณเป็น SSD!)
  • วิธีการปรับแต่งแบบสอบถามถ้า DBMS สร้างแผนแบบสอบถามไม่ดี
  • วิธีการวินิจฉัยประสิทธิภาพของฐานข้อมูลที่ไม่ดีวิธี "ดีบัก" แบบสอบถามที่ช้าและวิธีอ่านแผนแบบสอบถาม (หรืออธิบายขึ้นอยู่กับ DBMS ที่คุณเลือก)
  • กลยุทธ์การล็อกเพื่อเพิ่มประสิทธิภาพการรับส่งข้อมูลและหลีกเลี่ยงการหยุดชะงักในแอปพลิเคชันที่มีผู้ใช้หลายคน
  • ความสำคัญของการแบทช์และเทคนิคอื่น ๆ เพื่อจัดการการประมวลผลของชุดข้อมูล
  • การออกแบบตารางและดัชนีเพื่อสร้างสมดุลของพื้นที่และประสิทธิภาพที่ดีที่สุด (เช่นครอบคลุมดัชนีทำให้ดัชนีมีขนาดเล็กที่สุดเท่าที่จะเป็นไปได้ลดประเภทข้อมูลให้เหลือขนาดต่ำสุด ฯลฯ )

3

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

DECLARE c1 CURSOR FOR SELECT Col1, Col2, Col3 FROM Table1

FOREACH c1 INTO a.col1, a.col2, a.col3
    DECLARE c2 CURSOR FOR
        SELECT Item1, Item2, Item3
            FROM Table2
            WHERE Table2.Item1 = a.col2
    FOREACH c2 INTO b.item1, b.item2, b.item3
        ...process data from records a and b...
    END FOREACH
END FOREACH

โซลูชันที่ถูกต้อง (เกือบตลอดเวลา) คือการรวมสองคำสั่ง SELECT เข้าเป็นหนึ่งเดียว:

DECLARE c1 CURSOR FOR
    SELECT Col1, Col2, Col3, Item1, Item2, Item3
        FROM Table1, Table2
        WHERE Table2.Item1 = Table1.Col2
        -- ORDER BY Table1.Col1, Table2.Item1

FOREACH c1 INTO a.col1, a.col2, a.col3, b.item1, b.item2, b.item3
    ...process data from records a and b...
END FOREACH

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

นอกจากนี้การเรียงลำดับในแอปพลิเคชันมักเป็นแบบไม่มี


สไตล์แม้ว่าจะไม่ใช่รูปแบบนี้ แต่โดยเฉพาะอย่างยิ่งอาละวาดใน PHP ในประสบการณ์ของฉัน
dkretz

ไวยากรณ์คือ IBM Informix-4GL จริง ๆ แล้ว - แต่มันชัดเจนพอที่จะไม่ต้องการคำอธิบายมากเกินไป (ฉันคิดว่า) และรูปแบบนั้นเป็นที่แพร่หลายในโปรแกรม SQL จำนวนมากโดยไม่คำนึงถึงภาษาการเขียนโปรแกรม
Jonathan Leffler

ยกเว้นความจริงที่ว่าคุณกำลังใช้ antipattern ที่รู้จักกันดี (การรวมโดยนัย) เพื่อแสดงถึง antipattern ของคุณการเอาชนะจุดนั้น
Johan

และแน่นอนว่าการใช้เคอร์เซอร์นั้นก็คือ Antipattern SQl เคอร์เซอร์ทั้งหมดสามารถเขียนใหม่เป็นการดำเนินการตามที่ตั้งไว้ได้ บางอย่างที่ไม่สามารถเป็น DBA ที่มีประสบการณ์มายาวนานและผู้ที่เข้าใจว่า internals ของฐานข้อมูลควรทำงานอย่างไร แอปพลิเคชัน dev ไม่จำเป็นต้องเขียนเคอร์เซอร์ SQL
HLGEM

3

การใช้คีย์หลักเป็นตัวแทนสำหรับที่อยู่บันทึกและใช้กุญแจต่างประเทศเป็นตัวแทนสำหรับตัวชี้ที่ฝังอยู่ในบันทึก

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.