کنترل های 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:RequiredFieldValidator>
متداولترین نوع ارزیابی داده ورودی ، بررسی آن به منظور اطمینان از درج داده توسط کاربر است . کنترل <asp:RequiredFieldValidator> ، مسئولیت بررسی داده ورودی در یک Textbox را برعهده گرفته و در صورت عدم درج داده توسط کاربر ، یک پیام خطاء را نمایش خواهد داد . در چنین مواردی ، روتین هائی که می بایست پس از کلیک بر روی دکمه موجود از داده درج شده در TextBox استفاده نمایند ، فرصت انجام چنین کاری را به دلیل عدم درج داده توسط کاربر پیدا نخواهند کرد .
شکل عمومی
شکل عمومی کنترل فوق به صورت زیر است :
<asp:RequiredFieldValidator id="id" Runat="Server" |
توضیحات
از یک 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"> |
کنترل <asp:RangeValidator>
کنترل فوق مسئولیت بررسی و ارزیابی داده ورودی در یک TextBox را برعهده گرفته و ماموریت آن حصول اطمینان از این موضوع است که داده درج شده در محدوده مورد نظر است . این محدوده توسط دو خصلت MinimumValue و MaximumValue مشخص می گردد . فرآیند فوق می تواند در ارتباط با نوع های متفاوت داده نظیر Date ، اعداد صحیح ، اعداد اعشاری و یا رشته ( مقدار پیش فرض ) اعمال گردد .
شکل عمومی
شکل عمومی کنترل فوق به صورت زیر است :
<asp:RangeValidator id="id" Runat="Server" |
توضیحات
از یک 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"> |
در بخش دوم به بررسی سایر کنترل های Validation خواهیم پرداخت .
کنترل های Validation در ASP.NET ( بخش دوم )
در بخش اول به ماهیت و جایگاه کنترل های validation اشاره و عملکرد دو کنترل <asp:RequiredFieldValidator> و <asp:RangeValidator> بررسی گردید . در این بخش به بررسی سایر کنترل های validation خواهیم پرداخت .
کنترل <asp:CompareValidator>
کنترل فوق مسئولیت بررسی مقدار درج شده در یک TextBox را برعهده دارد . بدین منظور داده ورودی با یک مقدار خاص و یا مقدار یک کنترل موجود بر روی فرم مقایسه می گردد . نوع داده درج شده در TextBox می تواند از نوع Currency ، Date ، اعشاری ، صحیح و یا رشته ( مقدار پیش فرض ) باشد .
شکل عمومی
شکل عمومی کنترل فوق به صورت زیر است :
<asp:CompareValidator id="id" Runat="Server" |
توضیحات
از یک 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"> |
کنترل <asp:CustomValidator>
در زمان بررسی و ارزیابی داده ورودی ممکن است به مواردی برخورد نمائیم که با ترکیب یک RequiredFieldValidator ، RangeValidator و یا CompareValidator خواسته ما تامین نگردد. در چنین مواردی می توان از کنترل <asp:CustomValidator> به منظور انجام تست های اضافه استفاده نمود .
شکل عمومی
شکل عمومی کنترل فوق به صورت زیر است :
<asp:CustomValidator id="id" Runat="Server" |
توضیحات
خصلت های کنترل <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"> |
در بخش سوم به بررسی سایر کنترل های Validation خواهیم پرداخت .
یک نقص امنیتی در الگوریتم پنهان سازی مورد استفاده در پنهان کردن اسم رمز و 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" برای جلوگیری ذخیره اسم رمزها در رجیستری استفاده کنید.
شاخصهای یک جدول میتوانند به شما در دسترسی به یک یا چند سطر از دادهها کمک کنند. داشتن یک شاخص خوب برای پرس و جوی (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 سریعاً سطرهای منطبق شده را در جدول داخلی بیابد.
شکل 1 طرح پرس و جو را در مورد پرس و جوی 3 نشان میدهد. اولین خط این طرح نوع پیوند (حلقه تودرتو) را نشان میدهد و مشخص میکند که جدول خارجی ستون EmployeeID را ارجاع خواهد داد.
اسکن شاخص کلاستری در جدول خارجی شبیه اسکن یک جدول است زیرا هیچیک از شاخصهای موجود نمیتواند دستیابی به جدول خارجی را سرعت ببخشد. شرط WHERE در ستون OrdrerDate تعداد سطرهای برگردانده شده و تعداد دفعاتی که سرویس دهنده SQL باید به جدول داخلی دستیابی داشته باشد تا تعیین کند کدامیک مقدار
OrderDate قابل قبولی دارند. در نهایت، طرح پرس و جو نشان میدهد که سرویس دهنده SQL از یک شاخص کلاستری برای جستجوی جدول داخلی استفاده میکند زیرا این شاخص روی ستونی است که سرویس دهنده SQL برای یافتن سطرهای منطبق استفاده میکند.
چنانچه قبلاً ذکر شد شاخص در ستون OrderDate چیز خوبی است اما عملکرد پرس و جو را تقریباً به یک شاخص کلاستری روی ستون پیوند بهبود نخواهد بخشید. یک شاخص مفید در پارامتر جستجو در جدول خارجی بدین معناست که سرویس دهنده SQL نباید به تمام صفحات جدول خارجی رجوع نماید، بنابراین، مقدار P1 کاهش مییابد. باتوجه به اینکه مقدار P1 نسبت به مقدار دومین عبارت، P2 R1، کوچکتر است، بنابراین کاهش مقدار P1 فقط موجب بهبودی کمتر عملکرد میگردد. شاخص جدول خارجی تعداد دفعاتی که سرویس دهنده SQL باید به جدول داخلی رجوع کند را کاهش نمیدهد زیرا سرویس دهنده SQL هنوز باید بازای هر سطر تعریف شده در جدول خارجی به جدول داخلی رجوع کند. شما میتوانید انتخاب بهینهساز از پیوند حلقه تودرتو را اینگونه تعمیم دهید: در صورتی که یکی از ورودیهای پیوند بسیار کوچکتر از دیگری و ورودی بزرگتر دارای یک شاخص کلاستری روی ستون پیوند باشد، بهینه ساز اغلب پیوند حلقه تودرتو را برمیگزیند.
ادغام
در پیوند حلقه تودرتو، شاخص ستون پیوند در مورد جدول خارجی بیفایده است. بهرحال، زمانی که شما پرس و جوها و جداول را تنظیم میکنید، ممکن است همیشه ندانید که کدام جدول داخلی و کدام خارجی است، بنابراین باید در هر دو جدول ورودی شاخصهای کلاستری را روی ستونهای پیوند ایجاد کرد. زمانی که هر دو ورودیهای پیوند روی ستون پیوند مرتب سازی میشوند، سرویس دهنده SQL میتواند از پیوند ادغامی استفاده کند، درست مانند موردی که هر دو جدول دارای شاخصهای کلاستری روی ستون پیوند باشند.پیوند ادغامی را میتوان همچون ترکیب دویست مرتب سازی شده از مقادیر تصور کرد. فرض کنید دارای دو سری از اطلاعات پیمانکاری هستید. یک سری شامل قراردادهای مهم میباشد که هر پیمانکاری آن را امضا کرده است و دومین سری توصیف هریک از پروژههایی است که پیمانکار بر روی آن کار میکند بنابراین، شما اساساً نیاز به یک پل ارتباطی میان این دو سری اطلاعات دارید.پرس و جوی 1 را در نظر بگیرید: اگر جدول کارمندان و جدول سفارشات در ستون EmployeeID شاخصهای کلاستری داشته باشند، سرویس دهنده SQL میتواند پیوند ادغامی را اجرا کند. شبه کد مربوطه در مورد اجرای ادغامی سرویس دهنده SQL چیزی شبیه این عبارات خواهد بود:
بهینه ساز پرس و جو معمولاً استراتژی پیوند ادغامی را زمانی انتخاب می کند که هر دو ورودیها قبلاً در ستون پیوند مرتب شده باشند. اگر هر دو ورودی قبلاً مرتب شده باشند، در صورتی که پیوند یک به چند باشد استفاده از 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 تنها زبان استاندارد و جامع پیادهسازی، مدیریت، نگهداری و کار با بانکهای اطلاعاتی میباشد که تقریباً توسط تمام بانکهای اطلاعاتی کوچک و بزرگ مانند 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 نیست بدین معنی که به بزرگ یا کوچک بودن حروف حساس نمیباشد. بنابراین به راحتی میتوان دستورات و کلمات کلیدی آنرا در هر برنامهای با حروف کوچک یا بزرگ تایپ کرد.
یک فایل اچتمل متنی از نوع text است که از عناصر یا element ها تشکیل میشود و برای ایجاد عناصر از تگ ها یا tags استفاده میشود. در این فصل با عناصر و تگ ها اچتمل آشنا خواهید شد.
تگ های اچتمل (HTML Tags)مثال بخش مقدمه را در نظر بگیرید:
<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> |
*** مثال دوم یک عنصر اچتمل (معلوم الحال) :
<body> This is my first homepage. <b>This text is bold</b> </body> |
تگ ها میتوانند حاوی اطلاعات اضافی دیگر باشند، به این اطلاعات شناسه یا Attribute میگویند و وظیفه آنها بیان دیگر اطلاعات یک عنصر یا Element میباشد. مثلا در مورد تگ <body> شناسه ای به نام bgcolor وجود دارد که رنگ زمینه متن (background) را تعیین میکند برای نمونه اگر میخواهید که رنگ زمینه صفحه اچتملتان سیاه باشد کافی است که به شکل زیر عمل کنید :
شناسه ها به صورت کلی "مقدار=نام" یا "name=value" نوشته میشوند و همیشه به تگ شروع یک عنصر یا Element اضافه میشوند و نهایتا اگر در یک عنصر یا Element شناسه ها قید نشوند از مقادیر قراردادی یا default آنها استفاده خواهد شد مثلا در تگ body اگر شناسه bgcolor نوشته نشود از رنگ سفید برای زمینه صفحه استفاده خواهد شد.
مقدار یک شناسه را میتوانید داخل نویسه های " و یا ' بنویسید و اختیار دست شما است فقط در مواردی که مقدار یک شناسه شامل نویسه " هم میشود باید از نویسه ' استفاده شود.
وظیفه گروهی از تگ های اچتمل فرمت دهی و تعیین شکل نمایش متون ( مثلا ضخیم و bold بودن و یا مورب و ایتالیک بودن ) میباشد و در این درس با این گروه از تگهای formating آشنا خواهید شد:
<b> , <big> , <code> , <del> , <em> , <i> , <ins> , <kbd> , <pre> , <s> , <samp> , <small> , <strike> , <strong> , <sub> , <sup> , <tt> , <u> , <var>
مثالهای شکل دهی متون (Text Formatting)
در مثالهای زیر نحوه استفاده از عناصر و تگهای شکل دهی متون شرح داده شده اند:
شکل دهی متون
شکلهای مختلف نمایش متون با کمک عناصر b , strong , big , em , i , small , sub , sup
متون از قبل شکل دهی شده
نمایش متون از قبل شکل دهی شده با کمک عنصر pre یا pre Formatted
برای نمایش اشعار فارسی استفاده از عنصر pre بهترین انتخاب میباشد.
عناصر دیگر شکل دهی متن
نمایش متون deleted، underline و ... با کمک عناصر code , kbd , tt , samp , var , del , ins
نحوه دیدن سورس کدهای اچتمل (HTML Source)
چند نکته کاربردی:
Start Tag | Purpose | کاربرد | ||
---|---|---|---|---|
<b> | Defines bold text | نمایش توپر | ||
<big> | Defines big text | نمایش در اندازه بزرگ | ||
<em> | Defines emphasized text | نمایش بصورت تاکید شده | ||
<i> | Defines italic text | نمایش ایتالیک یا کج | ||
<small> | Defines small text | نمایش در اندازه کوچک | ||
<strong> | Defines strong text | نمایش قوی ؟! | ||
<sub> | Defines subscripted text | نمایش پایین تر از خط افقی | ||
<sup> | Defines superscripted text | نمایش بالاتر از خط افقی | ||
<ins> | Defines inserted text | نمایش به صورت خط زیر | ||
<del> | Defines deleted text | نمایش به صورت خط خورده | ||
<s> | Deprecated. Use <del> instead | از رده خارج | ||
<strike> | Deprecated. Use <del> instead | از رده خارج | ||
<u> | Deprecated. Use styles instead | از رده خارج | ||
Start Tag | Purpose | کاربرد | ||
---|---|---|---|---|
<code> | Defines computer code text | نمایش کدهای برنامه نویسی | ||
<kbd> | Defines keyboard text | نمایش متن بصورت صفحه کلیدی | ||
<samp> | Defines sample computer code | نمایش کدهای نمونه برنامه نویسی | ||
<tt> | Defines teletype text | نمایش تله تایپ | ||
<var> | Defines a variable | نمایش متغییرها | ||
<pre> | Defines preformatted text | نمایش متون از قبل فرمت شده | ||
مرجع : HTML 4.01 Specification - فهرست عناصر - فهرست شناسه ها
تگ ها ( tags ) اجزا تشکیل دهنده عناصر یا elements های اچتمل هستند و در این فصل با عناصر و تگ های پایه و مهم:
<hr> , <br> , <h1> .... <h6> , <!-- comment --> , <p>
آشنا خواهید شد . یکی از بهترین روش های یادگیری تگ های اچتمل دیدن مثالها و تغییر آنها میباشد و با کمک ادیتور اختصاصی ما و با استفاده از امکانات فارسی نویسی آن به صورت آنلاین میتوانید به مطالعه و یادگیری مثالها پرداخته، کدهای اچتمل را تغییر داده و با کلیک روی دکمه "نمایش نتایج" به مشاهده نتایج بپردازید.
مثالی ساده از یک صفحه اچتمل
در این مثال بسیار ساده جمله "!Hellow World" در صفحه مرور گر نمایش داده میشود و در واقع محتوا و متن عنصر body تماما نمایش داده خواهد شد.
پاراگرافهای ساده:
چگونگی نمایش متون با کمک تگ <p> و بصورت پاراگرافی
نمایش متون فارسی:
چگونگی نمایش متون فارسی. برای جزئیات بیشتر به فصل فارسی نویسی مراجعه کنید.
<h1>This is a heading</h1> <h2>This is a heading</h2> <h3>This is a heading</h3> <h4>This is a heading</h4> <h5>This is a heading</h5> <h6>This is a heading</h6> |
<p>This is a paragraph</p> <p>This is another paragraph</p> |
سطر جدید (Line Breaks)
برای رفتن سر سطر جدید از تگ <br> استفاده میشود.در اینحالت یک پاراگراف جدید ایجاد نمیشود. تگ <br> از نوع تگ های خالی بوده و دارای تگ انتهائی (مثلا <br/> ) نمیباشد.<p>This <br> is a para<br>graph with line breaks</p> |
برای نوشتن شرح و توضیحات در مورد کدهای اچتمل باید از تگ خاصی استفاده کنید. برای اینکار باید متن و شرحتان را درون علائم <-- و --!> قرار دهید. مرور تگ های comment را در نظر نگرفته و محتوی آنها را نمایش نخواهد داد و فقط شرح و توضیحات برای برنامه نویس و دیگر افرادی که احتمالا در آینده با کد اچتمل کار خواهند کرد مفید خواهد بود. (به محل نویسه "!" توجه کنید! فقط یکی و آنهم در ابتدا)
<!-- This is a comment --> |
توجه داشته باشید که بدلیل وجود مرورگرهای متفاوت (اکسپلورر، نت اسکیپ، ..) و به دلیل تفاوت دقت نمایش صفحه نمایش کامپیوترها، صفحات اچتمل با اندکی تفاوت در حالتهای مختلف نمایش داده میشوند و همیشه سعی کنید که صفحاتتان را نه تنها با اکسپلورر که معروفترین مرورگر است بلکه با نت اسکیپ و حتی مرورگرهای کامپیوترهای مکینتاش چک کرده و همچنین در دقت های نمایش 800x600 و 1024X768 آن را امتحان کنید.
از نظر فاصله و سطر بندی، متنی که در صفحه ادیتورتان تایپ میکنید با چیزی که مرورگر نمایش خواهد داد متفاوت خواهد بود.همیشه به یاد داشته باشید که فاصله های اضافی (space) و خطهای خالی متن در صفحه ادیتور توسط مرورگر در نظر گرفته نشده و نمایش داده نخواهد شد.
برای نمایش بیش از یک فاصله خالی باید از نویسها یا ترکیب کاراکتری خاصی (None Breaking Space) استفاده کنید. در بخش ( Entities ) نهادها به این مطلب بیشتر پرداخته خواهد شد.
فاصله های اضافی بین کلمات در یک متن اچتمل توسط مرورگرها دیده نخواهد شد و در نمایش همیشه تبدیل به یک فاصله (space) خواهد شد. در ضمن یک خط خالی در متن ادیتور بصورت یک فاصله یا space نمایش داده خواهد شد.
برای ایجاد یک سطر جدید هیچگاه از یک تگ <p> خالی استفاده نکنید و به جای آن از تگ <br> استفاده کنید..
مرورگرها به هنگام نمایش بعضی عناصر بصورت اتوماتیک یک سطر خالی قبل و بعد از آن عنصر نمایش خواهند داد. برای نمونه این گروه از عنصرها میتوان از پاراگراف (<p>) و سرتیترها (<h..>) نام برد.
تگ <hr> یا Horizontal Roler سبب نمایش یک خط افقی خواهد شد و در واقع بخش های مختلف مطالب این صفحات با کمک این تگ از هم جدا شده اند.
باز هم مثال پاراگرافها
این مثال بعضی از مقادیر قراردادی عناصر پاراگراف را شرح میدهد.
ترازبندی پاراگراف ها
این مثال نحوه تراز بندی یک پاراگراف را با کمک شناسه یا attribute ای به نام align نشان میدهد. در این حالت پاراگراف در وسط ناحیه نمایش داده خواهد شد.
( "align="center )
رفتن سر سطر جدید
این مثال نحوه استفاده از تگ <br> را در یک متن اچتمل نشان میدهد.
سر تیترها
این مثال نحوه استفاده از تگهای <h1> .... <h6> را در یک متن اچتمل نشان میدهد.
ترازبندی سر تیترها
این مثال نحوه تراز بندی یک سر تیتر را با کمک شناسه یا attribute ای به نام align نشان میدهد. در این حالت سر تیتر در وسط ناحیه نمایش داده خواهد شد.
( "align="center )
نمایش خطوط افقی
این مثال نحوه نمایش خطوط افقی با استفاده از تگ <br> میباشد.
استفاده از comment
این مثال نحوه استفاده از comment در کدهای اچتمل را نمایش میدهد.
تعیین رنگ زمینه صفحه
این مثال نحوه تعیین رنگ زمینه صفحه را با کمک یکی از شناسه های (attribute ) عنصر body با نام bgcolor نشان میدهد. (Background Color)
( "bgcolor ="blue )
تگهای اصلی
در جدول زیر عناصر معرفی شده در این فصل به همراه لینکهای مربوطه جهت مطالعه بیشتر آورده شده است. توجه داشته باشید که برای هر عنصر فهرستی از شناسه ها یا Attributes موجود است و همچنین به شناسه های کنارگذاشته شده (Deprecated) در نسخه های آینده اچتمل توجه داشته باشید و سعی کنید که از آنها استفاده نکنید.
:
Start Tag | Purpose | کاربرد | ||
---|---|---|---|---|
<html> | Defines a html document | نشان شروع متن اچتمل | ||
<body> | Defines the document's body | تعیین بدنه و قسمت اصلی صفحه اچتمل | ||
<h1>-<h6> | Defines heading 1 to heading 6 | تعریف سر تیترهای h1 تا h6 | ||
<p> | Defines a paragraph | تعریف پاراگراف | ||
<br> | Inserts a single line break | رفتن سر خط جدید | ||
<hr> | Defines a horizontal rule | نمایش خط افقی | ||
<!--> | Defines a comment in the HTML source code | نوشتن شرح و comment | ||
مرجع : HTML 4.01 Specification - فهرست عناصر - فهرست شناسه ها
در این درس با فارسی نویسی، فارسی سازی و استاندارد یونیکد و نحوه استفاده از ادیتور آنلاین و فارسی این سایت آشنا خواهید شد. همچنین متاتگ http-equiv و شناسه dir نیز معرفی خواهد شد.
سؤالات مربوط به فارسی نویسی را میتوان به سه گروه عمده تقسیم کرد:
- چگونه فارسی بنویسم ؟
- چگونه فارسی بخوانم؟
- چگونه صفحات اچتمل فارسی را نمایش دهم؟
در مورد فارسی نویسی و فارسی خوانی اگر از ادیتور آنلاین ما در بخش مثالها استفاده میکنید نیازی به فارسی سازی ندارید و با کمک ادیتور مزبور باید به راحتی قادر به تایپ فارسی و لاتین باشید.اگر میخواهید که در هر حال سیستمتان را فارسی کنید، مطالعه صفحات زیر راهنمای بسیار خوبی برای فارسی سازی میباشند:
* راهنمای فارسی سازی ویندوز
* استفاده از استانداردِ یونیکد
* وبلاگ فارسی FAQ
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
dir="ltr" , Left-to-right text. - چپ به راست
dir="rtl" , Right-to-left text. - راست به چپ
<p dir="rtl"> سلام بر دنیای وب </p>
<div dir="rtl"> سلام بر دنیای وب </div>
در بسیاری از عناصر و تگ های اچتمل امکان استفاده از شناسه dir میسر بوده و به عنوان نمونه میتوان از عناصر زیر نام برد:
<p> , <div> , <html> , <body> , <table> , <tr> , <td> , <h1 ... h6> , <input> , <pre> , <select> , <span> , ...
مثالهای زیر نحوه ترازبندی متون فارسی را به نمایش میگذارند و برای مطالعه بیشتر در مورد ترازبندی متون "راست به چپ" به این صفحه مراجعه کنید. (عناصر BDO ، Span و شناسه lang هم برای مطالعه مفید میباشند.)
مثالهای فارسی نویسی:
مثال 1 : سلام بی وفا
به بخش head و تگ div توجه کنید. متا تگ http-equiv نوع کدگزاری را تعیین میکند و در اینجا با کمک تگ div جهت نوشتن مطالب (از راست به چپ یا بلعکس) تعیین میگردد. dir به معنای direction و جهت بوده و rtl مخفف right to left و ltr معادل left to right میباشد.
مثال 2 : متن ها و پاراگراف بندی
به عناصر div و p توجه کنید. با کمک شناسه dir جهت نوشتن مطالب (از راست به چپ یآ بلعکس) تعیین میگردد.
مثال 3 : متون فارسی و لاتین در کنار هم
مثالی کاملتر با راهنمای استفاده از عنصر div و شناسه dir آن
مثال 4 : شناسه dir در عنصر html
اگر شناسه dir را در عنصر html بکار ببرید جهت نمایش تمامی متون از راست به چپ شده و برای نوشتن از چپ به راست باید به صورت موردی شناسه "dir="ltr را استفاده کنید. همچنین در این حالت ماسماسک! Scrool down مرورگر در سمت چپ صفحه نمایش داده خواهد شد. در صورت استفاده شناسه dir در عنصر body ماسماسک همان سمت راست خواهد ماند.
مثال 5 : مثال کامل
نحوه استفاده شناسه dir در عنصرهای مختلف
لازم به ذکر است که برای فارسی نویسی از کدهای java script موجود در این آدرس که ابزارهای برنامه نویسی فراهم شده توسط شورای عالی انفورماتیک و دانشجویان دانشگاه صنعتی هستند، استفاده شده است و توصیه میشود که پروژه farsiweb.info را فراموش نکرده زیرا که استاندارد آینده فارسی نویسی اینترنتی در ایران خواهد شد.
در استاندارد اچتمل گروهی از نویسه ها (Character) دارای معنی خاصی بوده ( مثلا نویسه < شروع یک تگ و نویسه > انتهای یک تگ را نشان میدهد. ) و برای نمایش آنها در صفحاتتان مستقیما قابل مصرف نمیباشند. در این فصل با فهرست این نویسه ها آشنا شده و نحوه درج آنها را با کمک Character Entities فرا خواهید گرفت.
Character Entities
در اچتمل بعضی از نویسه ها دارای معنی خاصی بوده و برای نمایش آنها در صفحاتتان باید از character entities ها استفاده کنید. یک character entities از سه قسمت تشکیل میشود:
1- نویسه ampersand (&)
2- نام entity یا نویسه # و سپس شماره عددی entity
3 - و نهایتا نویسه semicolon (;)
برای مثال برای نمایش نویسه > دو روش وجود دارد، باید از < یا از < استفاده کنید. در این مثال lt نام entity و 60 شماره عددی آن میباشد.
مزیت استفاده از نام entity در مقابل استفاده از شماره عددی آن سهولت یادآوری آن از روی نامش میباشد و عیب آن این است که تمامی مرورگرها نام گذاریهای موجود برای Entity ها را قبول ندارند ولی در عوض همگی شماره های عددی entity ها را بخوبی میشناسند. توجه داشته باشید که entity ها به کوچک و بزرگی حروف حساس هستند و در واقع Case Sensitive میباشند.
پر کاربردترین character entity در اچتمل، نویسه فاصله یا Space یا Blank میباشد و نام رسمی آن non-breaking space میباشد. همانطور که میدانید مرورگرها فاصله های اضافی را در نظر نگرفته (truncate spaces) و مثلا از 10 نویسه فاصله، 9 تای آنرا نادیده میگیرند و برای نمایش فاصله های اضافی باید از استفاده کنید.
Result (نمایش) | Description (شرح) | Entity Name (نام) | Entity Number (شماره عددی) | |
---|---|---|---|---|
non-breaking space | |   | ||
< | less than | < | < | |
> | greater than | > | > | |
& | ampersand | & | & | |
" | quotation mark | " | " | |
' | apostrophe | ' | ||
چند Character Entitie با کاربردهای کمتر
Result | Description | Entity Name | Entity Number | |
---|---|---|---|---|
¢ | cent | ¢ | ¢ | |
£ | pound | £ | £ | |
¥ | yen | ¥ | ¥ | |
§ | section | § | § | |
© | copyright | © | © | |
® | registered trademark | ® | ® | |
× | multiplication | × | × | |
÷ | division | ÷ | ÷ | |
برای دیدن فهرست کل character entities ها سری به این صفحه بزنید.