2 שאלות על DB בSQL SERVER

greena

New member
2 שאלות על DB בSQL SERVER


היי,
אני מנסה ללמוד התעסקות עם DB בSQL SERVER..נתקלתי ב2 בעיות ואולי תוכלו לסייע לי.
1. יש לי קשר כפול בין 2 טבלאות. אחד הקשרים הוא יחיד לרבים (יש מפתח זר בצד של היחיד) והקשר השני רבים לרבים, שיוצר טבלת קשר עם 2 המפתחות.
אני אביא פה דוגמא קטנה יותר שתמחיש את הבעיה. למשל קיימת טבלת Persons , Class ,Students . בכל כיתה יש מפתח זר של 'מורה' , ובנוסף נוצרת טבלת קשר של סטודנטים בכיתה עם 2 המפתחות.
עכשיו הבעיה היא שאני מעוניין לבצע On Update Cascade גם על המורה , וגם על הסטודנטים. כלומר שעדכון ת.ז של Person יגרור עידכון של שניהם אם צריך.(בפועל הת.ז לא תופיע ב2 הטבלאות במקביל..אבל עדיין אני צריך בשני המקרים Cascade).
ושאני מנסה להריץ את זה אני מקבל שגיאה שקיים מעגל בין הCascades ..איך בכל זאת אפשרי לגרום לעדכון המפתח בשתי הטבלאות?
הנה צרפתי את הקוד ובתחתית מופיעה השגיאה:

CREATE DATABASE [TRYShemen];
GO
USE [TRYShemen]
GO
CREATE TABLE Persons(
ID VARCHAR(50) PRIMARY KEY,
FullName VARCHAR(50) NOT NULL
);



CREATE TABLE Class(
ClassNum VARCHAR(30) PRIMARY KEY,
Teacher VARCHAR(50) NOT NULL,

constraint Class_FK foreign key (Teacher) references Persons (ID) ON DELETE NO ACTION ON UPDATE CASCADE,

);

CREATE TABLE Students(
StudentID VARCHAR(50) ,
ClassNum VARCHAR(30)

constraint Students_PK PRIMARY KEY (StudentID, ClassNum),

constraint Students_FK foreign key (StudentID) references Persons(ID) ON DELETE NO ACTION ON UPDATE CASCADE ,
constraint Students_FK1 foreign key (ClassNum) references Class(ClassNum) ON DELETE NO ACTION ON UPDATE CASCADE
);



Introducing FOREIGN KEY constraint 'Students_FK1' on table 'Students' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.



2. שאלה לא קשורה ל1, אבל נניח ויש לי מערכת ואני מעוניין לתת למשתמשים אפשרות לפתוח 'קריאה' ולצרף לה קובץ WORD\PDF ששוקלים בממוצע 1MB. בDB איך כדאי לשמור זאת? האם בתור VARCHAR שמכיל רק את שם הקובץ , ולאחסן אותו בשרת? או שהבנתי שקיימת אפשרות לשמור את הקובץ ישירות בDB משהו עם BLOB.. מה היתרונות /חסרונות של כל אחת מהאופציות?


תודה רבה !!!
 

greena

New member
האמת שהדוגמא לא משהו שאני חושב על זה..אבל אל

תתייחסו לתוכן שלה..רק לתבנית. הכוונה איך עושים קסקייד שיש קשר כפול :)
 

גרי רשף

New member
שאלה 1

אני מתרשם של-SQL Server יש בעייה במקרה הבא:
TblC => TblB1 => TblA
TblC => TblB2 => TblA

כלומר- TblC קשורה בעקיפין ל-TblA בשתי דרכים: גם דרך TblB1 וגם דרך TblB2.
יכול להיות שאין כאן שום בעייה מעשית ובפועל לא תיווצר התנגשות, אך מבחינת המערכת יש כאן לולאה ולכן הוא מסרב ליצור את ה-FK האחרון.

עד כאן הבעייה, והפתרון המאולתר:
ליצור את האחרון ללא Cascade, ובמקום זאת לטפל בשינויים באמצעות טריגרים.

אני חייב להדגיש שזה פתרון תיאורטי: לא ניסיתי בעצמי, ואשמח לשמוע אם הצלחת.
 

greena

New member
אחלה תודה אני אנסה ואעדכן.

לא למדתי עדיין על טריגרים. אני אקרא על זה קצת.אבל לפי מה שהבנתי בעצם זה פעולות שמוגדרות לאחר מחיקה/הוספה/עדכון..
אז בעצם שם אגדיר שבעת עדכון של טבלת הPersons זה יעדכן גם את המפתח הזהה בטבלת Students? במקום הCASCADE
 

pitoach

New member
שבת שלום, יש לך בעיה בתכנון המבנה של המערכת

שלך (בעיה לוגית חמורה, אבל תיאורטית אפשר לחיות איתה על ידי "מעקפים" כפי שהוצע).

תחשוב על "יישויות" או "אובייקטים", אז מה ההבדל בין הטבלה Class לבין הטבלה Students אצלך והיכן הטבלה המקשר בין היישויות במקרה של רבים לרבים. איזה יישות אתה מחבר לאיזה יישות?!? סטודנטים היא לא יישות נקייה אלא יישות תלויה!

אצלך טבלת הסטודנטים ניראית דומה לטבלה המקשרת כאשר יש לך טור אחד של מספר הסטודנט וטור אחד של מספר הכיתה. אבל מקשרת בין מי למי?!? איזה יישויות מקושרות בה?

אצלך הטבלה של הכיתה כוללת כבר נתונים מטבלת האנשים Persons ובנוסף אתה רוצה לקשר אותה שוב לטבלת האנשים דרך טבלה מקשר שלישית...
זו סתירה בתכנון שבאופן ישיר מובילה לסתירה בנתונים אם מתחילים לנהל אותם לפי היחסים. SQL SERVER מזהה זאת ולא מאפשר זאת בצדק

תחשוב על כך שסטודנטים הם אנשים לכל דבר ולא רק מורים והפוך מורים הם אנשים ולא רק סטודנטים ולכן סטודנט ומורה צריכים להיות מקושרים לטבלה באותו אופן!

אם אתה רוצה להגביל את מספר המורים בכל כיתה אז אתה יכול להגביל בעזרת תנאי constraint פשוט שלא יהיו יותר ממורה אחד קשורים לטבלה אבל הקשר צרך להיות זהה

תחשוב למשל על מבנה שבו יש 3 טבלאות:
אנשים
כיתות
קשר כיתות-אנשים

בטבלה המקשרת של היחס רבים לרבים (כיתות-אנשים) ניתן להגביל במספר הרשומות בהם מורה מקושר לכיתה מסויימת

טבלה נוספת תהיה טבלה של סטודנטים והיא צריכה להיות טבלת בן של טבלת אנשים. בדיוק כמו שטבלה נוספת צריכה להיות למורים שהיא טבלת בן של טבלת האנשים. באמצעות הקשר הזה נוכל לדעת כמה מורים וכמה תלמידים יש בכל כיתה למשל.

אני מקווה שההסבר הכללי הזה מובן (ברור לי שהוא לא רשום בצורה הכי טובה... היה לי יותר קל להסביר את הדברים עם תמונות
)

* נקודה נוספת: מה יהיה אם מחר יהיו בכיתה מסויימת 2 מורים או יותר? הרבה פעמים קורס מועבר על ידי 2 מורים או שמורה מוחלף באמצע או כל מצב שונה.
* השיטה עם הטריגר תעבוד בכל מקרה במבנה הנוכחי עד שייווצרו סתירות בפועל (ואז יזרקו שגיאות ספציפיות אבל באופן כללי זה יעבוד).
 

greena

New member
תודה רבה

על התגובה וההסבר המפורט. למדתי כמה דברים .
באמת הדוגמא שציינתי למעלה לא טובה , במקרה שלה עדיף כמו שאמרת לעשות "הורשה" ולפצל את 2 הבנים.

בפועל המקרה שלי הוא קצת שונה, רציתי לתת דוגמא פשוטה אבל לא הלך :)
מדובר במערכת לפתיחת תקלות,
ישנה טבלת תקלות, אשר מחוברת בקשר יחיד-רבים למשתמש( פותח התקלה) , ובנוסף ישנו קשר בין משתמש לבין תקלה שמציין אילו משתמשים מכותבים על תקלה זו. (קשר של רבים לרבים).
ככה שבמקרה שלי מדובר באותה יישות בדיוק ב2 הקשרים.

חשבתי אולי להפוך את 2 הקשרים , לקשר 1 של רבים לרבים, ולהוסיף לטבלה הנוצרת מהקשר שדה שיגדיר האם זהו פותח התקלה או מכותב.
וככה הupdate יעבוד.. ואני אנסה להוסיף טריגר שבודק שאין יותר מפותח תקלה אחד.
אתה חושב שזה יעשה את העבודה?

תודה!!
 

pitoach

New member
אני חושב שאני לא יכול לתת אפיון מקצועי בפורום

המילה מקצועי תסתור את העובדה שאני שם אפיון בלי מידע מעמיק ולכן הוא לא מקצועי


כדי לאפיין מערכת ספציפית אני צריך להכיר אותה וללמוד אותה ואז אני יכול לאפיין אותה בצורה דיי טובה (אני לא מנסה להיות צנוע, ולכן אגיד טובה מאוד או מיטבית
) אפיון מערכת ותכנון הוא החלק הכי חשוב בפיתוח ויכול להבטיח את הגמישות של המערכת בעתיד והצלחה או כישלון שלה.

כאן אני יכול רק לזרוק הערות כלליות ולתת כיוונים כלליים ולענות לשאלות ספציפיות. תבדוק את הקישור ששמתי ואולי יתקבלו לך תובנות חדשות (אין הכרח לשימוש בטריגרים בכלל וצריך לדעת מה הייתרון ומה החיסרון שיש בשימוש בטריגרים לפני שבוחרים בכיוון זה).
 

גרי רשף

New member
קח בחשבון שיש כאן בעייה יסודית

כשיש יחס של אחת לרבים - לא ניתן לעדכן את המפתח בצורה פשוטה: לא משנה איזה צד נעדכן ראשון - זה יגרום לצד הרבים להתייתם והפעולה תיכשל..

צריך אם כך ליצור שורה חדשה בצד האחת,
לעדכן את צד הרבים,
ולמחוק את השורה הישנה בצד האחת;
כל זה כמובן בטרנזקציה אחת.
 

pitoach

New member
גרי, בשביל זה יש לנו CASCADE

זה נכון בעקרון שיש פעולות שצריך לבצע ביחד, אבל זה מנוהל על ידי השרת בצורה אוטומתית אם בונים DDL מתאים. בהחלט ניתן לעדכן את המפתח בצורה ישירה ופשוטה


תבדוק בקישור ששמתי מעל יש דוגמה גם של עדכון של ClassNum (המפתח) בצד היחיד שגורר עדכון כל רשומות בצד הרבים, כמו כן יש דוגמה הפוכה כיצד עולה הודעת שגיאה כשאין שימוש ב CASCADE ומבצעים למשל מחיקה.
 

pitoach

New member
אז חושבים על שינוי המצב שכן יהיה אפשר


אבל אתה צודק שלפעמים אין אפשרות לבצע שינויים כאלה וחייבים לחיות עם הקיים ואז צריך לנהל את הדברים לבד
 

nitzos1

New member
שאלה 2

על 1 דנו, דשו והסבירו היטב מה יש, מה אין ובעיקר מה צריך לדעת כדי לעזור באמת.

על 2 שהיא יותר קלילה
התשובה היא: תלוי

אני באופן כללי ביותר מעדיף לשמור קישור לקבצים ולשמור את הקוץ כמושהוא בשרת קבצים.
אבל הדבר קשור מאוד לקליינט שמנהל את היישום וכיצד אתה ממש את הפעולות.
שונה הפתרון לשרת מקומי/יעודי וירטואלי לחברה מאשר אתר אינטרנט חיצוני פרוץ.

מניסיוני בעבר הרחוק מאוד, שימוש ב-BLOB דורש הבנה טובה ביותר סוג שדה זה.

לא רואה בגודל שהקבצים שציינת דבר מהותי לכאן או לכאן.

מקווה שעזרתי
שמוליק ב
 

greena

New member
אחלה תודה!

בהמשך יהיה לי יותר פרטים על השרת וכו' אז אני אכנס יותר לעומק העניין..
עזרתם לי מאוד!
 
למעלה