480 likes | 854 Views
236363 מערכות מסדי נתונים. 11 . שפות ODL ו- OQL ותכנון מכוון עצמים שקפים: עודד סודרסקי עריכה והתאמות: אלדר פישר. המודל מכוון העצמים למסדי נתונים. פרט למודל הרלציוני למסדי נתונים, קיימים מודלים נוספים: מודלים ישנים יותר, שבהם הקשר בין הרשומות מתקבל ע"י מצביעים ולא ע"י ערכים משותפים:
E N D
236363מערכות מסדי נתונים 11. שפות ODL ו-OQLותכנון מכוון עצמים שקפים: עודד סודרסקי עריכה והתאמות: אלדר פישר
המודל מכוון העצמים למסדי נתונים • פרט למודל הרלציוני למסדי נתונים, קיימים מודלים נוספים: • מודלים ישנים יותר, שבהם הקשר בין הרשומות מתקבל ע"י מצביעים ולא ע"י ערכים משותפים: • מדרגי (היררכי – hierarchical) • רשת (network) • מודל חדש יותר: • מכוון-עצמים (object-oriented) • המודל מכוון העצמים דומה למודל הרלציוני, בתוספת רעיונות מתכנות מכוון עצמים. • מודל זה עדיין אינו מבוסס וסטנדרטי כמו המודל הרלציוני.
ERD Relations Relational DBMS Ideas ODL Object-oriented DBMS ODL: מבוא • ERD היא שיטת מידול; לאחר מידול מסד הנתונים יש לתרגם אותו ל-DDL עבור מודל DBMS ספציפי, למשל מודל היחסים (רלציות). • לעומת זאת, ODL (Object Definition Language) יכולה לשמש גם כשיטת מידול וגם כ-DDL למסד נתונים מכוון-עצמים.
ODL: מחלקות (classes) • מחלקה (class) ב-ODL שקולה לישות ב-ERD או למחלקה בתכנות מכוון-עצמים. היא מיוצגת ע"י הצהרת interface: • interface Movie { • }; • למחלקה יכולים להיות תכונות (attributes), קשרים (relationships),ובמקרה של OQL גם שיטות (methods).
ODL: תכונות • תכונה (attribute) היא שדה של מחלקה: • interface Movie { • attribute string title; • attribute integer year; • attribute integer length; • attribute enum Film {color, blackAndWhite} filmType; • }; • ("Gone With the Wind", 1939, 231, color)שורה לדוגמא: • interface Star { דוגמא עם תכונה מרוכבת: • attribute string name; • attribute Struct Addr {string street, string city} address; • };
ODL: תכונות 2 • כל תכונה יכולות להיות מטיפוס בסיסי או מרוכב. • טיפוסים בסיסיים (atomic): • integer, real, char, string, bool • enum TypeName {val0, val1, …} • טיפוסים מרוכבים (structured): • Set<type>,Bag<type>, • List<type>, Array<type, size> • Struct TypeName {type1 field1, type2 field2, …}
ODL: תכונות 3 • מותר: • טיפוס בסיסי (integer, real, char, string, bool, enum) • תכונה עם תת תכונות (Struct) • אוסף (Set, Bag, List, Array) של הנ"ל • אסור: • אוסף של אוסף • Struct עם אוסף בתוכו
ODL: מפתחות • מפתח (key) הוא תכונה, או קבוצת תכונות, שמזהה עצמים מהמחלקה באופן חד ערכי : • interface Movie (key (title, year)) { • attribute string title; • attribute integer year; • attribute integer length; • attribute enum Film {color, blackAndWhite} filmType; • }; • לא ייתכנו שני סרטים זהים ב-title וב-year ושונים באחת התכונות האחרות. • אפשר להגדיר מפתחות אחדים: • interface Movie (key (title, year), movieID)
ODL: קשרים • קשר (relationship) מבטא יחס בין מחלקות. • קשר חד-ערכי: • interface Movie { • relationship Star starOf; • }; • לכל סרט יש כוכב אחד לכל היותר. • קשר רב-ערכי: • interface Movie { • relationship Set<Star>stars; • }; • לסרט יכולים להיות מספר כוכבים.
ODL: קשרים 2 • מותר: • קשר חד-ערכי • קשר רב-ערכי ע"י אוסף (Set, Bag, List, Array) • אסור: • אוסף של אוסף • קשר עם Struct, בפרט אין קשרים עם תכונות או קשרים בין יותר משתי מחלקות
ODL: קשרים הפוכים • בד"כ נרצה לשמור, לכל קשר בין שתי מחלקות, גם את הקשר ההפוך (inverse relationship). לדוגמא: • interface Movie { • relationship Set<Star> stars inverse Star::starredIn; • }; • interface Star { • relationship Set<Movie> starredIn inverse Movie::stars; • }; • זהו קשר רבים-לרבים בין סרטים לבין כוכבים.
ODL: קשרי אחד-לרבים, אחד-לאחד • כפי שראינו, קשר ללא Set<> הוא חד-ערכי. כך ניתן להגדיר קשר אחד-לרבים: • interface Studio { • relationship Set<Movie> owns inverse Movie::ownedBy; • }; • interface Movie { • relationship Studio ownedBy inverse Studio::owns; • }; • או אחד-לאחד: • interface President { • relationship Studio runs inverse Studio::runBy; • }; • interface Studio { • relationship President runBy inverse President::runs; • };
ODL: ירושה (inheritance) • ירושה (inheritance) מאפשרת להגדיר מחלקה מסוימת כתת-מחלקה של מחלקה אחרת: • interface Cartoon: Movie{ • relationship Set<Star> voices; • }; • Cartoon יורש את כל התכונות והקשרים של Movie, ובנוסף יש לו את הקשר הרב-ערכי voices למחלקה Star .
ODL: ירושה מרובה • ירושה מרובה (multiple inheritance) מאפשרת לרשת משתי מחלקות או יותר: • interface MurderMystery: Movie { • attribute string weapon; • }; • Interface Cartoon-MurderMystery: Cartoon,MurderMystery{ }; • Cartoon-MurderMystery יורש את כל התכונות והקשרים של Cartoon ושל MurderMystery. הוא יורש בעקיפין גם את כל התכונות והקשרים של Movie, אבל רק פעם אחת. • במקרה שיורשים מאבות שונים תכונות או קשרים בעלי שם זהה וטיפוסים שונים, התוצאה אינה מוגדרת.
teacher in charge course semester in charge teacher course semester מ-ERD ל-ODL: קשרים לא בינריים • קשר בין יותר משתי ישויות (או קשר עם תכונות): • יש להפוך את הקשר לישות, ואז לתרגם ל-ODL: • interface InCharge { • relationship Teacher teacher; • relationship Course course; • relationship Semester semester; • };
מ-ERD ל-ODL: ישויות חלשות? • לעומת מודל ER, ב-ODL לא קיימות ישויות חלשות (weak entities).זאת מפני שלכל עצם ב-ODL יש זיהוי ייחודי משלו: הכתובת שבה הוא מאוחסן. לכן אפשר להבדיל בין שני עצמים מאותה מחלקה גם אם יש להם אותם ערכים לכל התכונות. • ב-ER, לעומת זאת, הישויות מזוהות רק ע"י ערכי התכונות.ישות חלשה ב-ERD תתורגם ל-ODL כאילו היא ישות רגילה.
title year length type Movie מ-ODL ל-ERD: מח', תכונות בסיסיות • לא הכל ניתן לתרגום! • מחלקה ב-ODL מתורגמת לישות ב-ERD • תכונה מטיפוס בסיסי מתורגמת לתכונה ב-ERD • אחד המפתחות ב-ODL מתורגם למפתח ב-ERD • interface Movie (key (title, year)) { • attribute string title; • attribute integer year; • attribute integer length; • attribute enum Film {color, blackAndWhite} filmType; • };
name street city street city Star name Addr Star מ-ODL ל-ERD: תכונות Struct • תכונה מטיפוס Struct ב-ODL מתורגמת למספר תכונות ב-ERD, כמספר השדות ב-Struct, או לתכונה מרוכבת. • interface Star (key name) { • attribute string name; • attribute Struct Addr • {string street, string city} address; • }; • או
street city name Addr Star מ-ODL ל-ERD: תכונות Set • תכונה מטיפוס Set מתורגמת לתכונה רב-ערכית בתרשים ה-ER. • interface Company (key id) { • attribute integer id; • attribute string name; • attribute Set<Struct Addr{string street, • string city}> addresses; • };
id name number count Company phone מ-ODL ל-ERD : תכונות Bag • תכונה מטיפוס Bag אין אלא לתרגם לישות חלשה נפרדת, עם תכונה נוספת עבור מספר ההופעות. • המפתח: כל שדות התכונה (לא כולל מס' ההופעות). • interface Company (key id) { • attribute integer id; • attribute string name; • attribute Bag<integer> phones; • };
id name position city street Company address מ-ODL ל-ERD : תכונות List • תכונה מטיפוס List גם מתורגמת לישות חלשה נפרדת, עם תכונה עבור המספר הסידורי. • המפתח: המספר הסידורי, ולא השדות המקוריים. • interface Company (key id) { • attribute integer id; • attribute string name; • attribute List<Struct Addr{string street, • string city}> addresses; • };
id name position number Company phone id name phone1 phone2 Company מ-ODL ל-ERD : תכונות Array • תכונה מטיפוס Array מטופלת כמו List, או ע"י חזרה על התכונה (אם המערך קטן יחסית). • interface Company (key id) { • attribute integer id; • attribute string name; • attribute Array<integer, 2> phones; • }; • או
President runs Studio owns Movie starredIn Star מ-ODL ל-ERD: קשרים • interface President { • relationship Studio runs inverse Studio::runBy; • }; • interface Studio { • relationship President runBy inverse President::runs; • relationship Set<Movie> owns inverse Movie::ownedBy; • }; • interface Movie { • relationship Studio ownedBy inverse Studio::owns; • relationship Set<Star> stars inverse Star::starredIn; • }; • interface Star { • relationship Set<Movie> starredIn inverse Movie::stars; • };
position Star starredIn Movie starPosition moviePosition Star starredIn Movie מ-ODL ל-ERD: קשרי List • לקשר מטיפוס List נוספת תכונת מס' סידורי כמפתח: • interface Movie { • relationship List<Star> stars inverse Star::starredIn; • }; • interface Star { • relationship Set<Movie> starredIn inverse Movie::stars; • }; • interface Movie { • relationship List<Star> stars inverse Star::starredIn; • }; • interface Star { • relationship List<Movie> starredIn inverse Movie::stars; • };
count Star starredIn Movie מ-ODL ל-ERD: קשרי Bag • לקשר מטיפוס Bag נוספת תכונת מס' ההופעות: • interface Movie { • relationship Bag<Star> stars inverse Star::starredIn; • }; • interface Star { • relationship Set<Movie> starredIn inverse Movie::stars; • };
position Star starredIn Movie starredIn1 Star Movie starredIn2 מ-ODL ל-ERD: קשרי Array • קשר Array מיוצג כמו List, או כמס' קשרים. • interface Movie { • relationship Array<Star, 2> stars inverse Star::starredIn; • }; • interface Star { • relationship Set<Movie> starredIn inverse Movie::stars; • }; • או
Movie isa Cartoon מ-ODL ל-ERD: ירושה • ירושה ב-ODL הופכת להפרדה ב-ERD: • interface Movie { • }; • interface Cartoon: Movie { • };
ERD Relations Relational DBMS Ideas attributes+dependencies ODL Object-oriented DBMS ODL ומסדים מכווני עצמים • ODL+OQL: אחד המימושים למודל מכוון-העצמים למסדי נתונים (מימוש אחר: SQL3) • ODL (Object-Definition Language): • שיטת מידול, כמו ERD או ניתוח תלויות למודל הרלציוני • שפת הגדרה (Data Definition Language) למודל מכוון-העצמים
ODL: תוספות למודל מכוון-העצמים שם המחלקה (סוג העצמים שבקבוצה) שם קבוצת העצמים—המופע • interface Movie (extent Movies key (title, year)) { • attribute string title; • attribute integer year; • attribute integer length; • attribute enum Film {color,blackAndWhite} filmType; • relationship Set<Star> stars inverse Star::starredIn; • relationship Studio ownedBy inverse Studio::owns; • float lengthInHours(); • stars(out Set<String>); • otherMovies(in Star, out Set<Movie>) raises(noSuchStar); • }; • interface Star (extent Stars key name) {...}; • interface Studio (extent Studios key name) {...}; פונקציה (method) עם ערך מוחזר, ללא פרמטרים פונקציה ללא ערך מוחזר, עם פרמטר פלט פונקציה ללא ערך מוחזר, עם פרמטר קלט, פרמטר פלט, ואפשרות לחריג (exception)
OQL: מבוא • OQL (Object Query Language): שפת שאילתא ועדכונים (Data Manipulation Language) למודל מכוון-העצמים • משוכנת בשפת תכנות מכוונת-עצמים, כגון C++, Smalltalk או Java • כוללת אלמנטים מ-ODL ומ-SQL
OQL: טיפוסי משתנים וקבועים • טיפוסים בסיסיים (atomic): כמו ב-ODL. • integer, real, char, string, bool • enumTypeName{val0, val1, …} • טיפוסים מרוכבים (structured): כמו ב-ODL. • Set<type>, Bag<type>, • List<type>,Array<type, size> • Struct TypeName{type1field1, type2field2, …} • – אבל כאן מותר גם אוסף של אוסף, או Struct של אוסף.
OQL: קבועים • מטיפוס בסיסי: • 17, 17.5, 'a', "abc", true • מטיפוס מרוכב: • Set(17, 18, 19) • Bag(17, 17, 18) • List("Haifa","Haifa","Tel-Aviv") • Array(5.0, 6.5) • Struct(addr: "1 Main Str., LA", phones: Set(1234, 5678))
OQL: אופרטור הנקודה (.) • גישה לתכונה:myMovie.length • כאשר myMovie עצם מהמחלקה Movie • גישה לקשר: myMovie.stars • מחזיר קבוצה של עצמים מהמחלקה Star • גישה לפונקציה:myMovie.starNames(myStars) • מציב ל-myStars את שמות כוכבי הסרט (כקבוצת מחרוזות) • גישה לשדה של Struct:address.street • הרכבה:myMovie.ownedBy.address.street • הרחוב של האולפן שהוא הבעלים של הסרט myMovie
OQL: שאילתות בסיסיות • השאילתות ב-OQL דומות תחבירית ל-SQL: • SELECT [DISTINCT]ביטוי,... • FROMאוסף[AS]משתנה,... • [WHEREתנאי] • אוסף— מופע (extent) קיים במסד הנתונים, או תת-שאילתא. • משתנה— מקבל בכל פעם ערך של רשומה אחת מתוך האוסף. • ביטוי, תנאי— כוללים קבועים ומשתנים מחלק ה-FROM (אפשר להשתמש באופרטור הנקודה). • התוצאה—Bag (או Set אם יש DISTINCT).
OQL: שאילתות בסיסיות—דוגמאות • השנים שבהן יצא סרט בשם "שר הטבעות": • SELECT m.year • FROM Movies m • WHEREm.title = "Lord of the Rings" • שמות כוכבי הסרטים בשם "לשחרר את ווילי": • SELECT s.name • FROM Movies m,m.stars s • WHERE m.title = "Free Willy" • כוכבי הסרטים של אולפן "האחים וורנר": • SELECTDISTINCTs.name • FROM Movies m, m.stars s • WHERE m.ownedBy.name = "Warner Bros."
OQL: טיפוסים מרוכבים בפלט • זוגות של כוכבים שגרים באותה כתובת: • SELECT DISTINCT • Struct(star1: s1, star2: s2) • FROM Stars s1, Stars s2 • WHERE s1.addr = s2.addr • AND s1.name < s2.name • טיפוס התוצאה: • Set<Struct N{star1:Star,star2:Star}>
OQL: תת-שאילתות • האוסף ב-FROM יכול להיות גם תת-שאילתא. • דוגמא: שמות כוכבי הסרטים של אולפן "פרמונט": • SELECT DISTINCT s.name FROM • (SELECT m FROM Movies m WHERE • m.ownedBy.name="Paramount") • f, f.stars s
OQL: סדר התוצאה • הסרטים של אולפן "דיסני", עם מיון ראשוני לפי אורך הסרט (בסדר יורד) ומיון משני לפי שמו: • SELECT m • FROM Movies m • WHERE m.ownedBy.name = "Disney" • ORDER BY m.length DESC, m.title • התוצאה: List (במקום Bag או Set)
OQL: כמתים • בחלק ה-WHERE אפשר להשתמש גם בכמתים ∃ ו-∀: • FOR ALL (משתנה) IN (אוסף): (תנאי) • EXISTS (משתנה) IN (אוסף): (תנאי) • דוגמא: כוכבי הסרטים של אולפן "קולומביה": • SELECT s FROM Stars s • WHERE EXISTS m IN s.starredIn: • m.ownedBy.name = "Columbia" • דוגמא: הכוכבים שהופיעו רק בסרטי "פוקס": • SELECT s FROM Stars s • WHEREFOR ALLm IN s.starredIn: • m.ownedBy.name = "Fox"
OQL: ביטויים סטטיסטיים • COUNT, MIN, MAX, SUM, AVG פועלים על אוספים של ערכים: • COUNT— עבור ערכים מטיפוס כלשהו • MIN, MAX— עבור ערכים מטיפוס בר-השוואה (כגון מספר או מחרוזת) • SUM, AVG— עבור ערכים מטיפוס מספרי • דוגמא: האורך הממוצע של כל הסרטים במסד: • AVG(SELECT m.length FROM Movies m)
OQL: קיבוץ הגדרה • אחרי SELECT-FROM-WHERE אפשר להוסיף: • GROUP BY שדה:ביטוי,... • מקבץ את הרשומות המתקבלות מ-FROM-WHERE ל-Bags. • כל Bag כולל את כל הרשומות שיש להן אותם ערכים עבור כל הביטויים המופיעים ב-GROUPBY. • מחזיר Set של Structs. • כל Struct מייצג Bag אחד של רשומות. • בכל Struct מופיעים כל השדות שב-GROUPBY. • הערך של כל שדה ב-Structהוא ערך הביטוי המתאים לשדה (של הקיבוץ) עבורbagהרשומות המיוצג ע"י ה-Struct. • בנוסף, יש בכל Struct שדה בעל השם השמור partition. • ערך השדה partition הוא Bag של Structs מהצורה • Struct(משתנה:רשומה,...) • עם המשתנים המופיעים ב-FROM והרשומה המתאימה לכל משתנה.
OQL: קיבוץ דוגמא • אולפן, שנה, וסך אורכי הסרטים שהופקו ע"י האולפן בשנה זו: • SELECTstd, yr, • sumLength: SUM(SELECT p.m.length • FROM partition p) • FROM Movies m • GROUP BY std: m.studio, yr: m.year
OQL: קיבוץ בחירת חלק מהקבוצות • אחרי GROUP BY אפשר להוסיף תנאי HAVING. • הביטויים המופיעים בתנאי כמו ב-SELECT. • דוגמא: אולפן, שנה, וסך אורכי הסרטים שהאולפן הפיק בשנה זו,אבל רק אם האולפן הפיק לפחות סרט אחד של יותר משעתיים בשנה זו: • SELECT std, yr,sumLength:SUM(SELECT p.m.length • FROM partition p) • FROM Movies m • GROUP BY std: m.studio, yr: m.year • HAVING MAX(SELECT p.m.length FROM partition p) • > 120
OQL: אופרטורים מתורת הקבוצות • בין שני Sets אפשר להפעיל את האופרטורים • UNION (U), INTERSECT (∩), EXCEPT (–) • דוגמא: כל סרטי הריסון פורד שלא הופקו ע"י "מ.ג.מ.": • (SELECT DISTINCT m FROM Movies m, m.stars s • WHERE s.name = "Harrison Ford") • EXCEPT(SELECT DISTINCT m FROM Movies m • WHERE m.ownedBy.name = "MGM") • בין שני Bags (או בין Bag ל-Set), המשמעות היא: • UNIONסכום מספרי ההופעות בשני ה-Bags • INTERSECTמינימום מספרי ההופעות בשני ה-Bags • EXCEPTהפרש מספרי ההופעות בשני ה-Bags (אך לא פחות מ-0)
OQL: שיכון בשפה מארחת • אפשר לשכן שאילתות OQL בשפת תכנות מכוונת-עצמים מארחת, למשל C++. • השמה למשתנה של השפה המארחת: • Set<Movie> oldMovies; • oldMovies =SELECT DISTINCT m • FROM Movies m WHERE m.year < 1920; • שליפה מ-Set או Bag עם אלמנט יחיד: • Movie s; • s =ELEMENT(SELECT m FROM Movies m • WHERE m.title = "Shrek");
OQL: שיכון בשפה מארחת 2 • שליפה מ-List:ע"י סוגריים מרובעים, האינדקס רץ מ-0. • List<Movie> movieList; • movieList = SELECT m FROM Movies m • ORDER BY m.title, m.year; • const int numMovies = COUNT(Movies); • for (int i = 0; i < numMovies; i++){ • const Movie mv = movieList[i]; • cout << mv.title << " " << mv.year << " " • << mv.length << endl; • };
OQL: שיכון בשפה מארחת 3 • הגדרת טיפוסים: • typedef Struct{star1:Star, star2:Star}StarPair; • Set<StarPair> pairs = • SELECT DISTINCT • StarPair(star1:s1, star2:s2) • FROM Stars s1, Stars s2 • WHERE s1.addr = s2.addr • AND s1.name < s2.name;
OQL: שיכון בשפה מארחת 4 • יצירת עצמים חדשים: ע"י הפעלת constructor: • Studio mgm; • mgm =ELEMENT(SELECT s FROM • Studios s WHERE s.name = "MGM"); • Moviegwtw; • gwtw = • Movie(title:"Gone with the Wind", • year:1939,length:239,ownedBy:mgm); • יוצר עצם חדש ב-Moviesextent, ומציב אותו במשתנה gwtw.