ขั้นตอนการจัดเก็บโดยที่พารามิเตอร์ข้อ

ฉันมีหน้าค้นหา ASP.net ซึ่งผู้ใช้สามารถป้อนเกณฑ์การค้นหาตั้งแต่หนึ่งเกณฑ์ขึ้นไป เพจนี้เรียกกระบวนงานที่เก็บไว้เพื่อสอบถามฐานข้อมูล MS SQL Server 2008

เกณฑ์การค้นหาส่วนหนึ่งคือวันที่เดียวหรือช่วงวันที่ หากผู้ใช้ระบุ Date1 เราจะค้นหาในวันที่เดียว หากผู้ใช้ระบุ Date1 และ Date2 เราจะค้นหาในช่วงวันที่

ปัญหาของฉันคือการเข้ารหัสตรรกะนี้ใน proc ที่เก็บไว้

@Date1 datetime
@Date2 datetime
..other search params...

จึงมีเงื่อนไขสามประการ:

  1. ทั้ง @Date1 และ @Date2 เป็นโมฆะ (ผู้ใช้ไม่ได้ค้นหาวันที่)
  2. @Date1 ไม่เป็นโมฆะและ @Date2 เป็นโมฆะ (ผู้ใช้กำลังค้นหาในวันที่เดียว)
  3. @Date1 ไม่ใช่ null และ @Date2 ไม่ใช่ null (ผู้ใช้กำลังค้นหาช่วงวันที่)

ฉันไม่สามารถหาวิธีจัดโครงสร้าง WHERE clause เพื่อจัดการกับเงื่อนไขที่เป็นไปได้ทั้งสามเงื่อนไขได้

ฉันคุ้นเคยกับ ISNULL() และ COALESCE()

คำแนะนำหรือข้อเสนอแนะใด ๆ ที่ชื่นชมอย่างมาก


person paparush    schedule 08.06.2011    source แหล่งที่มา
comment
คุณสามารถแสดงแบบสอบถามที่คุณใช้ได้หรือไม่?   -  person Alex Aza    schedule 08.06.2011


คำตอบ (2)


CREATE PROCEDURE BLABLABLA(
  @DATE1 DATETIME = NULL,
  @DATE2 DATETIME = NULL
)
AS
BEGIN
  SELECT COL1, COL2
  FROM THE_TABLE
  WHERE 
    THE_TABLE.DATETIMEFIELD BETWEEN 
      ISNULL(@DATE1, THE_TABLE.DATETIMEFIELD) 
      AND COALESCE(@DATE2, @DATE1, THE_TABLE.DATETIMEFIELD)
END

อีกทางเลือกหนึ่งที่สูญเสียความหมายไปบ้างแต่มีแนวโน้มว่าจะใช้ดัชนี อาจเป็น:

CREATE PROCEDURE BLABLABLA(
  @DATE1 DATETIME = NULL,
  @DATE2 DATETIME = NULL
)
AS
BEGIN
  SELECT COL1, COL2
  FROM THE_TABLE
  WHERE 
    (THE_TABLE.DATETIMEFIELD >= @DATE1 OR @DATE1 IS NULL) 
     AND (THE_TABLE.DATETIMEFIELD <= @DATE2 
         OR THE_TABLE.DATETIMEFIELD = @DATE1
         OR (@DATE1 IS NULL AND @DATE2 IS NULL)) 
END
person Rodrigo    schedule 08.06.2011
comment
โรดริโกขอบคุณสำหรับการตอบกลับ BETWEEN จะจัดการกับกรณีที่ให้ @ Date1 หรือไม่ นั่นคือผู้ใช้เพียงแค่ค้นหาว่า THE_TABLE.DATETIMEFIELD = @Date1? - person paparush; 08.06.2011
comment
ถ้า @date2 เป็นโมฆะ ฟังก์ชัน isnull จะอยู่ในคอลัมน์เดียวกัน ดังนั้น โดยที่ส่วนคำสั่งจะเป็น datetimecolumn between @date1 and datetimecolumn และในฐานะ datetimecolumn = datetimecolumn ส่วนสุดท้ายของส่วนย่อยระหว่างส่วนคำสั่งจะยังคงเปิดอยู่สำหรับค่าที่เป็นไปได้ - person Rodrigo; 08.06.2011
comment
คำตอบดูดี แต่การใช้ ISNULL จะป้องกันความเป็นไปได้ที่ดัชนีจะถูกใช้บน DATETIMEFIELD หรือไม่ (เช่น การพิจารณาความสามารถในการเสียเงิน) - person Moe Sisko; 08.06.2011
comment
ตกลง ฉันได้ปรับปรุงการค้นหาแล้ว ดังนั้นจึงน่าจะใช้ดัชนีใน DATETIMEFIELD - person Rodrigo; 08.06.2011
comment
ฉันยังเห็นปัญหาอยู่ หากระบุ @Date1 และ @Date2 เป็นโมฆะ โค้ดจะทำ ›= @Date1 เสมอ ตรรกะที่ฉันต้องการสร้างคือ: หากระบุเฉพาะ @Date1 แล้วโดยที่ datetimecolumn = @Date1 - person paparush; 08.06.2011
comment
หากต้องการค้นหาในวันที่เดียว ฉันคิดว่าสิ่งที่ฉันจะทำคือแค่สั่งให้ผู้ใช้ตั้งค่าวันที่เดียวกันใน @Date1 และ @Date2 - person paparush; 08.06.2011
comment
ตกลง ตอนนี้แบบสอบถามได้รับการแก้ไขแล้วเพื่อให้เป็นไปตามข้อกำหนด - person Rodrigo; 09.06.2011

คุณสามารถลองสร้างแบบสอบถาม SQL ของคุณเป็นสตริงใน SP แล้วดำเนินการดังนี้:

...
declare @sql varchar(500)
set @sql = 'select from myTable where 1=1'

if(@Date1 <> null)
    set @sql = @sql + ' and date1 >= '+ @date1

if(@Date2 <> null)
    set @sql = @sql + ' and date2 <= '+ @date2

print(@sql) -- for debug 
exec(@sql)
person noinstance    schedule 08.06.2011
comment
นี่ ไม่ใช่แนวทางปฏิบัติที่สมบูรณ์แบบ แต่ได้ผล และในบางกรณี คือ วิธีที่ง่ายและมีประสิทธิภาพที่สุดในการสร้างข้อความค้นหา - person noinstance; 08.06.2011
comment
ต้องใช้ dynamic sql เฉพาะในกรณีที่ไม่มีทางเลือกอื่น ในกรณีนี้ คุณสามารถสร้างนิพจน์ SQL ที่สามารถรองรับข้อกำหนดได้โดยไม่ต้องมี SQL ไดนามิกใดๆ - person Rodrigo; 08.06.2011
comment
+1 สำหรับไดนามิก sql, Entity Framework และ Linq ถึง Sql สร้างไดนามิก sql ณ รันไทม์ - person jimjim; 08.06.2011
comment
ฉันต้องการให้ -1 สำหรับการจัดการสตริงประเภทนี้ แต่คะแนนโหวตลงไปที่ -2 โพสต์นี้ไม่แย่หรือดี ไม่อยากให้มันลงมากเกินไป แต่ยังเห็นด้วยกับโรดริโกด้วยว่าจะไม่ใช้ไดนามิก sql หากไม่จำเป็น - person jimjim; 08.06.2011
comment
@Rodrigo เนื่องจากฉันยอมรับว่าโซลูชันของคุณหรูหรากว่าในกรณีนี้ ฉันไม่เห็นด้วยกับคำว่า Must ในข้อความแรกของคุณ Dynamic SQL สามารถอ่านและแก้ไขจุดบกพร่องได้ดีกว่านิพจน์ SQL ที่ยาวและซับซ้อนมาก ฉันไม่เคยทำการเปรียบเทียบประสิทธิภาพมาก่อน แต่เท่าที่ฉันรู้ว่าไม่มีความไม่สะดวกใด ๆ เลยจากการใช้ Dynamic SQL - person noinstance; 08.06.2011
comment
ไม่สะดวกจริง? เช่น การแทรก SQL, ข้อยกเว้นรันไทม์ที่ไม่คาดคิด, การขาดแผนการดำเนินการ ฯลฯ... - person Rodrigo; 08.06.2011
comment
การฉีด sql จะเกิดขึ้นเสมอหากข้อมูลไม่ถูกสุขลักษณะ เกี่ยวกับข้อโต้แย้งอื่นๆ ฉันไม่รู้จริงๆ ไม่เคยต้องจัดการกับข้อโต้แย้งเหล่านั้นเลย ขอบคุณสำหรับหัวข้อนี้ - person noinstance; 08.06.2011
comment
โดยปกติแล้ว นี่เป็นวิธีที่มีประสิทธิภาพมากที่สุดในการค้นหาที่ซับซ้อนโดยมีพารามิเตอร์จำนวนมากซึ่งอาจกรอกหรือไม่ก็ได้ ฉันไม่ใช่แฟนของ Dynamic SQL โดยทั่วไป แต่คำค้นหาคือสิ่งที่มันยอดเยี่ยม - person HLGEM; 08.06.2011
comment
อย่างไรก็ตาม อย่าใช้ Dynamic SQl จนกว่าคุณจะอ่านบทความนี้:sommarskog.se/dynamic_sql.html - person HLGEM; 08.06.2011