שאלה בנוגע ל update/insert

יהודה20

New member
שאלה בנוגע ל update/insert

שלום! על DB ה- ORACLE שלי (10.2g), אני מעוניין לכתוב פרוצדורה פשוטה, אשר יודעת לקרוא מרשימה ב UTL FILE, כאשר אם המופע (ע"פ האינדקס החד-חד ערכי) מופיע בטבלה שלי, אני רוצה לעדכן אותו ע"פ הפרטים בקובץ ה- UTL, ואם הוא לא נמצא כלל בטבלה, אני צריך להכניס אותו (כולל כל הפרטים כמובן). בכל מקרה, הפרוצדורה הזו אמורה לרוץ ב- JOB כל לילה, כאשר בקובץ הUTL יש כ- 4000 רשומות. אני צריך לעשות איזושהי הבדלה מתי להשתמש ב UPDATE, ומתי ב INSERT. לפי ההגיון שלי, אני צריך לעשות מעין "select count(value) from table where value=xxx" עבור כל רשומה ע"מ לדעת האם הנתון מופיע בטבלה ואני צריך לעדכן אותו, או שאינו מופיע בטבלה ויש להכניס אותו. אני לא חושב שזה כ"כ יעיל לעשות כל לילה כ- 4000 סלקטים על הטבלה... האם יש דרך טובה יותר לקבוע מתי להשתתמש ב UPDATE ומתי ב INSERT? והאם יש פקודה שיודעת לברור אוטומטית האם יש ערך בטבלה ולעדכן אותו, או שהוא לא נמצא וצריך להוסיף אותו? תודה מראש לעוזרים/פותרים/מכווינים!
 

nrotem

New member
יש פקודה!

אתה יכול להשתמש ב-merge. זו פקודת DML שמבצעת INSERT או UPDATE (או DELETE) על פי תנאי שאתה מגדיר. ראה: http://www.psoug.org/reference/merge.html או http://www.oracle-base.com/articles/10g/MergeEnhancements10g.php
 

יהודה20

New member
אני חושב שהבנתי,אבל אם המקור שלי הוא לא טבלה?

ז"א אני מכניס לתוך הטבלה נתונים שלא מתוך טבלה נוספת, אלא מ UTL FILE...
 

nrotem

New member
תשובה מהוססת

אני לא ממש מכיר קבצים, ויכול להיות שיש דרך פחות חוראנית (אולי עם SQL*Loader), אבל אפשר פשוט לקרוא את הרשומה לתוך משתנים, ולבצע merge שבו משובצים ערכי המשתנים.
 

יהודה20

New member
אני מבין

למרות שבאמת נראה לי יותר פשוט להכניס את כל הנתונים לטבלה זמנית. ועכשיו שאלה נוספת ברשותך, אם אני עושה merge into A using B כמובן עם התניה נכונה וכו', באופן תאורטי, כל פרטי שנמצא ב B ייכנס לתוך A, אבל אם יש מופעים ב A שאינם מופיעים ב B, האם הם יישארו? (קריטי מאד עבורי!)
 

s h i m s h o n

New member
שני דברים

1) נתונים ב-A שאינם ב-B ישארו. MERGE מבצע רק UPDATE ו-INSERT, לא DELETE. אם אתה רוצה להגיע למצב שהטבלאות תהיינה זהות לגמרי, תצטרך לבצע DELETE בעצמך. 2) אין חובה להשתמש ב-UTL_FILE, SQL_LOADER או טבלאות זמניות. ניתן להשתמש בטבלאות חיצוניות (ר' קישורים). בגדול - אתה מגדיר טבלה שממופה לקובץ - נותן את המיקומים והטיפוסים של העמודות וזהו. מרגע זה ואילך אתה משתמש ב-SELECT רגיל. בברכה, ש.
 

Ice Age

New member
תכניס לטבלה צדדית, ומשם תשתמש ב-merge

אגב, ב-SQL Server 2008 תהיה כנראה מקבילה ל-merge של אורקל (upsert).
 

et2005

New member
אני לא יודע אם מאוחר מדי, אבל אני אנסה

השאלה היא האם אתה מעריך שרוב הפקודות שלך יהיו INSERT או שהן יהיו UPDATE. במידה ואתה מעריך שרוב הרשומות יהיו כבר קיימות, ובחלק קטן תצטרך לעשות הוספה, השתמש ב- syntax הבא: <משפט UPDATE> if sql%notfound then <משפט INSERT> end if ככה הוא קודם יעשה עדכון, ובמקרה שלא תתעדכן אף שורה, הוא יבצע משפט הוספה. במידה ואתה מעריך שרוב הרשומות יהיו חסרות, השתמש קודם כל ב- INSERT, ותפוס את ה- EXCEPTION של הנפילה, ותעשה בו משפט עדכון. אבל זה יעבוד רק אם יש לטבלה primary key.
 

nrotem

New member
זה תחביר של SQL Server

והשואל כותב ב-Oracle. גם באורקל אפשר לכתוב קוד פרוצדוראלי (PL/SQL) אבל בעולם ה-MSSQL זה מקובל יותר. הפקודה merge נועדה לחסוך שימוש בקוד פרוצדוראלי. אני מאד מסכים עם מה שאתה אומר, et2005, לגבי שיטת ה-"ננסה לעשות X. אם נכשלנו, ננסה לעשות Y", אבל זה כדאי רק אם הסיכוי ל-Update ממש נמוך.
 

HaRmosh

New member
הערה

השיטה עם תפיסת ה-exception ממש מכוערת - BIG NO NO. לא עושים דברים כאלה, נקודה. כדי לבדוק אם הרשומה קיימת כבר - מבצעים SELECT פשוט.
 

יהודה20

New member
תודה על הרצון הטוב

אבל כבר "מאוחר מדי" ה- merge עובד נפלא, בקלות ובמהירות!
 
למעלה