พื้นหลัง : ฉันกำลังทำงานในhttp://sqlfiddle.com (เว็บไซต์ของฉัน) และกำลังพยายามป้องกันไม่ให้มีการละเมิดวิธีใดวิธีหนึ่ง ฉันหวังว่าด้วยการถามเกี่ยวกับปัญหาที่ฉันกำลังพูดถึงอยู่ในปัจจุบันฉันไม่ได้ตั้งใจทำให้การละเมิดที่อาจเกิดขึ้นแย่ลงโดยไม่ได้ตั้งใจ แต่คุณจะทำอย่างไร ฉันเชื่อใจพวกคุณ
ฉันต้องการป้องกันไม่ให้ผู้ใช้ออกการเรียก 'ส่งสัญญาณ' อย่างชัดเจนภายในบล็อคธุรกรรม จากบริบทของ SQL Fiddle บล็อกธุรกรรมคือรหัสที่เรียกใช้งานบนแผงด้านขวา โดยทั่วไปฉันจะวนซ้ำและดำเนินการรายการคำสั่ง plaintext SQL และฉันต้องการให้แน่ใจว่าการเปลี่ยนแปลงทั้งหมดที่ทำจะถูกย้อนกลับในตอนท้ายของแบทช์ โดยปกติการเปลี่ยนแปลงของพวกเขาจะได้รับการย้อนกลับ แต่บางครั้งก็มีคำสั่ง 'กระทำ' ที่ชัดเจนภายในข้อความและแน่นอนว่าการย้อนกลับของฉันจะไม่ทำงาน ความมุ่งมั่นที่ชัดเจนนี้มีแนวโน้มมากจากผู้ใช้ที่พยายามจะทำลาย schema บน SQL Fiddle ดังนั้นคนอื่น ๆ ที่ทำงานกับมันจะเห็นข้อผิดพลาด
ผลลัพธ์หลักที่ต้องการ : ฉันต้องการปิดใช้งานการกระทำที่ชัดเจนในระดับ JDBC ถ้าเป็นไปได้ นี่เป็นเพราะฉันต้องสนับสนุนผู้ขายแบ็กเอนด์ฐานข้อมูลหลายคนและแน่นอนว่าแต่ละคนมีนิสัยใจคอในระดับต่ำ
ตัวเลือกสำรอง : หากไม่สามารถกำหนดค่า JDBC เพื่อปิดใช้งานการกระทำที่ชัดเจนได้ฉันจะเปิดให้มีการตรวจหาการกระทำที่ชัดเจนในขณะประมวลผลชุดข้อมูลสำหรับแบ็กเอนด์ต่อไปนี้: SQL Server, Oracle, MySQL และ PostgreSQL
สำหรับ SQL Server ฉันคิดถึงวิธีนี้: แยกวิเคราะห์แผนการสืบค้น XML สำหรับคำสั่งก่อนที่ฉันจะดำเนินการและตรวจสอบการมีอยู่ของรายการที่ตรงกับ XPath นี้:
//*[@StatementType="COMMIT TRANSACTION"]
ฉันคิดว่านี่จะทำงานได้ดีสำหรับ SQL Server อย่างไรก็ตามวิธีนี้ใช้ไม่ได้กับฐานข้อมูลประเภทอื่น เอาต์พุตแผนการดำเนินการ XML ของ Oracle สำหรับการส่งข้อมูลที่ชัดเจนไม่ได้อ้างอิงถึงข้อเท็จจริงที่ว่าคุณกำลังเรียกใช้คำสั่ง commit (แต่เพียงทำซ้ำเอาต์พุตแผนการดำเนินการจากเคียวรีที่คอมมิท) PostgreSQL และ MySQL ไม่ได้เตรียมเอาท์พุทแผนการดำเนินการใด ๆ เลย (XML หรืออย่างอื่น) สำหรับการกระทำที่ชัดเจน
ทำให้ฉันตรวจสอบคำสั่งจริงสำหรับคำว่า "commit" สิ่งนี้จะได้ผลเว้นแต่มีความผันแปรได้ทุกประเภท:
declare @sql varchar(50)
set @sql = 'com' + 'mit'
exec(@sql);
ด้านบนเป็นตัวอย่างสำหรับ SQL Server (ซึ่งฉันสามารถแก้ไขได้) แต่ฉันเดาว่าสิ่งที่คล้ายกันอาจเป็นไปได้สำหรับ Oracle, MySQL และ PostgreSQL ฉันคิดผิดไปหรือเปล่า พวกเขาอาจจะไม่อนุญาตให้ใช้คำสั่ง "แบบไดนามิก"? อย่าลังเลที่จะใช้ SQL Fiddle (โดยเฉพาะอย่างยิ่งไม่ใช่ schema ตัวอย่างหรือมีคนอื่นกำลังทำงานอยู่) เพื่อดูว่าคุณสามารถทำสิ่งที่คล้ายกันเกิดขึ้นใน Oracle, MySQL และ PostgreSQL ได้ไหม ถ้าไม่เช่นนั้นการตรวจจับสตริงอย่างง่ายอาจใช้ได้ผล
ความเป็นไปได้อีกอย่างหนึ่ง
มีตัวเลือกอื่นเกิดขึ้นกับฉัน - หากคุณรู้วิธีตั้งค่าฐานข้อมูลใด ๆ เหล่านี้ในโหมดอ่านอย่างเดียวเช่นในขณะที่ไม่มีโหมดใดที่สามารถยอมรับได้ ฉันจะต้องยังคงอนุญาตให้เริ่มต้นการทำธุรกรรมและรหัสเพื่อให้ทำงานภายในพวกเขาตราบใดที่ไม่มีอะไรสามารถกระทำได้ในขณะที่อยู่ในโหมดนั้น เป็นไปได้ไหม
ปรับปรุง
สิ่งที่ฉันเรียนรู้เมื่อเร็ว ๆ นี้ - จริง ๆ แล้วไม่มีปัญหากับ PostgreSQL เห็นได้ชัดว่าการกระทำที่ออกภายในบล็อกธุรกรรมจะไม่นำไปใช้หากในที่สุดบล็อกเดียวกันนั้นได้รับการย้อนกลับ (ใน Postgres) ดังนั้นไชโยสำหรับ Postgres!
ขอบคุณลิงก์ของ Phil ไปยังโพสต์ SO ฉันคิดว่าฉันสามารถใช้แฮ็ค DEFERRABLE INFIEDY DEFERRED ที่ถูกกำหนดไว้ล่วงหน้าเพื่อให้ Oracle บรรลุสิ่งที่ฉันต้องการ สิ่งนี้ควรระบุถึง Oracle (ฉันคิดว่าชั่วขณะหนึ่งที่ธุรกรรมซ้อนกันอาจทำงานที่นี่ แต่ดูเหมือนว่า Oracle ไม่รองรับธุรกรรมซ้อนกันหรือไม่ฉันไม่สามารถหาสิ่งที่ใช้วิธีนี้ได้)
ยังไม่มีทางออกสำหรับ MySQL จริงๆ พยายามใช้การทำธุรกรรมที่ซ้อนกัน แต่ไม่ได้ผล ฉันคิดอย่างจริงจังถึงวิธีการที่รุนแรงมากขึ้นสำหรับ MySQL เช่นอาจไม่อนุญาตอะไรเลยนอกจากการเลือกทางด้านขวาหรือการวาง / สร้างฐานข้อมูลซ้ำหลังการสืบค้นแต่ละครั้ง ไม่ว่าจะฟังดูดี
มติ
ดังนั้นตอนนี้ฉันได้ติดตั้งโซลูชันที่อธิบายไว้สำหรับ SQL Server และ Oracle และตามที่ฉันกล่าวถึงสิ่งนี้ไม่ใช่ปัญหาสำหรับ PostgreSQL สำหรับ MySQL ฉันใช้ขั้นตอนที่ค่อนข้างโชคร้ายในการ จำกัด แผงการสืบค้นเพื่อเลือกเฉพาะข้อความสั่ง DDL และ DML สำหรับ MySQL จะต้องป้อนในแผงสคีมา (ด้านซ้าย) ฉันหวังว่านี่จะไม่ทำลายซอเก่า ๆ จำนวนมากเกินไป แต่ฉันคิดว่ามันเป็นสิ่งที่ต้องทำเพื่อให้แน่ใจว่าข้อมูลมีความสอดคล้องกัน ขอบคุณ!