برترین مقالات کامپیوتر

برترین مقالات کامپیوتر

برترین مقالات کامپیوتر

برترین مقالات کامپیوتر

ماهیت و نحوه پیکربندی دستگاه های شبکه ای

ماهیت و نحوه پیکربندی دستگاه های شبکه ای
استفاده از فن آوری های متعدد و درعین حال پویا در طراحی ، پیاده سازی و نگهداری شبکه های کامپیوتری ، ضرورت ارتقاء مستمر دانش برای علاقه مندان فعالیت در این عرصه را به یک باید تبدیل کرده است . صرفنظر از میزان اطلاعات شما در خصوص شبکه های کامپیوتری، همواره لازم است که با یک دید جدید به بازنگری اندوخته های خود پرداخته  تا از این رهگذر یک ساختار مناسب علمی  در جهت مدیریت و اشکال زدائی بهینه شبکه در ذهن ایجاد گردد .
علاقه مندان فعالیت در عرصه مدیریت شبکه های کامپیوتری ، می بایست دارای اطلاعات مناسبی در موارد متعددی نظیر تفاوت روتر با سوئیچ و اصول اولیه آدرس دهی IP باشند. علاوه بر این ، توجه دقیق به برخی از مفاهیم کلیدی در خصوص ماهیت و نحوه پیکربندی دستگاه های شبکه ای نیز حائز اهمیت است . در ادامه به بررسی مواردی خواهیم پرداخت که توجه به آنها، مسیر ما را برای حرکت منطقی و سریع به سمت جلو هموارتر می نماید. 

نکته اول : آگاهی از تفاوت بین پروتکل های routing و routed
 واژه routing  در شبکه های کامپیوتری به انتخاب مسیر جهت ارسال داده اطلاق می گردد. پروتکل های routing ، به آندسته از پروتکل هائی اطلاق می شود که مسئولیت توزیع اطلاعات روتینگ بین سایر روترهای موجود در یک شبکه را برعهده دارند. هر روتر می بایست نسبت به سایر شبکه هائی که به وی متصل شده اند آگاهی داشته باشد . پروتکل های زیر نمونه هائی از پروتکل های routing می باشند :

  • OSPF ( برگرفته از  Open Shortest Path First   )

  • RIP ( برگرفته از Routing Information Protocol  )

  • EIGRP ( برگرفته از Enhanced Interior Gateway Routing Protocol  )

  • BGP ( برگرفته از Border Gateway Protocol  )

هر پروتکل شبکه که اطلاعات لازم در سطح لایه شبکه را ارائه می نماید تا به کمک آن یک packet بتواند از یک میزبان به میزبان دیگر ( بر اساس یک مدل آدرس دهی ) ارسال گردد ، یک پروتکل routed محسوب می گردد . این نوع پروتکل ها فرمت یک packet را تعریف و از فیلدهای موجود در آن استفاده می نمایند . پروتکل IP یک نمونه از پروتکل های routed و  NetBEUI ( برگرفته از  NetBIOS Extended User Interface ) نمونه ای از یک پروتکل non-routable است .

نکته دوم : آشنائی با حالات متفاوت مدیریت روتر
بخش رابط کاربر IOS روترهای سیسکو به چندین حالت (mode ) متفاوت تقسیم می گردد . هر command mode ، امکان پیکربندی عناصر مختلفی را بر روی روتر فراهم می نماید . با توجه به موضوع فوق ، مدیران شبکه می بایست شناخت مناسبی نسبت به هر یک از سطوح مجاز روتر داشته باشند . به  عبارت دیگر ، آگاهی و شناخت مناسب نسبت به عملکرد هر command mode  و نحوه استفاده از پتانسیل های موجود، امکان پیکربندی بهینه روتر را فراهم می نماید. 

  •  User Exec Mode :  پس از log in به یک روتر سیسکو ،  به صورت پیش فرض در این mode قرار خواهیم گرفت . در mode فوق ، عملیات زیادی را نمی توان انجام داد و صرفا" امکان دستیابی و مشاهده برخی اطلاعات وجود دارد . در این mode امکان تغییر پیکربندی روتر وجود ندارد . از دستور enable برای استقرار در Privileged EXEC Mode  استفاده می گردد .
     

  •  Privileged Exec Mode : پس از استقرار در این mode با استفاده از مجموعه دستورات موجود می توان به مجموعه کاملی از اطلاعات دستیابی داشت . مثلا"  با استفاده از گونه های مختلف دستور ‌show می توان اطلاعات گسترده ای در خصوص وضعیت روتر و پیکربندی آن را مشاهده نمود . در این mode  نیز نمی توان  پیکربندی روتر را تعییر داد  و می بایست از سایر مدهای زیر مجموعه ( sub modes ) استفاده نمود . از دستور config terminal به منظور استقرار در Global Configuration Mode  استفاده می گردد .
     

  •  Global Configuration Mode : با استفاده از امکانات موجود در این mode می توان پیکربندی روتر را تغییر داد . از دستور exit به منظور برگشت به Privileged Exec Mod استفاده می گردد .

نکته سوم :  شناخت مناسب نسبت به گونه های مختلف دستور show
دستور show ، از جمله دستورات مهم در IOS سیسکو است که از آن در موارد متعددی استفاده می گردد . با این که می بایست با تمامی قابلیت های این دستور آشنا گردید ولی استفاده از آن در برخی موارد دارای اهمیت بیشتری است  :  

  • Show ip route : دستور فوق ، مسیرهای موجود بر روی روتر را نمایش می دهد ( اطلاعات موجود در جدول روتینگ IP ) . مسیرهای روتر می توانند به صورت ایستا و یا پویا تعریف گردند . در صورت عدم تعریف یک مسیر پیش فرض و یا عدم وجود مقصدی که ترافیک روتر می بایست به آن هدایت شود ، روتر ترافیک منتقل شده به خود را نادیده گرفته و از آن صرفنظر می نماید .
     

  • show running-configuration : دستور فوق ، پیکربندی جاری روتر را نشان می دهد . در صورت اعمال هرگونه تغییرات در پیکربندی روتر ، می بایست با استفاده از دستور  copy run start آنان را ذخیره نمود .
     

  • show ip interface brief : دستور فوق ، خلاصه ای از وضعیت جاری تمامی اینترفیس های موجود بر روی روتر را نمایش می دهد . از خروجی این دستور می توان به منظور تشخیص تعداد و نوع اینترفیس ها ،‌ آدرس و وضعیت آنان ( فعال بودن و یا غیرفعال بودن ) ، استفاده نمود. 

نکته چهارم : آگاهی از نحوه عملکرد آدرس های IP خصوصی و NAT با یکدیگر
بر اساس RFC 1918 ، آدرس های IP خصوصی قابل route بر روی شبکه اینترنت نمی باشند .از آدرس های فوق صرفا" در شبکه های داخلی استفاده می گردد و روترهای اینترنت ترافیک دریافتی از این نوع شبکه ها را دورخواهند انداخت .

10.0.0.0 /8 or 255.0.0.0
172.16.0.0 /12 or 255.240.0.0
192.168.0.0 /16 or 255.255.0.0

 اکثر شرکت ها و شبکه های موجود در منازل در حال حاضر از آدرس های IP خصوصی استفاده می نمایند .  شاید برای شما این سوال مطرح شده باشد که با توجه به این که روترها اینگونه آدرس ها را route نخواهند کرد ، نحوه مبادله اطلاعات از طریق کاربران اینگونه شبکه ها برروی اینترنت به چه صورت است ؟  در پاسخ می بایست به این موضوع اشاره نمود که در این نوع شبکه ها از NAT ( برگرفته از network address translation   ) استفاده می گردد .  NAT ، آدرس های IP خصوصی را به آدرس های IP عمومی تبدیل ( ترجمه ) می نماید .( در زمان ارسال و برگشت درخواست کاربران ) .

نکته پنجم : آگاهی از نحوه اشکال زدائی شبکه با استفاده از مدل OSI
اشکال زدائی شبکه از جمله وظایف مهم مدیران شبکه های کامپیوتری است که در صورت عدم تبعیت از یک رویکرد علمی به منظور برخورد با آن ، اتلاف منابع موجود خصوصا" زمان را به دنبال خواهد داشت . به منظور اشکال زدائی  شبکه از روش های متفاوتی استفاده می گردد . پیشنهاد می گردد که از لایه فیزیکی ( لایه اول) مدل OSI کار شروع شود و بتدریج به سمت لایه های دیگر حرکت گردد . رویکرد فوق ، یکی از سریعترین روش های اشکال زدائی در شبکه های کامپیوتری است . 

کنترل های Validation در ASP.NET ( بخش چهارم )

کنترل های Validation در ASP.NET ( بخش چهارم )
 آنچه تاکنون گفته شده است :

  • بخش اول :  ماهیت و جایگاه کنترل های validation و بررسی عملکرد کنترل های <asp:RequiredFieldValidator> و <asp:RangeValidator> 
  • بخش دوم : بررسی عملکرد کنترل های <asp:CompareValidator> و <asp:CustomValidator>
  • بخش سوم : آشنائی با گروه های validation  و  بررسی عملکرد کنترل <asp:ValidationSummary>

در این بخش به  بررسی برخی نکات خاص در خصوص ایمن سازی برنامه های وب با تمرکز بر روی کنترل های Validation خواهیم پرداخت .  

تهدیدات امنیتی در صورت عدم ارزیابی داده ورودی
برنامه های وب ، داده مورد نیاز خود را از طریق درخواست های مبتنی بر پروتکل HTTP  دریافت می نمایند ( در برخی موارد ممکن است داده مورد نیاز یک برنامه وب  از طریق یک فایل تامین گردد). با توجه به ماهیت پروتکل فوق ، مهاجمان می توانند هر بخشی از یک درخواست HTTP  نظیر   url ، querystring ،  هدر ، کوکی ها ، فیلدهای موجود بر روی فرم و فیلدهای مخفی را تحریف تا ضمن نادیده گرفتن مکانیزم های امنیتی بکارگرفته شده در یک سایت ، آن را با مشکلات امنتیی متعددی مواجه نمایند. حملات forced browsing, command insertion, cross site scripting, buffer overflows, format string attacks و SQL injection نمونه هائی در این زمینه می باشند . 
تعداد زیادی از برنامه های وب صرفا" از مکانیزم های سمت سرویس گیرنده به منظور بررسی و ارزیابی داده ورودی استفاده می نمایند . مهاجمان با استفاده از روش های متفاوتی می توانند مکانیزم های استفاده شده به منظور ارزیابی داده ورودی را نادیده گرفته و برنامه های وب را در مقابل داده ورودی مخرب خلع سلاح نمایند . مهاجمان ، بدین منظور می توانند با استفاده از ابزارهائی نظیر telnet درخواست های HTTP را تولید نمایند . بدیهی است در چنین مواردی نباید انتظار داشت آنان واکنش هائی را که مد نظر پیاده کنندگان برنامه های وب در سمت سرویس گیرنده است ،‌ انجام دهند . با این که بررسی و ارزیابی داده ورودی در سمت سرویس گیرنده یک ایده عالی است و می تواند به عنوان یک اقدام مناسب در  جهت افزایش کارآئی برنامه های وب تلقی گردد ولی قطعا" رویکرد فوق دارای مزیت امنیتی خاصی نخواهد بود .
به منظور ارزیابی داده ورودی می بایست از روش های سمت سرویس دهنده استفاده گردد تا یک لایه دفاعی مناسب به منظور پیشگیری از درج داده مخرب توسط مهاجمان ایجاد گردد . پس از تحقق خواسته فوق ، می توان با دقت اقدام به بهینه سازی روش های استفاده شده به منظور بررسی و ارزیابی داده ورودی در سمت سرویس گیرنده نیز نمود تا ترافیک غیرضروری بر روی سرویس دهنده به حداقل مقدار ممکن برسد .

بررسی یک نمونه  
 در برخی موارد از داده ورودی در یک TextBox به منظور ایجاد یک query در ارتباط با یک بانک اطلاعاتی استفاده می گردد . روش فوق ، ممکن است مسائل و مشکلات امنیتی متعددی را به دنبال داشته باشد ( از عدم اجرای اسکریپت ها گرفته تا بروز اشکال در بانک اطلاعاتی ) . مجددا" لازم است به این نکته مهم اشاره گردد که کنترل های validation ، به منزله اولین لایه دفاعی در مقابل درج داده مخرب محسوب می گردند و این اطمینان را ایجاد می نمایند که صرفا" داده معتبر در اختیار سایر لایه های یک برنامه خصوصا" لایه داده آن قرار داده خواهد شد .
مهاجمان می توانند از طریق TextBox استفاده شده بر روی یک فرم ،‌ کدهای مخربی را به سیستم وارد نمایند که حذف تمامی بانک اطلاعاتی را به دنبال داشته باشد . با این که همواره فرض پیاده کنندگان برنامه های وب بر این است که از TextBox برای درج داده در سیستم استفاده خواهد شد ، ولی واقعیت این است که ممکن است از آنها برای درج کد نیز استفاده گردد . SQL injection یک نمونه از تهدیدات موجود در این زمینه است .

SQL Injection
فرض کنید از یک TextBox برای درج داده بر روی یک فرم استفاده شده باشد و پس از درج داده توسط کاربر ، از آن به منظور بازیابی رکوردهائی خاص از یک بانک اطلاعاتی استفاده می گردد . بدین منظور ، از دستور SELECT به صورت زیر استفاده شده است :

 SQLString = "SELECT * FROM MyTable WHERE MyKey = '" & MyTextBox.Text & "'"

دستور SELECT ، به صورت پویا از مقدار درج شده در TextBox استفاده می نماید . ظاهرا" همه چیز درست است و مشکل خاصی وجود نخواهد داشت ولی فرض کنید  کاربری کد SQL زیر را در TextBox وارد نماید :

   Search :    

پس از درج داده فوق در TextBox  ، وضعیت query نوشته شده در  برنامه به صورت زیر خواهد بود :

 SELECT * FROM MyTable WHERE MyKey = ' ' ; DROP DATABASE MyDatabase

در چنین مواردی ، عبارت SQL شامل دو دستور مجزاء می گردد که اولین دستور آن با توجه به ماهیت داده ورودی مقدار null خواهد بود و عملا" رکوردی را برنمی گرداند و دومین عبارت SQL ، باعث حذف یک بانک اطلاعاتی خواهد شد . بدین ترتیب یک SQL injection محقق می گردد و کد مخرب با داده مورد انتظار در عبارت SQL جایگزین می شود. با این که در یک بانک اطلاعاتی اکسس ، نمی توان چندین عبارت SQL را در یک خط استفاده نمود ولی برخی از سیستم های مدیریت بانک های اطلاعاتی قادر به اجراء کد فوق خواهند بود .
پیاده کنندگان برنامه های وب می توانند از کنترل های validation به منظور بلاک نمودن اینچنین کدهائی استفاده نمایند . بدین منظور می توان طول رشته ورودی ، نوع داده ورودی و یا وجود داده ورودی در یک محدوده خاص را بررسی نمود . تست های فوق در مواردی که داده ورودی از نوع string و با طول نامشخص باشند ، کارساز نبوده و نمی توان از کنترل های اشاره شده در جهت ایجاد یک سطح حفاظتی مناسب استفاده نمود . 

راه حل چیست ؟ 
بهترین روش برای حفاظت در مقابل ورود کدهای مخرب به سیستم ، استفاده از عبارات SQL به صورت پارامتریک در مقابل بکارگیری مستقیم داده ورودی است . پارامترها ، مکان لازم برای نگهداری مقادیر داده را فراهم نموده و این اطمینان را ایجاد می نمایند که از مقادیر ورودی مستقیما" در کد استفاده نخواهد شد . 
در کد زیر از یک عبارت SELECT به منظور بازیابی رکوردهائی خاص از جدول Books در بانک اطلاعاتی BooksDB استفاده شده است . عبارت SQL به عنوان خصلت SelectCommand کنترل منبع داده AccessDataSource ( با " id="BookSource ) در نظر گرفته شده است .

 Sub Get_Record (Src As Object, Args As EventArgs)

  Dim SQLString As String
  SQLString = "SELECT BookID, BookTitle, BookPrice FROM Books" & _
                     "
WHERE BookID = @BookID"
  BookSource.SelectCommand = SQLString

End Sub

یک پارامتر با استفاده از نام خود که به دنبال یک کاراکتر "@" می آید ( در این مثال BookID @  ) ، مشخص می گردد و یک مرجع به داده ورودی است که در عبارت SELECT و به منظور بازیابی رکوردهای مورد نظر استفاده می گردد . فرض کنید ، کاربر داده زیر را در TextBox وارد نماید :

  Book ID :    

مقدار ورودی در TextBox ، به عنوان مقدار پارامتر BookID @   در عبارت SELECT در نظر گرفته می شود . در چنین مواردی ، می بایست با صراحت مقدار درج شده در TextBox را با پارامتر فوق مرتبط نمود . زمانی که از کنترل AccessDataSource به منظور بازیابی داده از یک بانک اطلاعاتی استفاده می گردد ، برای مشخص کردن پارامترهای مورد نیاز در یک عبارت SELECT ، می بایست از بخش <SelectParameters>   در کنترل استفاده گردد . در این بخش می توان از یک و یا چندین کنترل <asp:ControlParameter> استفاده نمود . با استفاده از کنترل <asp:ControlParameter> ، می بایست یک نام را برای پارامتر در نظر گرفت .همچنین ، لازم است کنترلی که قرار است مقدار آن به عنوان پارامتر در نظر گرفته شود نیز مشخص گردد.
کد زیر نحوه استفاده از پارامتر BookID @  در کنترل AccessDataSource را نشان می دهد .

 Book ID:
  <asp:TextBox id="BookIDInput" Runat="Server"/>
  <asp:Button Text="Find" OnClick="Get_Record" Runat="Server"/>

  <asp:AccessDataSource id="MySource" Runat="Server" DataFile="../DB/BooksDB.mdb">
     <SelectParameters>
         <asp:ControlParameter Name="BookID" ControlID="BookIDInput" PropertyName="Text"/>
     </SelectParameters>
</asp:AccessDataSource>

توضیحات :

  • کنترل  <asp:ControlParameter>  از سه خصلت به منظور ایجاد ارتباط با کنترلی که داده مورد نیاز را تامین خواهد کرد ، استفاده می نماید .

  • خصلت Name ، نام در نظر گرفته شده برای پارامتر را که از آن در عبارت SELECT استفاده خواهد شد را مشخص می نماید .

  • خصلت ControlID ، شناسه (id ) کنترلی است که داده مورد نیاز برای پارامتر را مشخص می نماید .
     

  • PropertyName ، خصلت کنترلی است که از مقدار آن به عنوان مرجع استفاده می گردد ( در این مثال خصلت Text مربوط به کنترل TextBox ) .
     

  • در مثال فوق از یک پارامتر در عبارت SELECT استفاده شده است ، بنابراین به یک کنترل  <asp:ControlParameter> نیاز می باشد. در صورتی که لازم است از چندین پارامتر استفاده شود ، می بایست برای هر یک از آنها از یک کنترل <asp:ControlParameter> استفاده گردد .

سادگی کد نویسی
با پارامتر درج شده در یک عبارت SELECT به عنوان یک مقدار داده literal برخورد می شود . بنابراین ، بر خلاف زمانی که از رشته های متصل شده به هم به منظور بکارگیری یک عبارت SQL استفاده می گردد ، احتمال درج داده مخرب بطرز مشهودی کاهش خواهد یافت . استفاده از پارامتر در عبارات SQL ، کاهش پیچیدگی کدینگ عبارات SQL را نیز به دنبال خواهد داشت .
کد زیر یک نمونه عبارت SQL را نشان می دهد که در آن از یک رشته متصل شده به هم استفاده شده است :

 SQLString = "SELECT * FROM Books WHERE " & _
         "BookType = '" & TypeTextBox.Text & "' AND " & _
         "BookPrice > " & PriceTextBox.Text & " AND " & _
         "BookQty <= " & QtyTextBox.Text & " AND " & _
         "BookTitle LIKE '%" & TitleTextBox.Text & "%'"

کد فوق را می توان با عبارت زیر جایگزین نمود :

 SQLString = SELECT * FROM Books WHERE " & _
        "BookType = @BookType AND BookPrice > @BookPrice AND " & _
        "BookQty <= @BookQty AND BookTitle LIKE @BookQty"

درون کنترل AcessDataSource ، می بایست از یک بخش SelectParameters به منظور معرفی کنترل هائی که مقدار مورد نیاز هر یک از پارامترها را تامین می نمایند ، استفاده گردد .

کنترل های Validation در ASP.NET ( بخش سوم )

کنترل های Validation در ASP.NET ( بخش سوم )
در بخش اول به ماهیت و جایگاه کنترل های validation اشاره و عملکرد دو  کنترل <asp:RequiredFieldValidator> و <asp:RangeValidator> بررسی گردید.در بخش دوم  با کنترل های <asp:CompareValidator> و <asp:CustomValidator> آشنا شدیم . در این بخش به بررسی سایر کنترل های validation خواهیم پرداخت .

گروه های validation
در زمان پیاده سازی فرم های ورود اطلاعات به مواردی برخورد خواهیم کرد که لازم است از چندین TextBox به منظور دریافت داده ورودی جهت انجام پردازش های مورد نیاز در یک اسکریپت ، استفاده گردد .همچنین ، ممکن است در مواردی لازم باشد که از چندین button در یک فرم ورود اطلاعات استفاده گردد و متناسب با این که کدام button توسط کاربران فعال شده است ، بررسی و صحت داده ورودی تعداد خاصی از کنترل های موجود بر روی فرم ورود اطلاعات ( مستقل از سایر کنترل ها ) ، انجام شود . در چنین مواردی می بایست تمامی کنترل هائی را که می خواهیم  پس از کلیک بر روی یک button خاص ،    validate شوند را عضوء یک گروه نمود و نام آن گروه را برای button مورد نظر نیز مشخص نمود . بدین ترتیب ، پس از کلیک بر روی button مورد نظر صرفا" آندسته از کنترل هائی که عضوء گروه هم نام با گروه معرفی شده به همراه button می باشند ، بررسی و ارزیابی خواهند شد .

مثال
در فرم ورود اطلاعات زیر از چندین کنترل ( چهار کنترل TextBox )  استفاده شده است که تمامی آنها عضوء یک گروه validation می باشند . پس از کلیک بر روی دکمه "ارسال اطلاعات " ، صرفا" آندسته از کنترل هائی که کنترل های validation آنها عضوء گروه مشخص شده می باشند ، validate خواهند شد .

 
فرم ورود اطلاعات : استفاده از چهار کنترل TextBox که تمامی آنها عضوء یک گروه Validation می باشند
 

<SCRIPT Runat="Server">

Sub Validate_Email (Src As Object, Args As ServerValidateEventArgs)

  If InStr(Args.Value, "@") = 0 Then
      EmailValidator.ErrorMessage = "لطفا یک آدرس پست الکترونیکی صحیح را وارد نمائید"
      Args.IsValid = False
  End If

End Sub

Sub
Get_Data (Src As Object, Args As EventArgs)

  If Page.IsValid Then
     Output.Text = "You entered valid data"
  End If

End Sub

</SCRIPT>


<
form Runat="Server">

<h3>فرم ورو اطلاعات</h3>

<table border="0" cellpadding="2">
<tr>
<td>نام:</td>
<td><asp:TextBox id="FirstName" Runat="Server"/></td>
<td><asp:RequiredFieldValidator Runat="Server"
        ControlToValidate="FirstName"
        ValidationGroup="Group1"
        ErrorMessage="لطفا  نام خود را وارد نمائید"
        Display="Dynamic"/></td>
</tr>
<tr>
<td>نام خانوادگی:</td>
<td><asp:TextBox id="LastName" Runat="Server"/></td>
<td><asp:RequiredFieldValidator Runat="Server"
         ControlToValidate="LastName"
         ValidationGroup="Group1"
         ErrorMessage="لطفا  نام خانوادگی خود را وارد نمائید"
         Display="Dynamic"/></td>
</tr>
<tr>
<td>سن:</td>
<td><asp:TextBox id="Age" Width="50" Runat="Server"/></td>
<td><asp:RangeValidator Runat="Server"
         ControlToValidate="Age"
         ValidationGroup="Group1"
         Type="Integer"
          MinimumValue="15"
          MaximumValue="99"
          ErrorMessage="لطفا" یک عدد بین پانزده تا نود و نه را وارد نمائید "
          Display="Dynamic"/>
<asp:RequiredFieldValidator Runat="Server"
        ControlToValidate="Age"
        ValidationGroup="Group1"
        ErrorMessage="لطفا  سن خود را وارد نمائید  "
        Display="Dynamic"/></td>
</tr>
<tr>
<td>آدرس پست الکترونیکی:</td>
<td><asp:TextBox id="Email" Runat="Server"/></td>
<td><asp:CustomValidator id="EmailValidator" Runat="Server"
         ControlToValidate="Email"
         ValidationGroup="Group1"
         Display="Dynamic"
         OnServerValidate="Validate_Email"/>
<asp:RequiredFieldValidator Runat="Server"
        ControlToValidate="Email"
        ValidationGroup="Group1"
         ErrorMessage="لطفا  آدرس پست الکترونیکی خود را وارد نمائید"
         Display="Dynamic"/></td>
</tr>
</table>
<br/>
<asp:Button Text="
ارسال اطلاعاتValidationGroup="Group1"
        OnClick="Get_Data" Runat="Server"/>
<asp:Label id="Output" Runat="Server"/><br/>

</form>

به دکمه "ارسال اطلاعات "  ، یک نام گروه validation  نسبت داده شده است تا پس از کلیک بر روی آن ، کنترل هائی که کنترل های validation آنها عضوء گروهی با همین نام می باشند ، بررسی و ارزیابی گردند . در صورتی که از کنترل های validation دیگر بر روی فرم استفاده شده است که عضوء گروه validation نمی باشند ، پس از کلیک بر روی دکمه "ارسال اطلاعات " ، ارزیابی نخواهند شد .
پس از کلیک بر روی هر button موجود بر روی یک فرم ، صرفا" آندسته از کنترل هائی بررسی و ارزیابی خواهند شد که تشکیل یک گروه را می دهند و از یک نام مشابه برای گروه استفاده می نمایند که همانند نام نسبت داده شده به button مورد نظر است .

 کنترل <asp:ValidationSummary>
با استفاده از کنترل <asp:ValidationSummary> ، پیام های خطاء جداگانه توسط یک کنترل تولید و با یکدیگر نمایش داده می شوند. کنترل فوق ، همچنین قادر به تولید گزارش پیام های خطاء محدود به مجموعه ای خاص از کنترل ها می باشد . 

شکل عمومی
شکل عمومی کنترل فوق به صورت زیر است :

<asp:ValidationSummary id="id" Runat="Server"
DisplayMode="BulletList|List|SingleParagraph"
HeaderText="string"
ShowMessageBox="False|True"
ShowSummary="False|True"
ValidationGroup="name"
/>

توضیحات 

  • خصلت DisplayMode ، نحوه ( فرمت ) نمایش پیام های خطاء را مشخص می نماید که به صورت پیش فرض یک لیست bulleted در نظر گرفته می شود .

  • مکان نمایش گزارش پیام های خطاء در محلی است که کنترل ValidatiomSummary استفاده شده است .

  • با استفاده از خصلت ShowMessageBox و نسبت دادن مقدار True به آن ، یک پیام pop-up نمایش داده خواهد شد .  بدین ترتیب ، خروجی کنترل ValidationSummary در یک PoP-Up نمایش داده می شود .

  • در صورتی که خلاصه گزارش خطاء مرتبط با یک گروه validation  خاص می باشد ، می بایست نام آن گروه به خصلت ValidationGroup نسبت داده شود .

مثال
مثال زیر ، بازنویسی مثال قبل است . با این تفاوت که در مقابل نمایش جداگانه پیام های خطاء ، از یک کنترل ValidationSummary استفاده شده است .

استفاده از کنترل ValidationSummary

<SCRIPT Runat="Server">

Sub
Validate_Email (Src As Object, Args As ServerValidateEventArgs)

  If InStr(Args.Value, "@") = 0 Then
      EmailValidator.ErrorMessage = "لطفا یک آدرس پست الکترونیکی صحیح را وارد نمائید"
      Args.IsValid = False
  End If

End Sub

Sub
Get_Data (Src As Object, Args As EventArgs)

 If Page.IsValid Then
      Output.Text = "You entered valid data"
 End If

End Sub

</SCRIPT>


<form Runat="Server">

<h3>فرم ورو اطلاعات</h3>

<table border="0" cellpadding="2">
<tr>
<td>نام:</td>
<td><asp:TextBox id="FirstName" Runat="Server"/></td>
<td><asp:RequiredFieldValidator Runat="Server"
        ControlToValidate="FirstName"
        ValidationGroup="Group1"
        ErrorMessage=" نام "
        Display="None"/></td>
</tr>
<tr>
<td>نام خانوادگی:</td>
<td><asp:TextBox id="LastName" Runat="Server"/></td>
<td><asp:RequiredFieldValidator Runat="Server"
         ControlToValidate="LastName"
         ValidationGroup="Group1"
         ErrorMessage=" نام خانوادگی "
      
Display="None"/></td>
</tr>
<tr>
<td>سن:</td>
<td><asp:TextBox id="Age" Width="50" Runat="Server"/></td>
<td><asp:RangeValidator Runat="Server"
         ControlToValidate="Age"
         ValidationGroup="Group1"
         Type="Integer"
          MinimumValue="15"
          MaximumValue="99"
          ErrorMessage="یک عدد بین پانزده تا نود و نه  "
       
Display="None"/>
<asp:RequiredFieldValidator Runat="Server"
        ControlToValidate="Age"
        ValidationGroup="Group1"
        ErrorMessage=" سن   "
     
Display="None"/></td>
</tr>
<tr>
<td>آدرس پست الکترونیکی:</td>
<td><asp:TextBox id="Email" Runat="Server"/></td>
<td><asp:CustomValidator id="EmailValidator" Runat="Server"
         ControlToValidate="Email"
         ValidationGroup="Group1"
        
Display="None"/>
         OnServerValidate="Validate_Email"/>
<asp:RequiredFieldValidator Runat="Server"
        ControlToValidate="Email"
        ValidationGroup="Group1"
         ErrorMessage="  آدرس پست الکترونیکی  "
       
Display="None"/></td>
</tr>
</table>
<br/>
<asp:Button Text="Submit" ValidationGroup="Group1"
         OnClick="Get_Data" Runat="Server"/>
<asp:Label id="Output" Runat="Server"/><br/>

<asp:ValidationSummary Runat="Server"
     ValidationGroup=
"Group1"
     DisplayMode=
"BulletList"
     HeaderText=
" لطفا اطلاعات زیر را وارد نمائید "
     ShowSummary=
"True"
     ShowMessageBox=
"False"/>

</form>

در بخش چهارم به بررسی برخی نکات خاص در خصوص ایمن سازی برنامه های وب با تمرکز بر روی کنترل های Validation خواهیم پرداخت .  

کنترل های Validation در ASP.NET ( بخش اول )

کنترل های Validation در ASP.NET ( بخش اول )
بررسی و ارزیابی صحت اطلاعات ورودی توسط کاربران ، یکی از عملیات بسیار مهم در برنامه های کامپیوتری خصوصا" برنامه های وب با توجه به ماهیت معماری آنها می باشد . پیاده کنندگان برنامه های وب می بایست پس از درج داده ورودی توسط کاربر و  قبل از ارسال آن به لایه های دیگر ، آنها را ارزیابی و صرفا" پس از تائید ، پردازش های مورد نیاز را بر روی آنها انجام دهند . اعتقاد عملی به سیاست فوق باعث پیشگیری تعداد زیادی از حملات در برنامه های‌ وب می گردد . در صورت عدم رعایت موارد اشاره شده ، شرایط لازم به منظور سوء استفاده از پتانسیل فوق فراهم و مهاجمان می توانند با بهره برداری از نقاط ضعف موجود  ، حملات خود را برنامه ریزی نمایند .
در این مقاله به بررسی امکانات ارائه شده در ASP.NET به منظور ارزیابی صحت داده ورودی خواهیم پرداخت . آشنائی و بکارگیری روش های مناسب به منظور بررسی صحت داده ورودی یکی از عملیات مهم در جهت ایمن سازی برنامه های وب نیز می باشد . پس با انگیزه و دقت مضاعف کار را دنبال می نمائیم .

ضرورت و ماهیت کنترل های Validation
زمانی که از یک TextBox برای درج داده بر روی‌ یک فرم استفاده می گردد ،‌ همواره این احتمال وجود خواهد داشت که کاربران اطلاعات را متناسب با انتظار یک برنامه وارد نمایند . به عنوان مثال ،‌ فرض کنید که در یک فرم وب از دو TextBox برای درج داده عددی توسط کاربران استفاده شده است و  در ادامه  می بایست اطلاعات ورودی در اختیار یک روتین جهت انجام پردازش های مورد نیاز ( به عنوان نمونه ، انجام عملیات محاسباتی بر روی داده های ورودی ) قرار داده شود . در صورتی که کاربران داده را در محدوده مجاز وارد ننمایند و یا ورودی از نوع عددی نباشد ، روتین مورد نظر در انجام پردازش های خود با مشکل مواجه خواهد شد .  بنابراین ، می بایست  همواره قبل از این که داده ورودی در اختیار روتین های مورد نظر جهت انجام پردازش های مشخص شده قرار داده شود ،  آنها را بررسی و در صورت رعایت مجموعه سیاست های تعریف شده ، امکان استفاده از آنها را برای اسکریپت ها فراهم نمود .
به منظور ارزیابی داده ورودی توسط کاربران با توجه به داده مورد نیاز اسکریپت ها ،‌ از روش های متعددی می توان استفاده نمود .  متداولترین نیاز ، وجود یک مقدار ورودی است . در چنین مواردی ، انتظار داریم قبل از این که یک اسکریپت بتواند پردازش های مورد نیاز را بر روی داده ورودی انجام دهد، در TextBox مقداری درج شده باشد. ماهیت داده ورودی در این مقطع مهم نمی باشد و مهم این است که داده ئی توسط کاربر در مکان مورد نظر وارد شده باشد . در برخی موارد لازم است که داده ورودی از یک نوع خاص باشد ( به عنوان نمونه یک مقدار عددی ) تا بتوان آن را در اختیار روتین های مورد نظر به منظور انجام پردازش های محاسباتی قرار داد . در برخی موارد دیگر ، لازم است که داده ورودی در یک محدوده خاص باشد و داده درج شده خارج از محدوده مورد نظر ، غیرمعتبر گردد .
برای بررسی و ارزیابی صحت داده در ASP.NET مجموعه ای از کنترل های validation ارائه شده است . از کنترل های فوق  می توان به منظور بررسی و تست عدم درج داده ، مقایسه داده ورودی با یک مقدار خاص  ، بررسی وجود مقادیر در یک محدوده خاص و سایر فرم های داده استفاده نمود تا این اطمینان ایجاد گردد که داده مناسب و معتبر در اختیار اسکریپت ها و به منظور انجام پردازش ها قرار داده می شود .
کنترل های validation در ارتباط مستقیم با کنترل TextBox بوده و تست و ارزیابی خود را بطور اتوماتیک و پس از کلیک بر روی کنترل هائی نظیر Button  ، LinkButton  و ImageButton انجام خواهند داد . در صورتی که ماحصل بررسی یک کنترل validation توام با موفقیت نباشد ، validator یک پیام خطاء را نمایش و به کاربران اعلام می نماید که داده ورودی فاقد شرایط لازم برای استفاده در برنامه می باشد .
در شکل زیر کنترل های Validation ارائه شده در ASP.NET 2.0   ،‌ نشان داده شده است .
 

کنترل های Validation در ASP.NET
کنترل های Validation

در ادامه به بررسی کنترل های فوق خواهیم پرداخت .

کنترل <asp:RequiredFieldValidator>
متداولترین نوع ارزیابی داده ورودی ، بررسی آن به منظور اطمینان از درج داده توسط کاربر است . کنترل <asp:RequiredFieldValidator>  ، مسئولیت بررسی داده ورودی در یک Textbox را برعهده گرفته و در صورت عدم درج داده توسط کاربر ، یک پیام خطاء را نمایش خواهد داد . در چنین مواردی ، روتین هائی که می بایست  پس از کلیک بر روی دکمه موجود از داده درج شده در TextBox استفاده نمایند ، فرصت انجام چنین کاری را به دلیل عدم درج داده توسط کاربر پیدا نخواهند کرد .

شکل عمومی
شکل عمومی کنترل فوق به صورت زیر است :

<asp:RequiredFieldValidator id="id" Runat="Server"
   ControlToValidate="controlID"
   Display="Dynamic|None|Static"
   ErrorMessage="string"
   SetFocusOnError="False|True"
   ValidationGroup="name"
/>

توضیحات 

  • از یک id صرفا" زمانی استفاده می شود که قرار است به کنترل از طریق اسکریپپ مراجعه گردد .

  • به خصلت  ControlToValidate ، مقدار id کنترل textBox که مسئولیت بررسی آن به کنترل RequiredFieldValidator واگذار شده است ،‌نسبت داده می شود.

  • خصلت ErrorMessage ، پیام مورد نظر در صورت بروز خطاء را مشخص می نماید .

  • خصلت SetFocusOnErrorMessage ، یک blinking cursor را در کنترل TextBox مربوطه به منظور تسهیل در امر درج داده جدید قرار می دهد .

  • خصلت ValidationGroup یک گروه از کنترل های TextBox را که مجموعه ای از تست های بررسی روی آنها اعمال خواهد شد ، مشخص می نماید (در مواردی که دکمه های متفاوت می توانند باعث فعال شدن تست های مختلفی گردند ) .

  • خصلت Display : کنترل RequiredFieldValidator ، یک فضای افقی را متناسب با طول رشته مربوط به پیام خطاء اشغال خواهد کرد . در اغلب موارد ، پیام خطاء در کنار TextBox مربوطه نمایش داده می شود . مکان فوق بر روی صفحه همواره نشان داده خواهد شد ( ولو این که خطائی اتفاق نیافتد ) . در صورتی که مقدار خصلت Display معادل Dynamic در نظر گرفته شود ، مکانی برای نمایش پیام خطاء رزو نخواهد شد و  بطور پویا و همزمان با بروز خطاء ایجاد می گردد . 

مثال
در این مثال زمانی که کاربر بر روی button کلیک نمود ، کنترل RequiredFieldValidator  بطور اتوماتیک عملیات بررسی و ارزیابی داده ورودی در TextBox را آغاز می نماید ( قبل از این که روتین Get_Data فراخوانده شود ) . در صورتی که TextBox خالی باشد ،‌ یک پیام خطاء نمایش داده شده و cursor مجددا" در TextBox قرار خواهد گرفت . در صورتی که در TextBox داده ئی توسط کاربر درج گردد ، تست ارزیابی با موفقیت انجام و روتین مربوط فراخوانده شده و مقدار ورودی را در خروجی نمایش خواهد داد . در این مثال ، مقدار خصلت Display کنترل RequiredFieldValidator ،‌ معادل Dynamic در نظر گرفته شده است ، بنابراین در صورت عدم تولید یک پیام خطاء ، مکانی بر روی صفحه برای نمایش آن در نظر گرفته نخواهد شد . بدین ترتیب به کنترل label اجازه داده می شود که در کنار TextBox نمایش داده شده و از فضای مشابه پیام خطاء استفاده نماید ( استفاده مشترک از یک مکان بر روی فرم وب به منظور نمایش پیام خطاء و یا داده ورودی توسط کاربر ) .

<SCRIPT Runat="Server">

    Sub Get_Data (Src As Object, Args As EventArgs)
       Output.Text = "You entered '" & MyTextBox.Text & "'"
    End Sub

</SCRIPT>


<form Runat="Server">

<asp:TextBox id="MyTextBox" Runat="Server"/>
<asp:Button Text="Submit" OnClick="Get_Data" Runat="Server"/>
<asp:RequiredFieldValidator Runat="Server"
   ControlToValidate="MyTextBox"
   ErrorMessage="Please enter a data value"
   Display="Dynamic"
   SetFocusOnError="True"/>
<asp:Label id="Output" Runat="Server"/>

</form>

 کنترل <asp:RangeValidator>
کنترل فوق مسئولیت بررسی و ارزیابی داده ورودی در یک TextBox را برعهده گرفته و ماموریت آن حصول اطمینان از این موضوع است که داده درج شده در محدوده مورد نظر است . این محدوده توسط دو خصلت  MinimumValue  و MaximumValue  مشخص می گردد . فرآیند فوق می تواند در ارتباط با نوع های متفاوت داده  نظیر  Date ، اعداد صحیح ، اعداد اعشاری و یا رشته ( مقدار پیش فرض ) اعمال گردد . 

شکل عمومی
شکل عمومی کنترل فوق به صورت زیر است :

<asp:RangeValidator id="id" Runat="Server"
   ControlToValidate="controlID"
   Display="Dynamic|None|Static"
   ErrorMessage="string"
   MaximumValue="value"
   MinimumValue="value"
   SetFocusOnError="False|True"
   Type="Currency|Date|Double|Integer|String"
   ValidationGroup="name"
/>

توضیحات 

  • از یک id صرفا" زمانی استفاده می شود که قرار است به کنترل از طریق اسکریپپ مراجعه گردد .

  • خصلت ErrorMessage ، پیام مورد نظر در صورت بروز خطاء را مشخص می نماید .

  • خصلت SetFocusOnErrorMessage ، یک blinking cursor را در کنترل TextBox مربوطه به منظور تسهیل در امر درج داده جدید قرار می دهد .

  • خصلت ValidationGroup یک گروه از کنترل های TextBox را که مجموعه ای از تست های بررسی روی آنها اعمال خواهد شد ، مشخص می نماید (در مواردی که دکمه های متفاوت می توانند باعث فعال شدن تست های مختلفی گردند ) .

  • خصلت Display : کنترل RangeValidator ، یک فضای افقی را متناسب با طول رشته مربوط به پیام خطاء اشغال خواهد کرد . در اغلب موارد ، پیام خطاء در کنار TextBox مربوطه نمایش داده می شود . مکان فوق بر روی صفحه همواره نشان داده خواهد شد ( ولو این که خطائی اتفاق نیافتد ) . در صورتی که مقدار خصلت Display معادل Dynamic در نظر گرفته شود ، مکانی برای نمایش پیام خطاء رزو نخواهد شد و  بطور پویا و همزمان با بروز خطاء ایجاد می گردد . 

  • خصلت Type : در صورتی که نوع داده ورودی مشخص نگردد ،‌ نوع آن به صورت پیش فرض string در نظر گرفته خواهد شد .  یک TextBox خالی ، به عنوان یک نوع داده معتبر ارزیابی خواهد شد . بنابراین ، لازم است که به همراه کنترل RangeValidator از یک کنترل RequiredFieldValidator نیز استفاده گردد تا این اطمینان حاصل شود که با عدم درج داده در TextBox مربوطه با آْن به عنوان یک داده معتبر برخورد نخواهد شد .

  • خصلت های MinimumValue  و MaximumValue  ، حداقل و حداکثر محدوده مجاز برای داده ورودی را مشخص می نمایند .

مثال
در این مثال به منظور ارزیابی و تست داده ورودی در یک TextBox از دو کنترل RangeValidator  و RequiredFieldValidator استفاده شده است . بنابراین می بایست حتما" در TextBox مقداری درج گردد . با توجه به این که مقدار خصلت Type معادل integer و مقادیر خصلت های MinimumValue و MaximumValue به ترتیب صفر و نه در نظر گرفته شده اند ،‌داده ورودی می بایست عددی بین صفر تا نه باشد .

<SCRIPT Runat="Server">

   Sub Get_Data (Src As Object, Args As EventArgs)
      Output.Text = "You entered '" & MyTextBox.Text & "'"
   End Sub

</SCRIPT>

<form Runat="Server">

Enter a value between 0 and 9:<br/>
<asp:TextBox id="MyTextBox" Runat="Server"/>
<asp:Button Text="Submit" OnClick="Get_Data" Runat="Server"/>
<asp:RangeValidator Runat="Server"
   ControlToValidate="MyTextBox"
   Type="Integer"
   MinimumValue="0"
   MaximumValue="9"
   ErrorMessage="Please enter an integer in the range 0 to 9"
   Display="Dynamic"
   SetFocusOnError="True"/>
<asp:RequiredFieldValidator Runat="Server"
    ControlToValidate="MyTextBox"
    ErrorMessage="Please enter a data value"
    Display="Dynamic"
    SetFocusOnError="True"/>
<asp:Label id="Output" Runat="Server"/>

</form>

در بخش دوم به بررسی سایر کنترل های Validation خواهیم پرداخت .

کنترل های Validation در ASP.NET ( بخش دوم )

کنترل های Validation در ASP.NET ( بخش دوم )
در بخش اول به ماهیت و جایگاه کنترل های validation اشاره و عملکرد دو     کنترل <asp:RequiredFieldValidator>   و    <asp:RangeValidator>  بررسی گردید . در این بخش به بررسی سایر کنترل های validation خواهیم پرداخت .

کنترل <asp:CompareValidator>
کنترل فوق مسئولیت بررسی‌ مقدار درج شده در یک TextBox  را برعهده دارد . بدین منظور داده ورودی با یک مقدار خاص و یا مقدار یک کنترل موجود بر روی فرم مقایسه می گردد . نوع داده درج شده در TextBox می تواند از نوع Currency ، Date ، اعشاری ، صحیح و یا رشته ( مقدار پیش فرض ) باشد . 

شکل عمومی
شکل عمومی کنترل فوق به صورت زیر است :

<asp:CompareValidator id="id" Runat="Server"
ControlToCompare="controlID"
ControlToValidate="controlID"
Display="Dynamic|None|Static"
ErrorMessage="string"
Operator="Equal|NotEqual|GreaterThan|GreaterThanEqual|LessThan
                  |LessThanEqual|DataTypeCheck"
SetFocusOnError="False|True"
Type="Currency|Date|Double|Integer|String"
ValidationGroup="name"
ValueToCompare="value"
/>

توضیحات 

  • از یک id صرفا" زمانی استفاده می شود که قرار است به کنترل از طریق اسکریپپ مراجعه گردد .

  • به خصلت ControlToValidate ، مقدار id کنترل textBox که مسئولیت بررسی آن به کنترل <asp:CompareValidator> واگذار شده است ،‌نسبت داده می شود.

  • خصلت ErrorMessage ، پیام مورد نظر در صورت بروز خطاء را مشخص می نماید .

  • خصلت SetFocusOnErrorMessage ، یک blinking cursor را در کنترل TextBox مربوطه به منظور تسهیل در امر درج داده جدید قرار می دهد .

  • خصلت ValidationGroup یک گروه از کنترل های TextBox را که مجموعه ای از تست های بررسی روی آنها اعمال خواهد شد ، مشخص می نماید (در مواردی که دکمه های متفاوت می توانند باعث فعال شدن تست های مختلفی گردند ) .

  • خصلت Display : کنترل  <asp:CompareValidator> ، یک فضای افقی را متناسب با طول رشته مربوط به پیام خطاء اشغال خواهد کرد . در اغلب موارد ، پیام خطاء در کنار TextBox مربوطه نمایش داده می شود . مکان فوق بر روی صفحه همواره نشان داده خواهد شد ( ولو این که خطائی اتفاق نیافتد ) . در صورتی که مقدار خصلت Display معادل Dynamic در نظر گرفته شود ، مکانی برای نمایش پیام خطاء رزو نخواهد شد و  بطور پویا و همزمان با بروز خطاء ایجاد می گردد . 

  • مقدار ورودی می تواند با یک مقدار مشخص شده توسط خصلت ValueToCompare و یا مقدار یک کنترل دیگر موجود در صفحه ( مشخص شده توسط خصلت ControlToCompare ) ، مقایسه گردد . به صورت پیش فرض ، عملیات مقایسه برای "برابری " انجام خواهد شد . در صورت نیاز می توان از سایر عملگرهای مقایسه ای  که توسط خصلت Operator مشخص می گردند ، استفاده نمود . عملیات مقایسه بر اساس نوع داده درج شده در Textbox که توسط خصلت Type مشخص می گردد ، انجام خواهد شد .

  • خصلت Type : در صورتی که نوع داده ورودی مشخص نگردد ،‌ نوع آن به صورت پیش فرض string در نظر گرفته خواهد شد .  یک TextBox خالی ، به عنوان یک نوع داده معتبر ارزیابی خواهد شد . بنابراین ، لازم است که به همراه کنترل <asp:CompareValidator> از یک کنترل RequiredFieldValidator نیز استفاده گردد تا این اطمینان حاصل شود که با عدم درج داده در TextBox مربوطه با آْن به عنوان یک داده معتبر برخورد نخواهد شد .

مثال
در این مثال ،  کاربر می بایست یک عدد مثبت را وارد نماید و در صورتی که مقدار ورودی منفی باشد یک پیام خطاء نمایش داده می شود . به همراه کنترل CompareValidator از یک کنترل RequiredFieldValidator نیز استفاده شده است تا عدم درج داده ( خالی‌بودن ) به عنوان یک داده معتبر ارزیابی نگردد .
مقدار ورودی می بایست از نوع اعشاری (Type=Double ) و بزرگتر از (Operator=GreaterThan )  صفر (ValueToCompare=0 ) باشد  تا  به عنوان یک داده معتبر ارزیابی گردد  .

<SCRIPT Runat="Server">

Sub Get_Data (Src As Object, Args As EventArgs)
    Output.Text = "You entered '" & MyTextBox.Text & "'"
End Sub

</SCRIPT>


<form Runat="Server">

 Enter a positive number:<br/>
<asp:TextBox id="MyTextBox" Runat="Server"/>
<asp:Button Text="Submit" OnClick="Get_Data" Runat="Server"/>
<asp:CompareValidator Runat="Server"
   ControlToValidate="MyTextBox"
   ValueToCompare="0"
   Type="Double"
   Operator="GreaterThan"
   ErrorMessage="Please enter a number greater than 0"
   Display="Dynamic"
   SetFocusOnError="True"/>
<asp:RequiredFieldValidator Runat="Server"
   ControlToValidate="MyTextBox"
   ErrorMessage="Please enter a data value"
   Display="Dynamic"
   SetFocusOnError="True"/>
<asp:Label id="Output" Runat="Server"/>

</form>

 کنترل <asp:CustomValidator>
در زمان بررسی و ارزیابی داده ورودی ممکن است به مواردی برخورد نمائیم که با ترکیب یک RequiredFieldValidator ، RangeValidator و یا CompareValidator  خواسته ما تامین نگردد. در چنین مواردی می توان از کنترل <asp:CustomValidator> به منظور انجام تست های اضافه استفاده نمود .   

شکل عمومی
شکل عمومی کنترل فوق به صورت زیر است :

<asp:CustomValidator id="id" Runat="Server"
ControlToValidate="controlID"
Display="Dynamic|None|Static"
ErrorMessage="string"
SetFocusOnError="False|True"
ValidationGroup="name"
OnServerValidate="subprogram"
/>

توضیحات 

  • خصلت های کنترل <asp:CustomValidator> مشابه سایر کنترل های validation می باشند با این تفاوت که از خصلت OnServerValidate به منظور فراخوانی یک برنامه فرعی برای بررسی و ارزیابی داده ورودی نیز استفاده می گردد .

  • یک TextBox خالی به عنوان یک داده معتبر در نظر گرفته خواهد شد . بنابراین می بایست به همراه کنترل  CustomValidator از یک کنترل RequiredFieldValidator نیز استفاده گردد تا عدم درج داده به عنوان یک داده معتبر ارزیابی نگردد .

  • برنامه فرعی صدا زده شده دارای آرگومان های خاص ServerValidateArgs می باشد . در صورتی که بررسی و ارزیابی صحت داده ورودی توام با موفقیت نباشد ، مقدار خصلت IsValid معادل false خواهد شد . از آرگومان Value ، به عنوان مرجعی به منظور مراجعه به مقدار TextBox ( کنترل مشخص شده توسط خصلت ControlToValidate ) استفاده می گردد .

  • خصلت ErrorMessage ، پیام مورد نظر در صورت بروز خطاء را مشخص می نماید .

  • خصلت SetFocusOnErrorMessage ، یک blinking cursor را در کنترل TextBox مربوطه به منظور تسهیل در امر درج داده جدید قرار می دهد .

  • خصلت ValidationGroup یک گروه از کنترل های TextBox را که مجموعه ای از تست های بررسی روی آنها اعمال خواهد شد ، مشخص می نماید (در مواردی که دکمه های متفاوت می توانند باعث فعال شدن تست های مختلفی گردند ) .

  • خصلت Display : کنترل <asp:CustomValidator> ، یک فضای افقی را متناسب با طول رشته مربوط به پیام خطاء اشغال خواهد کرد . در اغلب موارد ، پیام خطاء در کنار TextBox مربوطه نمایش داده می شود . مکان فوق بر روی صفحه همواره نشان داده خواهد شد ( ولو این که خطائی اتفاق نیافتد ) . در صورتی که مقدار خصلت Display معادل Dynamic در نظر گرفته شود ، مکانی برای نمایش پیام خطاء رزو نخواهد شد و  بطور پویا و همزمان با بروز خطاء ایجاد می گردد . 

مثال
در این مثال به منظور ارزیابی و تست داده ورودی در یک TextBox از دو کنترل CustomValidator و RequiredFieldValidator استفاده شده است . داده ورودی می بایست یک عدد صحیح بین صفر تا نود و نه باشد .
پس از کلیک بر روی دکمه Submit ، روتین Get_Data فعال و قبل از هر چیز عملیات بررسی و ارزیابی صحت داده ورودی انجام خواهد شد . کنترل RequiredFieldValidator در ابتدا بررسی لازم در خصوص درج داده در TextBox را انجام  و در ادامه روتین Validate_TextBox توسط خصلت OnServerValidate کنترل CustomValidator فراخوانده می شود . روتین فوق ،  تست های لازم را بر روی داده ورودی انجام خواهد داد ( برای مراجعه به داده ورودی از  Args.Value  استفاده شده است ) . در صورتی که هر یک از تست های انجام شده توام با موفقیت نباشد ،  خصلت Args.Isvalid مقدار false را خواهد گرفت ( داده ورودی می بایست یک عدد مثبت بین صفر تا نود و نه باشد ) .
پس از انجام فرآیند بررسی داده ورودی ، روتین Get_Data ، اجرا خواهد شد . روتین فوق در ابتدا و پس از کلیک بر روی دکمه button فراخوانده می گردد و اجرای آن تا زمانی که عملیات بررسی و ارزیابی داده ورودی به اتمام نرسیده باشد ، به تاخیر خواهد افتاد .  پردازش های انجام شده در روتین Get_Data مشروط به انجام موفقیت آمیز تست ارزیابی و صحت داده است . بنابراین ، همه چیز وابسته به شرط Page.IsValid شده است و  در صورتی که Args.IsValid معادل false شده باشد  ، مقدار Page.IsValid  نیز false خواهد شد.

<SCRIPT Runat="Server">

 Sub Validate_TextBox (Src As Object, Args As ServerValidateEventArgs)

  If Not IsNumeric(Args.Value) Then
      MyValidator.ErrorMessage = "Please enter a number"
      Args.IsValid = False
    Else
    If Not Args.Value Mod 1 = 0 Then
       MyValidator.ErrorMessage = "Please enter an integer"
       Args.IsValid = False
   End If
   If Args.Value < 0 Then
      MyValidator.ErrorMessage = "Please enter a positive integer"
      Args.IsValid = False
   End If
   If Args.Value > 99 Then
     MyValidator.ErrorMessage = "Please enter a positive integer between 0 and 99"
     Args.IsValid = False
   End If
 End If

End Sub

Sub Get_Data (Src As Object, Args As EventArgs)

If Page.IsValid Then
   Output.Text = "You entered '" & MyTextBox.Text & "'"
End If

End Sub


</SCRIPT>

<form Runat="Server">

Enter a positive integer:<br/>
<asp:TextBox id="MyTextBox" Runat="Server"/>
<asp:Button Text="Submit" OnClick="Get_Data" Runat="Server"/>
<asp:CustomValidator id="MyValidator" Runat="Server"
   ControlToValidate="MyTextBox"
   Display="Dynamic"
   SetFocusOnError="True"
   OnServerValidate="Validate_TextBox"/>
<asp:RequiredFieldValidator Runat="Server"
   ControlToValidate="MyTextBox"
   ErrorMessage="Please enter a data value"
   Display="Dynamic"
   SetFocusOnError="True"/>
<asp:Label id="Output" Runat="Server"/>

</form>

در بخش سوم به بررسی سایر کنترل های Validation خواهیم پرداخت .

کنترل های پویا در ASP.NET ( بخش اول )

کنترل های سرویس دهنده معمولا" در زمان طراحی و با توجه به نیاز یک برنامه در صفحات ASP.NET قرار می گیرند . در چنین مواردی ، پیاده کنندگان در زمان طراحی نسبت به تعداد و نوع کنترل های سرویس دهنده مورد نیاز آگاهی کامل دارند . به عبارت دیگر ، دانش لازم برای استفاده از کنترل ها در زمان طراحی وجود دارد . در برخی موارد ممکن است دانش لازم به منظور استفاده از کنترل ها ( نوع و یا تعداد کنترل مورد نیاز ) در زمان طراحی وجود نداشته باشد . این وضعیت در مواردی که اطلاعات صفحه از طریق منابع داده خارجی تامین می گردد ، بسیار مشهود می باشد .
به عنوان نمونه ، فرض کنید می خواهیم دکمه هائی را بر روی یک فرم وب تولید نمائیم که با کلیک بر روی هر از آنها ، کتاب های موجود در بانک اطلاعاتی مرتبط با آن گروه خاص ، نمایش داده شوند . تعداد button مورد نیاز به تعداد گروه های تعریف شده در بانک اطلاعاتی ، بستگی خواهد داشت . با این که در زمان طراحی ممکن است شش گروه کتاب در بانک اطلاعاتی وجود داشته باشد ، ولی ممکن است متناسب با رشد اطلاعات در بانک ، گروه های جدیدی تعریف  و یا برخی گروه ها حذف گردند . در چنین مواردی ، تعداد button ایجاد شده بر روی فرم متاثر از تعداد گروه های تعریف شده در بانک اطلاعاتی است .  بدیهی است تا زمانی که به بانک اطلاعاتی دستیابی نشده باشد نمی توان به اطلاعات مورد نیاز جهت ایجاد buttons دستیابی داشت . به عبارت دیگر ،  هدف ایجاد buttons در زمان اجراء است نه در زمان طراحی . در چنین مواردی ، کنترل ها به صورت پویا و در زمان استقرار صفحه در حافظه ایجاد خواهند شد .

ایجاد کنترل ها با استفاده از اسکریپت
برای ایجاد یک کنترل با استفاده از اسکریپت در ابتدا می بایست یک شی کنترل را به عنوان یک نوع کنترل تعریف نمود . نوع کنترل را می توان یکی از نوع های استاندارد کنترل های سرویس دهنده در نظر گرفت . مثلا"  برای یک ایجاد یک کنترل <asp:label> ، می بایست آن را به عنوان یک نوع label ، برای ایجاد یک کنترل <asp:button> ، آن را به عنوان یک نوع button و برای ایجاد یک کنترل <asp:TextBox> آن را به عنوان یک نوع TextBox تعریف کرد .
کد زیر نحوه تعریف یک کنترل را نشان می دهد :

Dim MyLabel    As  New Label
Dim MyButton   As  New Button
Dim MyTextBox As  New TextBox

کنترل <asp:PlaceHolder>
پس از ایجاد یک کنترل ، به منظور نمایش آن بر روی صفحه می بایست آن را به یکی از مجموعه های Controls اضافه نمود . صفحه، دارای یک مجموعه کنترل با نام page.collection است که تمامی کنترل های موجود در یک صفحه  و سایر کنترل های جدیدی را که در ادامه می توان به اضافه نمود را شامل می شود . معمولا" ترجیح داده می شود که یک ناحیه خاص بر روی صفحه تعریف  و در ادامه کنترل های جدیدی را به آن اضافه نمود . 
کنترل <asp:PlaceHolder> ، ناحیه ای را مشخص می نماید که می توان کنترل های ایجاد شده به صورت پویا را در آن قرار داد . با نسبت دادن یک کنترل به مجموعه کنترل  PlaceHolder ، امکان مشاهده کنترل بر روی صفحه فراهم می گردد .
کد زیر نحوه  ایجاد یک کنترل PlaceHolder را نشان می دهد .

 <asp:PlaceHolder id="id" Runat="Server"/>

کنترل PlaceHolder خود فضائی را بر روی صفحه اشغال نخواهد کرد و صرفا" ناحیه ای را بر روی صفحه به منظور افزودن کنترل های پویا ، رزو می نماید . به کنترل فوق می بایست یک id نسبت داده شود تا امکان دستیابی به آْن از طریق اسکریپت فراهم گردد .

اضافه کردن کنترل به یک PlaceHolder
پس از تعریف یک PlaceHolder ، با استفاده از متد Add می توان کنترل مورد نظر را به آن اضافه نمود . کد زیر نحوه استفاده از  متد Add کنترل PlaceHolder   را نشان می دهد .

 PlaceholderId.Controls.Add(Control)

PlaceHolderId ، شناسه ( id ) کنترل PlaceHolder است که از طریق آن می توان به کنترل دستیابی داشت. Control ، نام کنترلی که می بایست به صورت پویا به صفحه اضافه گردد .  
در مثال زیر‌ ، یک PlaceHolder تعریف و در ادامه یک کنترل label جدید ایجاد و به PlaceHolder  اضافه شده است .

<SCRIPT Runat="Server">

Sub Page_Load

 Dim MyLabel As New Label
 MyPlaceHolder.Controls.Add(MyLabel)

End Sub

</SCRIPT>

<form Runat="Server">

<asp:PlaceHolder id="MyPlaceHolder" Runat="Server"/>

</form>

کنترل label  بر روی صفحه و در مکان مشخص شده توسط PlaceHolder نمایش داده می شود . در ادامه می توان کنترل های دیگری را با استفاده از اسکریپت تولید و به PlaceHolder  اضافه نمود ( در خطوط بعد از کنترل label نمایش داده می شوند ) . در صورت نیاز می توان چندین کنترل PlaceHolder را تعریف و در مکان های مختلف صفحه مستقر نمود تا در ادامه بتوان کنترل های تولید شده توسط اسکریپت را در هر یک از آنها با توجه به ضرورت های موجود ، اضافه نمود .
با توجه به این واقعیت که کنترل های تولید شده توسط اسکریپت به عنوان بخشی از view state صفحه در نظر گرفته نخواهند شد ، می بایست برای ایجاد آنها از روتین Page_load استفاده گردد .

 دستیابی به خصلت های یک کنترل توسط اسکریپت
در مثال قبل ، کنترل label به صورت پیکربندی پیش فرض و بدون هیچگونه تنظمیات خاصی بر روی صفحه نمایش داده می شود . در صورت تمایل می توان خصلت های مرتبط با یک کنترل را به صورت پویا و به کمک اسکریپت مقداردهی نمود .
کد زیر ، بازنویسی مثال قبلی است که در ابتدا خصلت های متعدد کنترل label مقداردهی و در ادامه کنترل فوق به مجموعه کنترل های PlaceHolder  اضافه شده است .

<%@ Import Namespace="System.Drawing" %>

<SCRIPT Runat="Server">

Sub Page_Load

  Dim MyLabel As New Label
  MyLabel.id = "Label01"
  MyLabel.Text = "این کنترل توسط اسکریپت تولید شده است"
  MyLabel.ForeColor = Color.FromName("blue")
  MyLabel.Font.Bold = True
  MyLabel.Font.Size = FontUnit.Parse("14pt")
  MyPlaceHolder.Controls.Add(MyLabel)

End Sub

</SCRIPT>

<form Runat="Server">

<asp:PlaceHolder id="MyPlaceHolder" Runat="Server"/>

</form>

تولید رویدادهای کنترل توسط اسکریپت
در مواردی‌ که کنترل هائی نظیر Button که به کمک آنها می توان اسکریپت های موجود در یک برنامه را فعال نمود به صورت پویا ایجاد می گردند ، می بایست event handler مورد نظر را به منظور فراخوانی برنامه فرعی نیز مشخص نمود . برای ایجاد یک event handler توسط اسکریپت از کد زیر استفاده می گردد . 

 AddHandler Control.Event, AddressOf Subprogram

control ، نام کنترلی است که event handler به آن نسبت داده خواهد شد . Event ، نوع Event handler را مشخص می نماید ( مثلا"  Click ) و  Subprogram ، نام روتینی است که پس از بروز رویداد می بایست فعال گردد .
در مثال زیر ، پس از تعریف یک Buuton و تنظیم خصلت های آن در زمان اجراء ، یک event handler نیز تعریف شده است تا پس از کلیک بر روی دکمه فوق ، روتین مورد نظر فعال (My_Subprogram ) و پاسخگوی رویداد ایجاد شده باشد .

Dim MyButton As New Button
MyButton.id = "Button1"
MyButton.Text = "Click Me"
AddHandler MyButton.Click, AddressOf My_Subprogram
MyPlaceHolder.Controls.Add(MyButton)

در مثال فوق ، یک handler برای رویداد Click به کنترل Button اضافه شده است . My_Subprogram ، روتینی است که پس از بروز رویداد ( کلیک بر روی button ) ، فعال و پاسخگوی رویداد ایجاد شده است .
پس از این که یک Button به صفحه اضافه گردید (  در مکان MyPlaceHolder ) ، عملکرد آن مشابه زمانی است که از یک Button  در زمان طراحی استفاده شده باشد:

<asp:Button id="Button1" Text="Click Me" OnClick="My_Subprogram" Runat="Server"/>

نوع رویداد تولید شده توسط اسکریپت که می توان آن را به کنترل ها اضافه نمود ، همانند event handler استفاده شده به همراه کنترل ها در زمان طراحی است . مثلا" کنترل button قادر به تشخیص دو event handler  با نام OnClick و OnCommand است . بنابراین ، می توان با استفاده از اسکریپت دو رویداد فوق را برای یک button تولید نمود . زمانی که یک رویداد Command توسط اسکریپت تولید می گردد ، می توان خصلت های CommandName و CommandArgument را نیز  برای button  تنظیم نمود . 
در بخش دوم به بررسی سایر عملیات در ارتباط با کنترل های پویا خواهیم پرداخت .

SQL

یک نقص امنیتی در الگوریتم پنهان سازی مورد استفاده در پنهان کردن اسم رمز و Login ID در Microsoft Enterprise Manager for SQL Server 7.0 وجود دارد. این مشکل زمانی رخ می‌دهد که بخواهید SQL Server جدیدی را در Enterprise Manager نصب ‌کنید یا SQL server نصب شده‌ای را ویرایش ‌کنید (منظور زمانی است که برخی مشخصه‌های آن تغییر می‌دهید). اگر SQL Server ، Login name به جای یک Domain ، User name ویندوز بکار رود و checkbox عنوان "Alway prompt for login name and password" ست نشده باشد،‌ LoginID و اسم رمز به صورتی ضعیف پنهان شده و در رجیستری ذخیره می‌شود.

هنگامی که یک (database Administrator)DBA به داخل یک workstation با یک log ، Profile می‌شود LoginID و اسم رمز، هر دو در کلید رجیستری ذخیره می‌شوند، این اطلاعات به عنوان یک فایل با نام NTUSER.DAT (در ویندوز NT) یا USER.DAT (در ویندوز 95 یا ویندوز 98) زمانی که کاربر logoff می‌کند ذخیره می‌شود. فرد متخاصم می‌تواند این فایل را در یک ویرایشگر متن باز کرده و DBA ، loginID و اسم رمز پنهان شده را ببینید. فرد متخاصم می‌تواند اسم رمز و login ID رمز شده پنهان شده را برگردانده و loginID و اسم رمز را بدست آورد. وجود این مشکل امنیتی به متخاصمین محلی و راه دور این اجازه را می‌دهد که اسم رمز Administrator سیستم را بدست آورده و کنترل کاملی روی پایگاه داده روی سرور داشته باشند. این مشکل امنیتی در Microsoft Enterprise Manager for SQL server 7.0 وجود دارد. سیستم پنهان سازی که برای پنهان کردن اسم رمز و SQL server ، LoginID نصب شده بکار می‌رود، قابل کشف است. روش پنهان سازی از جانشینی الفبایی استفاده می‌کند و هرکدام از کاراکترهای Unicode در اسم رمز با دو بایت متناسب با موقعیتشان در رشته، XOR شده‌اند. اگر checkbox با عنوان “Always prompt for login name and password” هنگامی که SQL server نصب می‌شود ست نشده باشد، LoginID و اسم رمز به صورت ضعیفی در رجیستری در قسمت :

--------------------------------------

[HKEY_CURRENT_USERSOFTWAREMicrosoftMSSQLServerSQLEWRegistered Server X]

--------------------------------------

ذخیره می‌شود. اطلاعات ذخیره شده در HKEY_CURRENT_USER زمانی در دسترس است که کاربر در حال حاضر log شده باشد در این حال زمانی که کاربر ویندوز NT به سیستم log می‌شود یک کپی متفاوت از HKEY_URRENT_USER لود می‌شود و هنگامی که کاربر Logoff می‌کند محتویات HKEY_URRENT_USER در فایل NTUSER.DAT یا USER.DAT ذخیره می‌شود و این فایل‌ها را می‌توان در Notepad ویندوز باز کرد و loginID و اسم رمز را براحتی در آن دید اگر DBA از یک workstation دیگری، به سیستم log کند، فایل NTUSER.DAT روی همان workstation که کاربر از طریق آن به سیستم log شده است ذخیره می‌شود.

برای حل این مشکل امنیتی و استفاده مطمئن از SQL server، مایکروسافت پیشنهاد کرده که از Windows Integrated security استفاده شود زیرا در مد Integrated security (امنیت یکپارچه)، اسم رمزها هیچگاه ذخیره نمی‌شوند.

اگر SQL server ، LoginID برای Logging به یک سرور در Enterprise Manager تعیین شده باشد، مایکرسافت پیشنهاد می‌کند که از انتخاب “Always Prompt for Login name and password" برای جلوگیری ذخیره اسم رمزها در رجیستری استفاده کنید.

SQL

شاخصهای یک جدول می‌توانند به شما در دسترسی به یک یا چند سطر از داده‌ها کمک کنند. داشتن یک شاخص خوب برای پرس و جوی (query) شما یکی از بهترین راههای بهبود بخشیدن به عملکرد است. هنگامی که پرس و جوی شما سعی دریافتن تنها تعداد محدودی سطر از یک جدول بزرگ دارد،‌وجود یا عدم وجود یک شاخص خوب و مفید می‌تواند تاثیر چشمگیری در تفاوت عملکرد داشته باشد. هنگام تنظیم پرس و جوهایی که جداول گوناگونی دارند (مانند پیوند)، شاخصها می‌توانند بطور موثری به سرویس‌دهنده SQL دریافتن سطرهای موردنظر از بین جدولها کمک کنند.

بهینه ساز پرس و جوی سرویس دهنده SQL می‌تواند برای اجرای پیوندها از میان 3 استراتژی یکی را انتخاب کند: پیوند حلقه‌ای تودرتو (nested-loop)، پیوند ادغامی (merge) و پیوند hash، در این مقاله به شرح دو استراتژی اول یعنی حلقه‌ای تودرتو و ادغامی می‌پردازیم. در هر روش، جدولهایی را که می‌خواهید پیوند دهید (یا زیر مجموعه‌هایی از آنها که با شرط WHERE محدود کرده‌اید) ورودی‌های پیوند هستند. اگر پرس و جوی شما علاوه بر پیوند، شرط WHERE را نیز شامل شود، سرویس دهنده SQL ممکن است قبل از یافتن سطرهای موردنظر در دومین جدول شرط WHERE را بکار ببرد. بعنوان مثال پرس و جوی 1 از بانک اطلاعاتی Northwind را در نظر بگیرید.

-- Query 1:
SELECT LastName, FirstName, OrderID, OrderDate
FROM Employees e JOIN Orders o
    ON e.EmployeeID = o.EmployeeID

این پیوند تمام سفارشات را از جدول سفارشها باز می‌گرداند و همچنین برای هر یک از آنها، FirstName، LastName کارمندی را که به آن OrderID و OrderDate مربوط می‌شود را نیز باز می‌گرداند.

در پرس و جوی 1 سرویس دهنده SQL تمام سطرها را در جدول کارمندان و سفارشات امتحان می‌کند و ورودی‌های پیوند تمام سطرهای جدولها هستند. بهرحال، طبق آنچه که پرس و جوی 2 نشان می‌دهد، اگر شما عبارت SELECT را با دو شرط WHERE تعریف کنید، ورودیهای پیوند دیگر تمام سطرهای جدولها نیستند.

-- Query 2:
SELECT LastName, FirstName, OrderID, OrderDate
FROM Employees e JOIN Orders o
    ON e.EmployeeID = o.EmployeeID
WHERE OrderDate < '1996-12-01' AND LastName < 'D'

ورودیهای پیوند در پرس و جوی 2، بسیار کوچکتر از پرس و جوی 1 هستند. به جای پیوند 9 سطر از جدول کارمندان با 830 سطر از جدول سفارشات، سرویس دهنده SQL باید تنها 2 سطر از جدول کارمندان را با 121 سطر از جدول سفارشات پیوند دهد. بهینه ساز پرس و جو با وجود تعداد محدودی از سطرهای ورودی غالباً استراتژی پیوند متفاوتی را در مقایسه با زمانی که ورودیهای پیوند بیشتر هستند برمی‌گزیند و همچنین ممکن است جدولها را به سبک متفاوتی پیوند دهد. به همان اندازه که تصمیمات استراتژی بهینه ساز مهم هستند اندازه جدولها نیز حائز اهمیت است.

حلقه‌های تودرتو

حتی اگر پرس وجوی شما بیش از 2 جدول را پیوند دهد، سرویس دهنده SQL عمل پیوند را از طریق پیوند تنها دو ورودی در یک زمان اجرا می‌کند و هر پیوند در یک پرس و جو ممکن است از استراتژی پیوند متفاوتی استفاده کند. آسانترین نوع پیوند – و نوعی از پیوند که اکثر افراد هنگام عملیات پیوند بدان فکر می‌کنند – پیوند حلقه تودرتوست  می‌توانید تصور کنید که سرویس دهنده SQL روی دو ورودی عمل می‌کند حتی اگر آنها آرایه‌هایی در یک زبان پیشرفته مانند C یا Basic باشند. سرویس دهنده SQL هر سطر یک ورودی را با تمام سطرهای ورودی دیگر مقایسه می‌کند تا تطابق بین سطرها را بیابد.

پرس و جوی 1 سعی دریافتن سطرهایی دارد که با ستون EmployeeID تطبیق داشته باشد. بنابراین با استراتژی پیوند حلقه تودرتو، سرویس دهنده SQL باید تمام مقادیر EmployeeID در یک جدول را با تمام مقادیر EmployeeID در جدول دیگر مقایسه کند.

بدترین قسمت سناریو برای یک پیوند حلقه تودرتو زمانی است که هیچ شاخصی نتواند به سرویس دهنده SQL دریافتن سطرهای منطبق در بین ورودیها و همچنین یافتن سطرهایی که در هر شرط WHERE صدق می‌کند، کمک نماید. در ین حالت، ورودیها کل سطرهای جدولها هستند. بهینه ساز پرس و جو جدولی را بعنوان جدول خارجی انتخاب می‌کند و در ابتدا به سطرهای آن دستیابی می‌یابد. بیایید فرض کنیم که جدول خارجی دارای P1 صفحه و R1 سطر باشد. دومین جدول که جدول داخلی است P2 صفحه دارد. سرویس دهنده SQL باید تمام صفحات را از جدول خارجی بخواند؛ و برای هر سطر تعریف شده در هر صفحه باید تمام صفحات را از جدول داخلی بخواند. برای یافتن تعداد صفحاتی که سرویس دهنده SQL برای خواندن و ارائه نتیجه نیاز دارد، می‌توانید از فرمول زیر استفاده کنید:

P1 + R1 * P2

حتی اگر جدولها نسبتاً کوچک باشند، عدد حاصله از صفحات خوانده شده به سرعت بزرگ می‌شود. در مورد یک جدول خارجی با تنها 200 صفحه و 4000 سطر (برای مثال 20 سطر برای هر صفحه) و یک جدول داخلی با 100 صفحه، نتیجه رقمی کاملاً بزرگ است. جدولهایی با 100 یا 200 صفحه جدولهایی نیستند که بطور غیرمعمول بزرگ باشند، اما برای پردازش پیوند در صورتی که جدولها شاخصهای مفیدی نداشته باشند، سرویس دهنده SQL نیاز به دستیابی به بیش از 400,000 صفحه خواهد داشت.

شاخصها می‌توانند در بهبود عملکرد یک پیوند حلقه تودرتو به طرق مختلف نقش داشته باشند. بزرگترین حسن این شاخصها اغلب زمانی است که شما یک شاخص کلاستری روی ستون پیوند یکی از جدولها داشته باشید. وجود یک شاخص کلاستری روی ستون پیوند غالباً مشخص می‌کند که سرویس دهنده SQL چه جدولی را بعنوان جدول داخلی انتخاب می‌کند. اگر جدول داخلی دارای شاخص کلاستری باشد، سرویس دهنده SQL نیاز به جستجو در میان کل سطرهای آن جدول را ندارد. شاخص کلاستری، سرویس دهنده SQL را مستقیماً به سوی سطرهایی در جدول داخلی هدایت می‌کند که دارای مقدار ستون پیوند بوده که سطرهای جاری در جدول خارجی را تطبیق می‌دهد. بنابراین در آن فرمول، به جای عبارت R1 ´ P2 که نشان می‌دهد سرویس دهنده SQL به تمام P2 صفحه دستیابی پیدا می‌کند، می‌توانید P2 را با دستیابی 2 یا 3 صفحه‌ای جایگزین کنید بسته به اینکه شاخص کلاستری چند Level دارد. بنابراین در مورد مثالی با 200 صفحه و 400 سطر در جدول خارجی و 100 صفحه در جدول داخلی نتیجه 3*4000+200 یا 200،12 صفحه خوانده شده است – یک پیشرفت بزرگ بالای 400,000 صفحه می‌باشد.

هنوز هم آن 4000 سطر در محاسبه نتیجه را بزرگتر از حد انتظار خواهد کرد. در این حالت، تمامی 4000 سطر در جدول خارجی بخشی از نتیجه هستند که موجب 4000 بار رجوع به جدول داخلی می‌شود. یک راه دیگر برای کاهش تعداد صفحات بدست آمده کاهش اندازه ورودیهای خارجی است. علاوه بر کنترل شاخص کلاستری روی ستون پیوند، ابتدا بهینه ساز سعی می‌کند جدولها را با ورودیهای کوچکتر پیوند دهد. در پرس و جوی 1، جدول کارمندان دارای یک شاخص کلاستری روی ستون پیوند یعنی EmployeeID هستند اما این جدول نیز بطور نمایشی کوچکتر از جدول سفارشات است. جدول کارمندان تنها 9 سطر دارد و جدول سفارشات 830 سطر. در پرس و جوی 1، اگر بهینه ساز یک پیوند حلقه تودرتو را انتخاب کند، از جدول کوچکتر کارمندان به عنوان ورودی خارجی استفاده می‌کند بگونه‌ای که تنها 9 بار به جدول سفارشات رجوع خواهد داشت.

اگر شما دارای شرط WHERE باشید که جدول خارجی را شامل می‌شود، تعداد سطرهای تعریف شده پایین می‌آید و سرویس دهنده SQL کمتر نیاز به مراجعه به جدول داخلی را خواهد داشت. اگر پرس و جوی 1 را طوری تغییر دهید که شامل یک شرط WHERE در جدول سفارشات باشد، همانگونه که در پرس و جوی 3 نشان داده شده، طرح پرس و جو تغییر می‌کند.

-- Query 3:
SELECT LastName, FirstName, OrderID, OrderDate
FROM Employees e JOIN Orders o
    ON e.EmployeeID = o.EmployeeID
WHERE OrderDate < '1996-12-01'

حالا، تنها 121 سطر در جدول سفارشات بخشی از نتیجه هستند، آن جدول کوچکتر که با شاخص کلاستری روی ستون پیوند جدول کارمندان ترکیب شده این مفهوم را می‌رساند که بهینه ساز حالا جدول کارمندان را به عنوان جدول داخلی انتخاب می‌کند. سرویس دهنده SQL از پیوند حلقه تودرتو استفاده خواهد کرد چرا که شاخص کلاستری باعث می‌شود سرویس دهنده SQL سریعاً سطرهای منطبق شده را در جدول داخلی بیابد.

FIGURE 1: Query plan for Query 3
|..Nested Loops(Inner Join, OUTER REFERENCES:([o].[EmployeeID]))
    |..Clustered Index Scan(OBJECT:([northwind].[dbo].[Orders].[PK_Orders]
     AS [o]),
         WHERE:([o].[OrderDate] < 'Dec 1 1996 12:00AM'))
    |..Clusterd Index
Seek(OBJECT:([northwind].[dbo].[Employees].[PK_Employees] AS [e]),
         SEEK:([e].[EmployeeID]=[o].[EmployeeID]) ORDERED FORWARD)

شکل 1 طرح پرس و جو را در مورد پرس و جوی 3 نشان می‌دهد. اولین خط این طرح نوع پیوند (حلقه تودرتو) را نشان می‌دهد و مشخص می‌کند که جدول خارجی ستون EmployeeID را ارجاع خواهد داد.

اسکن شاخص کلاستری در جدول خارجی شبیه اسکن یک جدول است زیرا هیچیک از شاخصهای موجود نمی‌تواند دستیابی به جدول خارجی را سرعت ببخشد. شرط WHERE در ستون OrdrerDate تعداد سطرهای برگردانده شده و تعداد دفعاتی که سرویس دهنده SQL باید به جدول داخلی دستیابی داشته باشد تا تعیین کند کدامیک مقدار
OrderDate قابل قبولی دارند. در نهایت، طرح پرس و جو نشان می‌دهد که سرویس دهنده SQL از یک شاخص کلاستری برای جستجوی جدول داخلی استفاده می‌کند زیرا این شاخص روی ستونی است که سرویس دهنده SQL برای یافتن سطرهای منطبق استفاده می‌کند.

چنانچه قبلاً ذکر شد شاخص در ستون OrderDate چیز خوبی است اما عملکرد پرس و جو را تقریباً به یک شاخص کلاستری روی ستون پیوند بهبود نخواهد بخشید. یک شاخص مفید در پارامتر جستجو در جدول خارجی بدین معناست که سرویس دهنده SQL نباید به تمام صفحات جدول خارجی رجوع نماید، بنابراین،‌ مقدار P1 کاهش می‌یابد. باتوجه به اینکه مقدار P1 نسبت به مقدار دومین عبارت،‌ P2 R1، کوچکتر است، بنابراین کاهش مقدار P1 فقط موجب بهبودی کمتر عملکرد می‌گردد. شاخص جدول خارجی تعداد دفعاتی که سرویس دهنده SQL باید به جدول داخلی رجوع کند را کاهش نمی‌دهد زیرا سرویس دهنده SQL هنوز باید بازای هر سطر تعریف شده در جدول خارجی به جدول داخلی رجوع کند. شما می‌توانید انتخاب بهینه‌ساز از پیوند حلقه تودرتو را اینگونه تعمیم دهید: در صورتی که یکی از ورودیهای پیوند بسیار کوچکتر از دیگری و ورودی بزرگتر دارای یک شاخص کلاستری روی ستون پیوند باشد، بهینه ساز اغلب پیوند حلقه تودرتو را برمی‌گزیند.

ادغام

در پیوند حلقه تودرتو، شاخص ستون پیوند در مورد جدول خارجی بی‌فایده است. بهرحال، زمانی که شما پرس و جوها و جداول را تنظیم می‌کنید، ممکن است همیشه ندانید که کدام جدول داخلی و کدام خارجی است، بنابراین باید در هر دو جدول ورودی شاخصهای کلاستری را روی ستونهای پیوند ایجاد کرد. زمانی که هر دو ورودیهای پیوند روی ستون پیوند مرتب سازی می‌شوند، سرویس دهنده SQL می‌تواند از پیوند ادغامی استفاده کند، درست مانند موردی که هر دو جدول دارای شاخصهای کلاستری روی ستون پیوند باشند.پیوند ادغامی را می‌توان همچون ترکیب دویست مرتب سازی شده از مقادیر تصور کرد. فرض کنید دارای دو سری از اطلاعات پیمانکاری هستید. یک سری شامل قراردادهای مهم می‌باشد که هر پیمانکاری آن را امضا کرده است و دومین سری توصیف هریک از پروژه‌هایی است که پیمانکار بر روی آن کار می‌کند بنابراین، شما اساساً نیاز به یک پل ارتباطی میان این دو سری اطلاعات دارید.پرس و جوی 1 را در نظر بگیرید: اگر جدول کارمندان و جدول سفارشات در ستون EmployeeID شاخصهای کلاستری داشته باشند، سرویس دهنده SQL می‌تواند پیوند ادغامی را اجرا کند. شبه کد مربوطه در مورد اجرای ادغامی سرویس دهنده SQL چیزی شبیه این عبارات خواهد بود:

GET one Orders row and one Employees row
DO (until one input is empty);
      IF EmployeeID values are equal
           Return values from both rows
           GET next Orders row
      ELSE IF Orders.EmployeeID <> Employees.EmployeeID
           GET next Employees row
      ELSE GET next Orders row

بهینه ساز پرس و جو معمولاً استراتژی پیوند ادغامی را زمانی انتخاب می کند که هر دو ورودیها قبلاً در ستون پیوند مرتب شده باشند. اگر هر دو ورودی قبلاً مرتب شده باشند، در صورتی که پیوند یک به چند باشد استفاده از I/O کمتری برای پردازش پیوند ادغامی ضروریست. پیوند ادغامی چند به چند (M:N) به جای کنار گذاشتن سطرها که معمولاً انجام می‌دهد، آنها را در یک جدول موقتی ذخیره می‌کند. اگر داده‌ها شامل مقادیر تکراری از هر دو ورودی باشند، هنگامی که سرویس دهنده SQL هر مقدار تکراری را از اولین ورودی پردازش می‌کند، دومین ورودی باید به ابتدای مقادیر تکراری در جدول موقت بازگردد. بهرحال، در اکثر موارد، سرویس دهنده SQL از پیوند ادغامی استفاده نخواهد کرد مگر اینکه حداقل یکی از ستونهای پیوند Unique باشد.در اینجا مثالی از پیوند دو جدول یکی با شاخص و دیگری بدون شاخص Unique آورده شده است.

 

LISTING 1: Joins Two Tables With and Without Unique Index

-- Copy the two tables
SELECT * INTO o1 FROM orders
SELECT * INTO od1 FROM [order details]

-- Create the indexes.
CREATE CLUSTERED INDEX orders_index
ON o1(orderID)
CREATE CLUSTERED INDEX OD_index
ON od1(orderID)

-- Look at the query plan for the query.
SELECT * FROM o1 JOIN od1
ON o1.orderID = od1.orderID

-- Now recreate the clustered index on o1 as unique.
CREATE UNIQUE CLUSTERED INDEX orders_index ON o1(orderID)
WITH DROP_EXISTING

-- Now Look at the query plan for the query.
SELECT * FROM o1 JOIN od1 ON o1.orderID = od1.orderID

LISTING 2: Modified Listing 1

SELECT * INTO o2 FROM orders

SELECT * INTO od2 FROM [order details]

CREATE UNIQUE CLUSTERED INDEX orders_index ON o2(orderID)
CREATE INDEX OD_index ON od2(orderID)

-- Check the query plan to see the sort operation before
-- the merge join:
SELECT * FROM o2 JOIN od2
ON o2.orderID = od2.orderID

 

لیست 1 کپی‌هایی از جدول سفارشات و جدول جزئیات سفارشات در بانک اطلاعاتی Northwind ایجاد می‌کند و یک شاخص کلاستری در OrderID هر دو جدول می‌سازد. زمانی که شما ابتداً این جدولها را پیوند می‌دهید و طرح پرس و جو را به نمایش می‌گذارید، خواهید دید که سرویس دهنده SQL پیوند حلقه تودرتو را انتخاب می‌کند. اگرچه ستون OrderID در جدول سفارشات Unique است، اما در صورتی که Unique بودن را در تعریف شاخص مشخص نکنید، بهینه ساز متوجه نخواهد شد که مقادیر کلیدی Unique هستند. بنابراین هنگامی که مجدداً شاخص کلاستری را در جدول سفارشات می‌سازید و مشخص کنید که آن شاخص باید Unique باشد، طرح پرس و جوی اصلاح شده نشان می‌دهد که سرویس دهنده SQL از یک پیوند ادغامی استفاده می‌کند. در برخی از حالتها، بهینه ساز سرویس دهنده SQL ممکن است به دلیل به صرفه بودن تصمیم بگیرد یکی از ورودیها را قبل از پیوند مرتب کند و بعد پیوند ادغامی را اجرا نماید. اگر لیست 1 را کمی تغییر دهید به گونه‌ای که شاخص اولیه که در جدول جزئیات سفارشات ساخته می‌شود کلاستری نباشد، طبق آنچه که لیست 2 نمایش می‌دهد، طرح پرس و جو عمل مرتب سازی را قبل از پیوند ادغامی نشان می‌دهد.

جدولهایتان را بشناسید

معمولاً، بهینه ساز پرس و جو تعیین می‌کند که سرویس دهنده SQL چه نوع پیوندی را استفاده خواهد کرد. شما می‌توانید پرس و جوی پیوند خود را نوشته و انتخاب استراتژی را به عهده SQL بگذارید. بهرحال، دانستن نحوه اجرای پیوندها در سرویس دهنده SQL می‌تواند انتخاب شما در مورد شاخصهای مفیدتر کمک کند. بهینه ساز معمولاً در صورتی که یکی از ورودیهای پیوند در مقایسه با ورودی دیگری کوچکتر و ورودی بزرگتر دارای یک شاخص کلاستری روی ستون پیوند باشد، از پیوند حلقه تودرتو استفاده می‌کند. اگر هر دو ورودی در ستون پیوند مرتب شده باشند و بخصوص یکی از ورودیها دارای شاخص کلاستری unique باشد نوع پیوند به احتمال زیاد ادغامی خواهد بود.

هر دو پیوند ادغامی و حلقه تودرتو نیاز به شاخصهای مناسب در جدولها دارند. بهرحال، اگر برنامه کاربردی شما باعث شود که کاربرها پرس و جوهای ویژه بسازند، ممکن است در ابتدا ندانید که بهترین ستون برای شاخصها کدام است. سومین نوع پیوند، پیوند hash است که باعث می‌شود سرویس دهنده SQL به یک عملکرد پیوند بسیار خوب دست بیابد حتی زمانی که جداول شما از شاخصهای مفیدی برخوردار نباشند.


SQL

زبان SQL تنها زبان استاندارد و جامع پیاده‌سازی، مدیریت، نگهداری و کار با بانکهای اطلاعاتی می‌باشد که تقریباً توسط تمام بانکهای اطلاعاتی کوچک و بزرگ مانند Access، SQL Server، Oracle و DB2 پشتیبانی می‌شود. طراحان و افرادی که بنوعی با بانکهای اطلاعاتی سروکار دارند و همچنین برنامه نویسانی که از این بانکها استفاده می‌کنند هرکدام باید تا اندازه‌‌ای با این زبان آشنایی داشته باشند. این مقاله که در سه قسمت تهیه شده است می‌کوشد تا مفاهیم زبان SQL را در قالب یک مثال کاربردی بیان کند. هرچند که مفاهیم بکار رفته در این مقاله در تمامی بانکهای اطلاعاتی قابل پیاده‌سازی می‌باشند ولی مثالهای ارائه شده در 2000 SQL Server مورد تست قرار گرفته‌اند.

بانک اطلاعاتی که در این مقاله بعنوان مثال مورد استفاده قرار گرفته است بانک اطلاعاتی یک آموزشگاه می‌باشد که شامل دو جدول بنامهای teachers و students می‌باشد. جدول اول اطلاعات اساتید و جدول دوم اطلاعات دانشجویان را در خود نگه می‌دارد. جدول اول دارای چهار فیلد زیر می‌باشد: name یا نام از نوع text، family یا فامیل از نوع text، age یا سن از نوع عدد، salary یا حقوق از نوع عدد.

جدول دانشجویان نیز شامل چهار فیلد می‌باشد، سه فیلد اول آن مشابه سه فیلد اول جدول اساتید می‌باشد و فیلد چهارم آن عبارتست از GPA یا معدل که یک فیلد عددی است.

زبان SQL دارای دستورات متنوع و نسبتاً زیادی می‌باشد. به این دستورات Clause نیز گفته می‌شود. در این مقاله و قسمتهای بعدی آن تعدادی از مهمترین Clauseهای زبان SQL مورد بررسی قرار می‌گیرند.

1 – دستورهای SELECT و FROM :

هدف نهایی از دادن انبوه اطلاعات به کامپیوتر، جستجو و یافتن اطلاعات مفید می‌باشد. به این عمل یعنی جستجوی اطلاعات در بانک اطلاعاتی Query نیز گفته می‌شود. اکثر دستورات زبان SQL نیز در همین راستا مورد استفاده قرار می‌گیرند. در این بین مهمترین و پرکاربردترین دستور را می‌توان دستور SELECT قلمداد کرد.

این دستور جهت انتخاب یک یا چند فیلد از یک یا چند جدول مختلف مورد استفاده قرار می‌گیرد، فیلدهای انتخاب شده پس از اجرای query روی صفحه نمایش داده خواهند شد.

بعنوان مثال اگر در بانک اطلاعاتی فرضی خودمان بخواهیم اسم و فامیل تمام دانشجویان را مشاهده کنیم باید برنامه‌ای به شکل زیر بنویسیم:

SELECT name, family
FROM students

در این برنامه که به زبان SQL استاندارد نوشته شده است از دو دستور SELECT و FROM استفاده شده است. دستور SELECT مشخص می‌کند که چه فیلدهایی از جدول باید نمایش داده شوند و دستور FROM نیز مشخص کننده جدولی است که قرار است اطلاعات از داخل آن استخراج شوند. حال اگر بخواهیم نام و فامیل تمام اساتید را ببینیم برنامه بالا را باید بصورت زیر تغییر دهیم:

SELECT name, family
FROM teachers

همان طوری که از مثال‌های بالا نیز مشخص است جلوی دستور SELECT نام فیلدهایی نوشته می‌شوند که قرار است نمایش داده شوند و بعنوان جداکننده نیز باید از کاراکتر کاما استفاده کرد. در صورتی که بخواهیم تمام فیلدهای یک جدول را ببینیم می‌توانیم بجای نوشتن اسم تمام فیلدها فقط از یک کاراکتر ستاره استفاده کنیم. کاراکتر ستاره بمعنی تمام فیلدهای یک جدول می‌باشد. مثلاً دو دستور زیر با هم معادلند:

SELECT *
SELECT name, family, age, gpa

2 – دستور WHERE :

دستور SELECT همان طوری که گفته شد جهت انتخاب و نمایش تعدادی از فیلدهای جداول مورد استفاده قرار می‌گیرد. در این حالت تمام رکوردها نمایش داده خواهند شد، ولی در بیشتر موارد هدف از نوشتن Query نمایش رکوردهایی است که دارای شرایط ویژه‌ای می‌‌باشند مثلاً نمایش مشخصات اساتیدی که بیش از پنجاه سال سن دارند. دستور WHERE برای گذاشتن یک یا چند شرط به دستور SELECT مورد استفاده قرار می‌گیرد. با اضافه کردن شرط به دستور SELECT تعداد رکوردهای خروجی (پاسخ) معمولاً محدودتر می‌شود. بعنوان مثال اگر بخواهیم مشخصات اساتیدی که بیش از چهل سال سن دارند را ببینیم باید برنامه‌ای بصورت زیر بنویسیم:

SELECT *
FROM teachers
WHERE age > 40

در این برنامه شرط age > 40 با استفاده از دستور WHERE به Query اضافه شده و باعث شده است تا فقط مشخصات اساتیدی نمایش داده شوند که در این شرط صدق می‌کنند یعنی بیش از چهل سال سن دارند.

حال اگر بخواهیم مشخصات دانشجویانی را که نام آنها علی می‌باشد و سن آنها نیز کمتر از پانزده سال است را ببینیم باید Query زیر را اجرا کنیم:

SELECT *
FROM students
WHERE age < 15 AND name = 'ali'

در مثال بالا دو مطلب جدید وجود دارد نخست آنکه در زبان SQL رشته متنی را باید داخل کوتیشن (‘) قرارداد. بنابراین برای معرفی کلمه‌ای بنام علی باید آنرا بصورت ‘ali’ نوشت، زیرا در این حالت این کلمه یک ثابت رشته‌ای (متنی) بحساب می‌آید. نکته دیگر آنکه می‌توان شرطهای مختلف را توسط AND، OR و NOT با همدیگر ادغام کرده و شرطهای پیچیده‌تری را بدست آورد. AND، OR و NOT هر سه از کلمات کلیدی زبان SQL می‌باشند. بعنوان یک مثال دیگر فرض کنید می‌خواهیم مشخصات تمام دانشجویانی را که نام آنها، علی یا رضا نباشند را پیدا کنیم، برنامه‌ای که این Query را انجام می‌دهد بصورت زیر می‌باشد:

SELECT *
FROM students
WHERE name NOT IN ('ali', 'reza')

در صورتی که NOT را از برنامه بالا حذف کنیم مشخصات تمام دانشجویانی که نام آنها علی یا رضا می‌باشند نمایش داده خواهد شد.

در این برنامه نیز یک کلمه کلیدی جدید وجود دارد: IN که برای تست عضویت در یک مجموعه بکار می‌رود. مجموعه‌ای که بادستور IN بکار می‌رود می‌تواند دهها عضو داشته باشد و نوع اعضا نیز می‌تواند رشته‌ای، عددی یا ... باشد. البته واضح است که تمام اعضا باید هم نوع باشند.

حال بعنوان یک مثال پیشرفته‌تر می‌خواهیم مشخصات دانشجویانی را ببینیم که اسم فامیل آنها به ‘ زاده’ ختم می‌شود مانند علیزاده، محمد زاده و ... برای این منظور باید Query زیر را نوشته و اجرا کنیم:

SELECT *
FROM family LIKE '% zadeh'

کاربرانی که با Access کار می‌کنند باید سطر آخر را به صورت زیر تغییر دهند:

WHERE family LIKE '*zadeh'

در این مثال از Wildcardها استفاده شده است که قبلاً با مفهوم آن در DOS و Windows یا حتی Unix آشنا شده‌ایم (ls a*) . در Wildcard ،SQL هایی به شرح زیر وجود دارند:

% (در Access از * استفاده کنید): این Wild card نشانگر هر تعدادی از کاراکترها (هر کاراکتری) می‌باشد.

- (در Access از ? استفاده کنید): این Wildcard نشانگر یک کاراکتر می‌باشد که این کاراکتر می‌تواند هر کدام از کاراکترهای مجاز کامپیوتر باشد.

جهت جستجو کردن فیلدهایی که دارای یک الگوی (Pattern) خاصی هستند باید از دستور LIKE و Wildcardها استفاده کرد. در مثال زیر نام و سن تمام اساتیدی که اسم آنها با Pe شروع می‌شود، نمایش داده خواهد شد.

SELECT name, age
FROM teachers
WHERE name LIKE 'Pe%'

بنابراین مشخصات افرادی که نام آنها مثلاً پدرام یا پیمان باشد در خروجی لیست خواهد شد.

3 – دستور ORDERBY :

دستور ORDERBY جهت Sort کردن رکوردهای نمایش داده شده مورد استفاده قرار می‌گیرد. با این دستور می‌توان مشخص کرد که رکوردهایی که قرار است نمایش داده شوند برحسب کدام فیلد باید مرتب شوند. بعنوان مثال برای مشاهده کردن مشخصات اساتیدی که سن آنها بیشتر از 29 سال می‌باشد و در ضمن لیست خروجی بترتیب اسم فامیل نیز مرتب شده باشد باید Query زیر را اجرا کرد.

SELECT *
FROM teachers
ORDERBY family

در این حالت افراد بترتیب اسم فامیل خود لیست خواهند شد. (از A تا Z) در صورتی که بخواهیم ترتیب Sort شدن برعکس شود (از Z تا A) می‌توان پس از دستور ORDERBY از کلمه کلیدی DESC استفاده کرد، مانند مثال زیر

SELECT *
FROM teachers
ORDERBY DESC name

در این مثال Sort شدن بترتیب اسم و نه بترتیب فامیل انجام می‌گیرد.

برای دستور ORDERBY می‌توان چند فیلد تعریف کرد، در این صورت این دستور عمل Sort کردن را با در نظرگرفتن اولین فیلد انجام خواهد داد در صورتی که چند رکورد دارای مقدار مشابهی در این فیلد باشند ملاک مرتب سازی آنها فیلد دومی خواهد بود که در دستور ORDERBY ذکر شده است، در صورتی که این فیلد نیز دارای مقادیر مشابهی باشد ملاک تصمیم‌ گیری فیلد سوم خواهد بود والی آخر.

بعنوان مثال در Query زیر نام اساتیدی که بیش از 30 سال دارند برحسب فامیل آنها مرتب می‌شود در صورتی که چند استاد دارای اسم فامیل یکسانی باشند ملاک مرتب شدن، اسم کوچک آنها خواهد بود.

SELECT *
FROM teachers
WHERE age > 30
ORDERBY family, name

4 – استفاده از توابع:

در دستور SELECT علاوه بر تعریف فیلدها می‌توان از عبارتهای ریاضی و یا توابع استاندارد SQL نیز استفاده کرد.

بعنوان مثال اگر مالیات بردرآمد پنج درصد باشد Query زیر نام اساتید و مالیاتی را که هر کدام می‌پردازند را مشخص می‌کند.

SELECT family, name, salary*5/100
FROM teachers

علاوه بر عبارتهای ریاضی می‌توان از توابع استاندارد SQL نیز استفاده کرد، تعدادی از این توابع عبارتند از:

تابع COUNT : تعداد فیلدها را برمی‌گرداند.

تابع SUM : مجموع یک فیلد عددی را برمی‌گرداند.

تابع AVG : میانگین یک فیلد عددی را برمی‌گرداند.

تابع MIN : مینیمم یک فیلد عددی را برمی‌گرداند.

تابع MAX : ماکزیمم یک فیلد عددی را برمی‌گرداند.

بعنوان مثال اگر بخواهیم تعداد اساتید و مجموع حقوقهایی را که به آنها پرداخت شده است را ببینیم می‌توانیم از Query زیر استفاده بکنیم.

SELECT COUNT (name), SUM (Salary)
FROM teachers

5 – Queryهای چند جدولی:

تمام Queryهایی که تاکنون مشاهده کردید، Queryهای تک جدولی بودند بدین معنی که در هر Query فقط اطلاعات یک جدول مورد جستجو قرار می‌گرفت. در SQL امکان نوشتن Queryهای چند جدولی نیز وجود دارد. در این حالت اطلاعات چند جدول بطور همزمان مورد جستجو قرار می‌گیرد و حتی امکان مقایسه فیلدهایی از یک جدول با فیلدهایی از جدول دیگر نیز وجود دارد. اگر در بین جداولی که در Query شرکت داده می‌شوند فیلدهای هم نام وجود داشته باشد باید نام آن فیلدها را Fully qualified کرد بدین معنی که ابتدا اسم جدول و سپس اسم فیلد را ذکر کرد. بین اسم جدول و اسم فیلد نیز باید از یک کاراکتر نقطه (‘.’) استفاده کرد.

بعنوان مثال اگر بخواهیم لیست اساتید و دانشجویانی که دارای ارتباط فامیلی هستند را ببینیم می‌توانیم از Query زیر استفاده بکنیم:

SELECT *
FROM students, teachers
WHERE students.family = teachers. Family

و یا اگر بخواهیم لیست اساتیدی را مشاهده کنیم که سن آنها از سن برخی از دانشجویان کمتر است، می‌توانیم Query زیر را اجرا کنیم:

SELECT teachers.family, teachers.name
FROM students, teachers
WHERE teachers.age < students.age

6 – کلام آخر:

کلام آخر اینکه زبان SQL برخلاف زبانهایی مانند C یا C++ یک زبان Case Sensitive نیست بدین معنی که به بزرگ یا کوچک بودن حروف حساس نمی‌باشد. بنابراین به راحتی می‌‌توان دستورات و کلمات کلیدی آنرا در هر برنامه‌ای با حروف کوچک یا بزرگ تایپ کرد.

HTML

یک فایل اچتمل متنی از نوع text است که از عناصر یا element ها تشکیل میشود و برای ایجاد عناصر از تگ ها یا tags استفاده میشود. در این فصل با عناصر و تگ ها اچتمل آشنا خواهید شد.

تگ های اچتمل (HTML Tags)
  • با کمک تگ های اچتمل عناصر و یا Elements ساخته میشوند.
  • در زبان اچتمل حدود 80 عنصر تعریف شده است.
  • تگ های اچتمل بوسیله دو نویسه (char) > و < ساخته میشوند.
  • تگ های اچتمل معمولا بصورت زوج ظاهر میشوند، مانند <b>test</b>
  • تگ اول در یک زوج تگ مثلا <b> تگ شروع و تگ دوم مثلا <b/> تگ پایانی نام دارد.
  • متن بین تگ اول و تگ دوم در یک زوج تگ محتوای عنصر یا element content نامیده میشود، مثلا "test"
  • تگ های اچتمل را میتوانید بوسیله حروف لاتین کوچک (lower case) و یا بزرگ (upper case) بنویسید و case sensitive نیستند. برای مثال دو تگ <b> و <B> معادل هم هستند ولی شدیدا توصیه میشود که به خاطر سازگاری با XHTML از حروف کوچک استفاده شود.

عناصر اچتمل (HTML Elements)

مثال بخش مقدمه را در نظر بگیرید:

<html>
<head>
<title>Title of page</title>
</head>
<body>
This is my first html page. <b>This text is bold</b>
</body>
</html>

*** نمونه ای از یک عنصر اچتمل:

<b>This text is bold</b>
عنصر اچتمل بالا با تگ <b> شروع شده و با تگ <b/> پایان می یابد. محتوای این عنصر عبارت "This text is bold" است. لازم به ذکر است که کاربرد تگ <b> نمایش توپر یا bold متون است.

*** مثال دوم یک عنصر اچتمل (معلوم الحال) :

<body>
This is my first homepage. <b>This text is bold</b>
</body>
عنصر اچتمل بالا با تگ <body> شروع شده و با تگ <body/> پایان می یابد. همانطور که میبینید گاهی یک عنصر حاوی یک یا چند تگ دیگر میباشد.وظیفه تگ <body> تعیین بدنه اصلی یا body یک متن اچتمل است.لازم به یادآوری است که تنها اطلاعات بخش <body> یک فایل اچتمل در صفحه مرورگر نمایش داده خواهد شد.
شناسه های یک تگ (Tag Attributes)

تگ ها میتوانند حاوی اطلاعات اضافی دیگر باشند، به این اطلاعات شناسه یا Attribute میگویند و وظیفه آنها بیان دیگر اطلاعات یک عنصر یا Element میباشد. مثلا در مورد تگ <body> شناسه ای به نام bgcolor وجود دارد که رنگ زمینه متن (background) را تعیین میکند برای نمونه اگر میخواهید که رنگ زمینه صفحه اچتملتان سیاه باشد کافی است که به شکل زیر عمل کنید :

<body bgcolor="black">

در مثال زیر تگ <body> دارای چهار شناسه مختلف با نامهای width، height ، align و border و مقادیر center، 60، 100 و 0 میباشد.
<table border="0" width="100" height="60" align="center" >
......
</table>

شناسه ها به صورت کلی "مقدار=نام" یا "name=value" نوشته میشوند و همیشه به تگ شروع یک عنصر یا Element اضافه میشوند و نهایتا اگر در یک عنصر یا Element شناسه ها قید نشوند از مقادیر قراردادی یا default آنها استفاده خواهد شد مثلا در تگ body اگر شناسه bgcolor نوشته نشود از رنگ سفید برای زمینه صفحه استفاده خواهد شد.
مقدار یک شناسه را میتوانید داخل نویسه های " و یا ' بنویسید و اختیار دست شما است فقط در مواردی که مقدار یک شناسه شامل نویسه " هم میشود باید از نویسه ' استفاده شود.