07/02/2011 | פורסם על ידי
ilDBA
האתגר הבא יהיה בעולם ה-SQL.
יש לציין שגם ב-SQL Server וגם ב-Oracle הבעיה המוצגת באתגר תתרחש בדיוק באותו האופן.
יש לנו את שתי הטבלאות הבאות (ה-Data types הם של Oracle ושל SQL Server בהתאמה).
ilDBA1
--------------------------------
ID Number / Int
Name Varchar2(10) / Varchar(10)
ilDBA2
--------------------------------
ID Number / Int
Name Varchar2(10) / Varchar(10)
בטבלאות הנ"ל קיימות הרבה מאוד רשומות.אלו חלק מהרשומות הקיימות:
SELECT * FROM ilDBA1 WHERE ID in (1,2,3);
------------------------------------------
Tom 1
And 2
Jerry 3
SELECT * FROM ilDBA2 WHERE ID in (1,2,3);
------------------------------------------
Coyote 2
ביצענו את השאילתא הבאה:
SELECT * FROM ilDBA1 WHERE ID not in (SELECT ID FROM ilDBA2);
כתשובה, ציפינו לראות לפחות את הרשומות שבהן ה-ID הוא 1 ו- 3, אבל לא קיבלנו אף רשומה מהשאילתא:
SELECT * FROM ilDBA1 WHERE ID not in (SELECT ID FROM ilDBA2);
no rows selected
איך זה יכול להיות ומה צריך לעשות על מנת שנקבל חזרה רשומות?
בין הפותרים נכונה תוגרל ארוחת בוקר זוגית.
אנא אל תכתבו תשובות אפשריות בתגובות אלא רק במייל, על מנת לאפשר לאנשים נוספים לענות על האתגר.
שיהיה בהצלחה!
צוות אתר ilDBA
—————————————————————————————————————————————————
עידכון: 02.03.11
חבר הקהילה הזוכה של אתגר חודש פברואר 2011 הוא: יניב משען!
אימייל יישלח לזוכה במהלך היום.
פיתרון האתגר של חודש זה:
התופעה הזאת אכן נראית מוזרה למדי ולא ברורה, וקרוב לוודאי רבים מכם אשר ניסו לבחון את התרחיש המתואר לא קיבלו בהתחלה את התוצאה שתוארה באתגר, אך ברגע שמבינים את הפרט הקטן שהשמטנו (בכוונה) מהנתונים הבסיסיים, אפשר להבין למה זה קורה.
הבעיה הבסיסית שבגינה השאילתה לא החזירה לנו שורות, היא מכיוון שבטבלה ilDBA2 קיימת רשומה שבה ה- id מכיל ערך Null .
בואו נבין למה זה גורם לבעיה המתוארת.
כאשר בסיס הנתונים מריץ את השאילתה, עבור כל רשומה ב- ilDBA1, הוא עובר על כל הרשומות ב- ilDBA2.
עבור כל זוג כזה של רשומות, בסיס הנתונים בודק האם ערכי ה- id של שתי הרשומות שונים.
רשומה מ- ilDBA1 תוחזר בשליפה, רק אם התשובה של כל ההשוואות מול ilDBA2 הן "true" כלומר, הערכים שונים לכל רשומה ב- ilDBA2.
כאמור, במקרה שלנו, קיימת בטבלתilDBA2 רשומה המכילה ערך Null בעמודת id.
הבסיס לתופעה שאנחנו רואים כאן הוא שכל פעולה שהיא מול ערך Null מחזירה false, למעט is Null ו- is not Null .
ולכן, כאשר בסיס הנתונים מבצע את ההשוואה המקבילה ל- ilDBA1.id<>ilDBA2.id ו- ilDBA2.id הוא Null , התוצאה היא false והרשומה של ilDBA1 לא עונה על התנאי של השאילתה.
בצורה כזאת עוברים על כל הרשומות ועבור כולן קורה דבר דומה, מה שגורם לשאילתה לא להחזיר תוצאות כלל.
הפתרון הוא פשוט, יש לבטל את הרשומות המכילות null ב- ilDBA2 בצורה הבאה:
SELECT * FROM ilDBA1
WHERE ID not in (SELECT ID FROM ilDBA2 where id is not null);
מזל טוב לזוכה,
השבוע יתפרסם האתגר הבא של חודש מרץ, יש למה לחכות.
השאר תגובה: