ฉันอ่านในเอกสารของ Oracle เกี่ยวกับตารางที่สงวนคีย์ในการอัปเดตส่วนเข้าชม
อย่างไรก็ตามฉันไม่พบวิธีง่าย ๆ ที่จะเข้าใจ
ฉันหวังว่าจะได้รับรายละเอียดเกี่ยวกับแนวคิดอย่างง่ายนอกเหนือจากเอกสาร Oracle อย่างเป็นทางการ
ฉันอ่านในเอกสารของ Oracle เกี่ยวกับตารางที่สงวนคีย์ในการอัปเดตส่วนเข้าชม
อย่างไรก็ตามฉันไม่พบวิธีง่าย ๆ ที่จะเข้าใจ
ฉันหวังว่าจะได้รับรายละเอียดเกี่ยวกับแนวคิดอย่างง่ายนอกเหนือจากเอกสาร Oracle อย่างเป็นทางการ
คำตอบ:
Key อนุรักษ์หมายความว่า 1 คีย์ค่าไปที่ 1 ตาราง การให้ตัวอย่างเคาน์เตอร์อาจช่วยให้คุณเข้าใจแนวคิดนี้ดีขึ้น
example1:
มุมมองของคุณมีการรวม สมมติว่าคุณมีโครงสร้างมุมมองดังต่อไปนี้
GroupID, AverageSalary
1 , 10000
2, 12000
3, 14000
ในตัวอย่างนี้ค่าของคุณมาจากแถวมากกว่าหนึ่งแถว ถ้าคุณพยายามอัปเดต AverageSalary ในมุมมองนี้ฐานข้อมูลจะไม่มีวิธีในการค้นหาแถวที่จะอัปเดต
ตัวอย่างที่ 2: มุมมองของคุณแสดงค่าจากมากกว่าหนึ่งตาราง มุมมองของคุณแสดงค่าจาก PERSON และ PERSON_CONTACT_DETAILS (ID, PersonID, ContactType, ContactValue)
แถวตัวอย่าง:
1,1,email,ddd@example.com
1,1,phone,898-98-99
คุณเข้าร่วม 2 ตารางนี้และแสดงข้อมูลที่เป็นมิตรกับธุรกิจมากขึ้นในมุมมอง
PersonId, ชื่อ, นามสกุล, เบอร์โทรศัพท์ 1, อีเมล 1
ที่นี่คุณต้องการอัปเดต Phone1 และ Email1 แต่ personID ของคุณแมปกับแถวที่แตกต่างกันสองแถวอาจมีแถวมากกว่านี้ในตัวอย่างนี้ ในมุมมองนี้อีกครั้งฐานข้อมูลไม่มีวิธีค้นหาแถวที่จะอัปเดต
หมายเหตุ: หากคุณ จำกัด มุมมอง sql และทำให้ชัดเจนในการค้นหาว่าแถวใดที่จะอัปเดตอาจทำงานได้
ตัวอย่างสองตัวอย่างนี้เป็นตัวอย่างแรกที่อยู่ในใจของฉัน พวกเขาสามารถเพิ่มขึ้น แต่แนวคิดชัดเจน ฐานข้อมูลจำเป็นต้องแมป 1 ค่าคีย์กับ 1 ตาราง ตัวอย่างเช่นคุณมีตาราง PERSON, PERSON_DETAILS หนึ่งถึงหนึ่ง ที่นี่การดูและอัปเดตจะใช้งานได้เนื่องจากเป็นแบบหนึ่งต่อหนึ่ง
เอกสารที่คุณได้อ่านแล้วบอกว่ามันสวยดี เพื่ออธิบายเพิ่มเติม:
แนวคิดของตารางที่สงวนไว้เป็นกุญแจสำคัญในการทำความเข้าใจข้อ จำกัด ในการแก้ไขมุมมองการเข้าร่วม
โดยปกติแล้วการupdate
กระทำบนโต๊ะเดียว เพื่อหลีกเลี่ยงเคียวรีย่อยที่คลุมเครือในตัวกรอง Oracle อนุญาตให้คุณupdate
ดู (หรือเคียวรีย่อย) ตราบใดที่ยังสามารถแม็พการเปลี่ยนแปลงที่คุณทำกับแถวที่แท้จริงในตารางได้อย่างง่ายดาย สิ่งนี้เป็นไปได้ถ้าset
อนุประโยคแก้ไขเฉพาะคอลัมน์ในตาราง 'การเก็บรักษาคีย์':
ตารางได้รับการสงวนรักษากุญแจไว้หากทุกปุ่มของตารางสามารถเป็นกุญแจของผลลัพธ์ของการเข้าร่วมได้เช่นกัน ดังนั้นตารางที่สงวนไว้จะมีการเก็บรักษาคีย์ผ่านการเข้าร่วม
ตัวอย่างเช่น:
create table foo( foo_id integer primary key, foo_val integer not null );
create table bar( bar_id integer primary key, bar_val integer not null,
foo_id integer not null references foo );
update (select * from foo join bar using(foo_id)) set foo_val=1;
ORA-01779: cannot modify a column which maps to a non key-preserved table
update (select * from foo join bar using(foo_id)) set bar_val=1;
0 rows updated.
การปรับปรุงครั้งแรกล้มเหลวเนื่องจาก Oracle มีวิธีที่ 1 ไม่มี: 1 การทำแผนที่foo_val
ในการสอบถามไปfoo_val
ในfoo
- ตรงกันข้ามการปรับปรุงที่สองประสบความสำเร็จเพราะออราเคิลสามารถ 1: 1 แผนที่แต่ละbar_val
ที่จะ อยู่ในbar_val
bar
สิ่งที่สำคัญคือการที่foo_id
เป็นเอกลักษณ์ในการfoo
- เพื่อให้แต่ละแถวในbar
, มีเพียงสามารถเป็นที่หนึ่งส่วนใหญ่แถวที่สอดคล้องกันในfoo
(ที่จริงว่า 1 ในตัวอย่างนี้ แต่เช่นเดียวกับคีย์ต่างประเทศ nullable - ประเด็นก็คือว่าไม่เคยมี มากกว่าหนึ่งแถว)
ขอยกตัวอย่างก่อนแล้วค่อยอธิบายทีหลัง พิจารณานักเรียน 2 คน (t_students) และหลักสูตร (t_course)
- ตารางนักเรียน (stundentid, ชื่อ, Courseid) มีคีย์หลักในรหัสนักศึกษา
- ตารางหลักสูตร (courseid, coursename) มีคีย์หลักในรหัสหลักสูตร
เมื่อเข้าร่วมสองตารางนี้ ->
select * from t_students S, t_course C where S.courseid=C.courseid;
ข้อมูลที่ได้จะมีจำนวนแถวเท่ากันกับตารางนักเรียน จะไม่มีค่าซ้ำของ studentid ในชุดผลลัพธ์ (studentid ถูกเก็บรักษาไว้) อย่างไรก็ตามแม้ว่าหลักสูตรนี้จะไม่ซ้ำกันในตารางหลักสูตร แต่จะมีการทำซ้ำหลายครั้งในชุดผลลัพธ์เนื่องจากนักเรียนหลายคนอาจเลือกเรียนหลักสูตรเดียวกัน (กล่าวอีกนัยหนึ่งไม่ได้เก็บไว้แน่นอน)
ด้วยตัวอย่างนี้คุณสามารถสรุปได้ว่า:
- ทุกคีย์ในตารางฐานทำหน้าที่เป็นกุญแจสำคัญในข้อมูลผลลัพธ์หลังจากเข้าร่วม (นักเรียน)
- แถวจากแถวฐานปรากฏในข้อมูลผลลัพธ์มากที่สุดเพียงครั้งเดียว (ไม่มีแถวซ้ำกัน)
นี่คือแนวคิดของ Key Key Tables
หากต้องการทราบว่าคอลัมน์มุมมองสามารถอัปเดตได้หรือไม่
select * from all_updatable_columns where table_name='V_VIEW_NAME';
PS: ระบุชื่อตาราง / มุมมองเป็นตัวอักษรตัวใหญ่