Sunday, September 14, 2008

ROW_NUMBER

+آپدیت: این هفته سه‌شنبه سایت A آزاد نیست. فعلن این هفته کلاس طبق روال قبلی روزهای 5شنبه و جمعه تشکیل می‌شه. خواهش می‌کنم مطالب جلسات قبل رو مطالعه کنید و در این دو جلسه غیبت نکنید٬ چون مبحث خیلی مهم Index ها رو شروع می‌کنیم.



+خب اول توضیح بدم که من تصمیم گرفتم تو این وب‌لاگ به جای نگارش رسمی از شکسته‌نویسی(نوشتن محاوره‌ای) استفاده کنم. کارم دو دلیل داشت. یکی این‌که بیش‌تر از 4 ساله که جای دیگه‌ای شکسته می‌نویسم و خب این ترک عادت موجب عارضه‌ی کم نوشتن شده بود. دوم این‌که روی نوشته‌هایی که با نگارش رسمی می‌نویسم خیلی وسواسم زیاده که پر از کلمات بزرگ چندین بخشی نشه و در ضمن غلط نداشته باشه و از نظر نگارشی روون باشه که با شیوه‌ی محاوره‌ای این مشکلات وجود نداره. ضمن این‌که تجربه‌ی کوتاهی که از نوشتن وب‌لاگ با موضوع فنی داشتم این بوده که این‌طوری٬ رابطه دوطرفه من و مخاطب ساده‌تر برقرار می‌شه(این شد دلیل سوم :) ). در نتیجه از این به بعد اوضاع بر این منواله.



+نکته دیگه این‌که تونستم Windows Live Writer رو به صورت Portable رو فلش‌دیسکم نصب کنم. در نتیجه می‌تونم روی لپ‌تاپم(که معمولن با اون کار می‌کنم) بنویسم و نتیجه رو روی PC(که به اینترنت وصله) پابلیش کنم. تا 3-2 روز دیگه هم یه Wireless Adapter می‌گیرم که لپ‌تاپ رو با PC شبکه کنم و بتونم از ADSL روی لپ‌تاپ هم استفاده کنم.



+سر کلاس گفتم که چند مطلب ویرایش نشده دارم که به تدریج پست می‌کنم. مطلب این پست جزو اون‌ها نیست. یکی از دوستان دیروز تعدادی از script های دیتابیسش رو داده بود که من یه نگاهی به‌شون بندازم. توی چند تا از stored procedure ها لازم بوده که تو دستور select ٬ شماره سطر رو هم برگردونه. از روشی استفاده کرده بود که ظاهرن آقای بنایی پیشنهاد کرده بوده(لینکش رو برام فرستاد). من خودم با این روش موافق نیستم چون اورهد پردازش زیادی داره(مربوط می‌شه به table scan‌ ها که این‌جا بحثش رو باز نمی‌کنم چون خیلی مفصله. اواخر دوره توضیح مختصری راجع‌ به‌شون می‌دم٬ بحث مفصلش می‌مونه برای دوره administration-اگر تشکیل بشه البته).



اما راه حل من. من قبلن به این شکل عمل می‌کردم:



 




SELECT [row_number]=IDENTITY(int,1,1), * 
INTO #testtbl
FROM sys.objects

SELECT * FROM #testtbl



 
GO



همون‌طور که می‌بینید من یه متغیر از نوع identity قبل از * اضافه کردم که به ازای هر سطر یکی به مقدارش اضافه می‌شه. اما چون این روش فقط با دستور SELECT INTO قابل انجامه٬ من یه جدول temporary درست کردم و نتیجه رو توی اون ریختم. درباره جدول‌های temporary و دستور SELECT INTO لطفن به "فصل 5 درس 3" و "فصل 3 درس 1" یه نگاهی بندازید٬ جلسه آینده هر دو مورد رو توضیح می‌دم.



نتیجه اجرای اسکریپت بالا:








اما همراه SQL Server 2005 ٬ تابع ROW_NUMBER معرفی شد که کار رو راحت‌تر کرده. به اسکریپت بعدی توجه کنید:






SELECT ROW_NUMBER() OVER(ORDER BY [object_id]) AS [row_number],* 
FROM sys.objects

GO



سینتکس تابع به صورت (ROW_NUMBER() OVER(ORDER BY column_name  هست که نیاز به توضیح بیش‌تر نداره. خروجی این دستور هم دقیقن مثل دستور قبلیه.



 



+پ.ن: اگر لازم باشه سطرهای خاصی رو انتخاب کنیم(مثلن سطرهای 100 تا 110) یک راه٬ استفاده از این سینتکس هست:



 




WITH [tbl_Numbered_Rows] AS 
(SELECT ROW_NUMBER() OVER (ORDER BY [object_id]) AS [row_number] ,*
FROM sys.objects)
SELECT * FROM tbl_Numbered_Rows
WHERE [row_number] BETWEEN 100 AND 110

GO




+پ.ن: اگر سوالی دارید لطفن کامنت بذارید.

Tuesday, August 26, 2008

کلاس روز پنج‌شنبه ۷ شهریور کنسل شده است.
روز جمعه ۸ شهریور کلاس در دو جلسه از ساعت ۸ تا ۱۳ برگزار می‌شود.

Sunday, August 24, 2008

Orphaned Users

-در مورد مطالب وب‌لاگء سعی می‌کنم هم مطالب مقدماتی و هم مباححث پیش‌رفته‌تر را این‌جا مطرح کنم.

-لینک پست قبل به لیست توابع رشته‌ای SQL Server 2005 بود. در مورد توابع سیستمی جلسه آیندهء ۸ شهریورء مباحث خلاصه‌ای را مطرح می‌کنم و لینک مربوط به این نوع توابع را در وب‌لاگ خواهم گذاشت.

-این پست در مورد Orphaned User ها یا User های رهاشده است.

-یادآوری: برای متصل شدن به Instance ۲ راه وجود داشت: Windows Authentication و SQL Authentication. ما ابتدا Login ی بر روی Instance ایجاد می‌کردیم که از آن برای اتصال به دیتابیس به یکی از این دو روش استفاده می‌کردیم. اولین قدم در پروسه اتصال به Instanceء Authentication است تا مشخص شود آیا Login مورد نظر می‌تواند به دیتابیس کانکت شود یا خیر.

نکته: برای دیدن لیست Login ها و User ها می‌توانید از View های sys.syslogins و sys.server_principals استفاده کنید(در جلسه قبل توضیح داده شد).

پس از این‌که Authentication انجام شدء سرویسء چک می‌کند که آیا در دیتابیس‌هایی که به Instanceء Attach شده‌اند User ی به این Loginء Map شده است یا خیر. اگر Userی در دیتابیسی به Login مورد نظر ما Map شده بودء بر اساس دسترسی‌هایی که برای User تعریف شده استء دسترسی Client ی که با این Login به Instance متصل شده است Set می شود.

-حال Orphaned User چیست؟ User رها شدهء User ی است که Login برای آن تعریف نشده یا به صورت اشتباه تعریف شده است(نمونه: وقتی شما Loginی را حذف می‌کنیدء User هایی که به آن Map شده‌اندء به عنوان Orphaned User به حساب می‌آیند. یکی از موارد دیگری که ممکن است به چنین موضوعی بر بخوریدء منتقل کردن دیتابیس از یک سرور به سرور دیگر است-اتفاقی که دیروز برای من افتاد و انگیزه‌ی نوشتن این مطلب شد).

چطور می‌توان Orphaned User ها را در دیتابیس پیدا کرد؟ از اسکریپت زیر استفاده کنید:


sp_change_users_login @Action=’Report’



دقت کنید که این اسکریپت در سطح دیتابیس است نه Instance.

توصیه می‌کنم هربار پس از انتقال دیتابیس بین دو Instance مختلف این اسکریپت را اجرا کنید و یا Orphaned User ها را دوباره به Login ی Map کنید یا آن‌ها را حذف کنید.

sp_change_users_login یک Stored Procedure سیستمی است. در مورد Stored Procedure ها در جلسات آینده صحبت خواهیم کرد.

-توضیحات تکمیلی در مورد sp_change_users_login

Thursday, August 21, 2008

SQL Server String Functions



Link @ MSDN

Friday, August 15, 2008

Trim Function

در SQL Server 2005 تابع Trim وجود ندارد.
2 راه برای Trim کامل وجود دارد.
یکی، همان طور که در کلاس مطرح شد، به شکل زیر است:


LTRIM(RTRIM(str))



راه دیگر تعریف تابع Trim است. برای تعریف تابع Trim در دیتابیس از script زیر استفاده کنید:


CREATE FUNCTION dbo.TRIM(@str VARCHAR(MAX))

RETURNS VARCHAR(MAX)

BEGIN
RETURN LTRIM(RTRIM(@str))
END

GO


درباره توابع در جلسات آینده بحث خواهیم کرد.

در همین راستا، تابع REPLACE نیز یکی از توابع رشته ای مفید است.
این تابع در یک رشته مورد نظر شما، یک زیر رشته را با زیر رشته دیگر تعویض می کند.



REPLACE(main_str,search_str,replace_str)



main_str: رشته اصلی
search_str: زیر رشته ای که می خواهید تعویض شود
replace_str: زیر رشته ای که می خواهید search_str با آن تعویض شود.

مثال:



REPLACE('This is a test','is','XX')

result:

'ThXX XX a test'