vahid بي تو هرگز
Joined: 26 Nov 2004 Posts: 3067 Location: Tehran
|
Posted: Thu Dec 23, 2004 6:00 pm Post subject: پيوند جداول در پرس و جو ها |
|
|
پيوند جداول در پرس و جو ها .
در استفاده از دستورات SQL گذركردن از رابطه جداول دقيقا مانند انستكه كلا سيستم بانك اطلاعاتي رابطه اي را حذف كرده باشيم و كلا سيستم بانك اطلاعاتي رابطه اي را ناديده بگيريم .
ميدانيم كه هر پيوند دو يا بيش از دو جدول را به يكديگر مرتبط ميكند .
انواع پيوندها در SQL عبارتند از EQUIJOIN , NATURAL JOIN , NON-QUIJOINS , OUTER JOINS , SELF JOINS
EQUIJOIN
مهمترين پويند اين پيوند است كه پيوند داخلي INNER JOIN نيزبه ان گفته ميشود . EQUIJOIN دو جدول را با يك ستون مشترك كه معمولا در هر دوي انها كليد اصلي است به يكديگر پيوند ميزند .
نمونه قالب ان بصورت زير است :
| SELECT TABLEN.COLUMNN , TABLEM.COLUMNM …
FROM TABLEN,TABLEM
WHERE TABLEN.COLUMNN = TABLEM.COLUMNM
[AND … ] |
همانطور كه قبلا هم گفتم براي مشخص كردن فيلدهايي كه در دو جدول در يك دستور SELECT مي ايند با يكديگر مي ايند بايد نام جدول را قبل از نام فيل نوشت و با يك نقطه ازنام فيلد جدا كرد . اينكار براي تنها فيلدهايي لازم است كه در دو جدول استفاده شده ما در دستور SELECT مشترك هستند و اگر براي نام ديگر فيلدها هم نام جدول را قبل از انها بنويسيد كاملا اختياري است .
چنانچه بخواهيد از دستوري مانند دستور زير استفاده كنيد :
| SELECT S.STNO,S.FNAME,G.GRADE FROM STUDENT S,GRADE G ; |
دستور فوق فيلدهاي STNO و FNAME را از جدول student و فيلد grade را نيز از جدول grade انتخاب ميكند . g و s كه قبل از نام فيلدها ميبينيد نام مستعاريست (alias) براي دو جدول student و grade كه با استفاده از student s و grade g اين نام هاي مستعار را براي راحتي كار انتخاب كرده ايم . ميتوان بجاي دستور فوق از student as s و يا grade as g نيز استفاده كرد .
در دو دستور فوق بدليل عدم مشخص كردن پيوندي براي جداول طبق قانون ضرب تمامي فيلدهاي جدول اولي در دومي ضرب ميشود . اين بان دليل است كه طبق قانون ضرب هرگاه n مسير را بتوان به m طريق طي كرد بنابراين ميتوان m*n مسير را انتخاب كرد است .
به اين ضرب كه ضرب كارتزين معروف است كاملا در هنگام استفاده از دستورات SQL توجه داشته باشيد چرا كه هرگاه اشتباهي اينگونه انجام دهيد اگر هر جدول 1000 سطر داشته باشد و بين ان رابطه اي برقرار نكنيد طبق اين قانون 1000000 سطر در خروجي خواهيد داشت !
بنابراين يادتان باشد كه هرگاه داده ها را از بيشتر از دو جدول انتخاب كرديد . رابطه را برقرار كنيد . وگرنه سرويس دهنده بانك اطلاعاتي شما چون پيوندي نميبيند براي هر سطر جدول اولي كليه سطرهاي جدول دومي را در خروجي ميدهد .
بنابراين بايد شرطي در دستور فوق اعمال كنيم كه ديگر چنين حادثه اي پيش نيايد بنابراين با استفاده از دستور Where يك رابطه equijoin درست ميكنيم . در واقع براي دسترسي به خروجي صحيح بصورت زير دستور فوق را عوض ميكنيم :
| SELECT S.STNO,S.FNAME,G.GRADE FROM STUDENT S,GRADE G WHERE S.STNO=G.STNO |
با شرط فوق فرمان داديم كه تنها اندسته از فيلدهايي را كه مقادير فيلد Stno در هر دوي جداول يكسان هستند نمايش دهد.
درمورد استفاده از نام مستعار براي جداول كه در بالا نيز از اين روش استفاده كرديم بايد بگويم كه استفاده از اين روش كاملا اختياري است اما استفاده از ان بهتر از استفاده نكردن از انست جراكه استفاده از نام مستعار سبب كوتاهتر شدن دستور sql ميشود كه منجر به كاهش احتمالي خطاي تايپ توسط كاربر است . در ضمن نام مستعار قرار دادن براي يك جدول تنها يك نام دادن موقتي است و در همان QUERY اين نام معتبر است وگرنه نام اصلي جدول دست نخورده باقي ميماند ...
توجه داشته باشيد كه نوع پيوند EQUIJOIN تنها يك نام است و انتظار دستور خاصي براي استفاده از اين پيوند نداشته باشيد . شما بدون انكه بدانيد استفاده از دستور WHERE در دستورات SQL سبب ايجاد اين نوع پيوند است ميتوانيد به كار خود ادامه دهيد .
در نقطه مقابل اين نوع پيوند نام ديگري بنام NON-EQUALITY قرار گرفته است كه اين پيوند تنها تفاوتي كه با پيوند EQUIJOIN دارد انستكه تنها در عبارت مقايسه اي كه در دستور WHERE استفاده ميكنيم از عملگر عدم تساوي استفاده ميكنيم ... دستور زير يك دستور از نوع اخري است:
| SELECT S.STNO,S.FNAME,G.GRADE FROM STUDENT S,GRADE G WHERE S.STNO!=G.STNO |
در ضمن بجاي عملگر != بسته به نوع نسخه اي كه نرم افزار مديريت بانك اطلاعاتي شما استفاده ميكند شايد بايد از اين <> استفاده كنيد . وظيفه تست كردن اينكه كدامين يك از دو عملوند ذكر شده در دستور sql شما قرار ميگيرد بر عهده خود شما .
مراقب باشيد هنگام استفاده از رابطه NON-EQUALITY با مشكل قانون ضرب كه در بالا گفتم مواجه نشويد .
در ضمن اينكه چرا قانون ضرب رخ ميدهد دليل دارد و ان به اين دليل است كه براي هر فيلد از ركورد مورد نظر در جدول اولي به تعداد تمامي ركوردهاي جدول دومي مقدار وجود دارد بنابراين فيلد اول از جدول اول N بار براي هر كدام از N ركورد جدول دومي متناظر ميشود و در خروجي نمايش داده ميشود .
OUTER JOIN
اين اتصال براي بدست اوردن تمامي سطرهاي جدولي مورد استفاده قرار ميگيرد كه در سطرهاي متناظر جدول ديگر وجود ندارد . يعني هر گاه بازاي مقدار مشتركي از يك فيلد كه در مقدار WHERE امده است مقداري نداشته باشيم اما بخواهيم باقي مقادير را نيز نمايش دهيم بايد از اين اتصال استفاده كرد .
اگر دستوري كه در SQUIJOIN استفاده كرديم را مرور كنيم :
| SELECT S.STNO,S.FNAME,G.GRADE FROM STUDENT S,GRADE G WHERE S.STNO=G.STNO |
ميبينيد كه جلوي شرط WHERE ذكر كرده ايم كه هر گاه STNO هر دو جدول برابر بود مقادير فيلد مورد نظر در مقابل SELECT را نمايش بده .
حال شايد مقداري از فيلد STNO در جدول داشته باشيم كه بخواهيم ان نيز نمايش داده شود . بنابراين بايد با استفاده از OUTER JOIN مشكل را حل كرد .
استفاده از نماد (+) در يك دستور SQL نمايانگر اين رابطه است كه انرا با عملوند جمع نبايد اشتباه بگيريد . چرا كه اين نماد هميشه بين دو پرانتز قرار ميگيرد . اين نماد در انتهاي نام جدول كه در مقابل عبارت WHERE امده است اورده ميشود . جدولي كه درمقابل ان از اين نماد استفاده ميكنيم بايستي جدولي باشد كه سطرهاي متناظر ما را نداشته باشد . در واقع جدولي كه نقصان فيلد مورد نظر دارد بايد اين نماد را با خودش حمل كند . البته استاندارد مورد نظر در بيشتر سرويس دهنده ها استفاده از اين نماد نيست بلكه رابطه ها به بخش هاي full , right , left تقسيم ميشوند اما اين نماد را نيز ميپذيرند .
نكته اي كه بايد فهميده باشيد انستكه استفاده از اين نماد تنها در يك طرف عمليات جايز است . يعني تنها يك جدول است كه اين نماد را ميتواند داشته باشد .
اما ياداوري ميكنم كه نكته فوق دليل بر ان نيست كه فيلدهاي يك جدول نتوانند از اين نماد استفاده كنند . اگر شرط فوق را رعايت كنيد يعني اين نماد را تنها براي يك جدول استفاده كنيد محدوديتي در استفاده ان براي چند فيلد از همان جدول نداريد .
| SELECT S.STNO,S.FNAME,G.GRADE FROM STUDENT S,GRADE G WHERE S.STNO=G.STNO(+) |
در دستور فوق اگر STUDENT را جدول ليست دانش اموزان بدانيم و GRADE را ليست نمرات . و از طريق فيلد STNO كه بيانگر شماره دانش اموزي است با يكديگر رابطه داشته باشند .
حال با استفاده از (+) ميتوانيم بفهميم كه كدام دانش اموز نمره نداشته و كدام دانش اموز نمره دارد . اگر نماد OUTER JOIN را پاك كنيم تنها ليستي از دانش اموزاني نمايش داده ميشود كه نمره دارند .
پيش مي ايد كه فيلد مشتركي بين دو جدول نداريد ! اما چون بانك اطلاعاتي شما رابطه اي است با نگاهي به رابطه هاي جداول ميتوانيد واسطه دو جدولي كه فيلد مشترك ندارند را پيدا كنيد . اينجاست كه از جدول واسط نيز براي ايجاد ارتباط استفاده ميكنيد .
فرض كنيد جدول A از طريق جدول B به جدول C مرتبط است . حال چون دو جدول A , C از طريق جدول B بهم مرتبط شده اند . بنابراين جدول A با فيلدي از جدول B ارتباط دارد و جدول C نيز با فيلدي از جدول واسطه B ارتباط دارد . بنابراين دو جدول A , C را ميتوان بهم مرتبط كرد به اين صورت كه
اگر جدول A,B با فيلدي بنام KABK مرتبط به هم هستند و جدول B,C با فيلدي بنام KBCK به هم مرتبط هستن بنابراين با دستور زير ميتوان دو جدول A ,C را بهم مرتبط كرد:
| WHERE (A.KABK=B.KABK) AND (B.KBCK=C.KBCK)
|
با تشكر از استاد رئوف مكفي
Last edited by vahid on Wed Dec 29, 2004 10:01 pm; edited 1 time in total |
|