سلام. دوستان. قصد دارم در این تاپیک یک سری سوال بنویسم و جوابهاشو نیز بعد از یکی دو روز قرار میدم. دوستان سعی کنند مسائل رو حل کنند . در هر مسئله ای نکته ریزی وجود دارد که قدرت شما رو در دستورات TSQL افزایش میده.
باتشکر.
Printable View
سلام. دوستان. قصد دارم در این تاپیک یک سری سوال بنویسم و جوابهاشو نیز بعد از یکی دو روز قرار میدم. دوستان سعی کنند مسائل رو حل کنند . در هر مسئله ای نکته ریزی وجود دارد که قدرت شما رو در دستورات TSQL افزایش میده.
باتشکر.
سوال اول:
جدول زیر رو در نظر بگیرید:
CREATE TABLE [dbo].[CustomerMaster](
[CustomerId] [int] IDENTITY(1,1) NOT NULL,
[CustomerCode] [varchar](30),
[CustomerName] [varchar](200),
[CreatedDate] [datetime],
[ContactNo] [varchar](20)
CONSTRAINT [PK_CustomerId] PRIMARY KEY CLUSTERED
(
[CustomerId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[CustomerDocuments](
[DocAttachmentId] [int] IDENTITY(1,1) NOT NULL,
[CustomerId] [int] NOT NULL,
[DocumentType] [varchar](5),
[DocumentName] [varchar](200) NULL,
CONSTRAINT [PK_CustomerDocs] PRIMARY KEY CLUSTERED
(
[DocAttachmentId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
ALTER TABLE [dbo].[CustomerDocuments] WITH CHECK ADD CONSTRAINT [FK_DocAttachment_Customer] FOREIGN KEY([CustomerId])
REFERENCES [dbo].[CustomerMaster] ([CustomerId])
GO
ALTER TABLE [dbo].[CustomerDocuments] CHECK CONSTRAINT [FK_DocAttachment_Customer]
GO
فرض کنید در جدول Customer master 20 ردیف وجود دارد و دو Document برای هر Customer در جدول CustomerDocument . خروجی بعد از دستورات زیر چه خواهد بود.؟
TRUNCATE TABLE CustomerDocuments
TRUNCATE TABLE CustomerMast
SELECT IDENT_CURRENT( 'CustomerMast' )
گزینه 1 - عدد 1
گزینه 2 - خطا هنگام Truncate
گزینه 3- عدد 21
لطفا جواب خود را با توضیح بیان فرمائید.
سلام
جواب برابر 1 مي باشد.
چون بعد از truncate كردن همه چيز براي جداول مورد نظر reset مي شود. مثلا حافظه اختصاص داده شده.
جواب گزینه 2 .
چون کلید اصلی جدول customerMaster در جدول CustomerDocuments به عنوان
ForeignKeyتعریف شده و در این موارد جدول Master قابل truncate شدن نیست.
تشکر میکنم از جناب sepahan82 . جواب صحیح گزینه دو می باشد و همونطور که فرمودند در جدولی که foreignkey هست شما نمیتونید از Truncate استفاده کنید.
فقط در صورتی میشه با وجود Foreignkey عمل Truncate رو انجام داد که Foreignkey به خود جدول اشاره شده باشه نه به یک جدول دیگه.
سوال دوم رو در اسرع وقت مطرح خواهم کرد.
سوال دوم:
نتیجه Query زیر چه خواهد بود؟
SELECT DATEADD(MONTH, 3, '31-Jan-2010')
گزینه 1 : 00:00:00.000 30-04-2010
گزینه 2 : 00:00:00.000 31-03-2010
گزینه 3 : 00:00:00.000 29-04-2010
سلام.توضیح که دادم چون به صورت Foreignkey هست اجازه Truncate به شما نمیده. میتونید کد فوق رو تست کنید.
00:00:00.000 30-04-2010
قبل از هر چيزي از زحماتي كه ميكشيد واقعا ممنونم.
جواب : گزينه 1
جناب صادقيان اگر اين كد رو اجرا كنم به راحتي به جواب ميرسم!!
اگر قراره معما طرح كنيد معماهايي طرح كنيد كه با اجرا كردن كد شما به جواب نرسيم و نياز به تجزيه تحليل بيشتري داشته باشه. ممكنه بعضي از دوستان سعي كنند نكته كد رو با فكر كردن بفهمند ولي دوستان ديگه با اجرا جواب رو بدست ميارن و ...
اگر هم قصد داريد در مورد نكته كدها صحبت كنيد بهتره تاپيكي فرضا با عنوان نكته هايي در SQL Server درست كنيد و اين نكات رو اونجا قرار بديد تا ماهيت تاپيك حفظ بشه و كارايي تالار بالا بره.
سلام.
ممنون از جناب یاراحمدی. نکته شما در معماهای بعدی رعایت خواهدشد.نقل قول:
جناب صادقيان اگر اين كد رو اجرا كنم به راحتي به جواب ميرسم!!
اگر قراره معما طرح كنيد معماهايي طرح كنيد كه با اجرا كردن كد شما به جواب نرسيم و نياز به تجزيه تحليل بيشتري داشته باشه. ممكنه بعضي از دوستان سعي كنند نكته كد رو با فكر كردن بفهمند ولي دوستان ديگه با اجرا جواب رو بدست ميارن و ...
اگر هم قصد داريد در مورد نكته كدها صحبت كنيد بهتره تاپيكي فرضا با عنوان نكته هايي در SQL Server درست كنيد و اين نكات رو اونجا قرار بديد تا ماهيت تاپيك حفظ بشه و كارايي تالار بالا بره.
با اجازه
اينم ازون معماهاي جالب كه استاد سر كلاس به ما آموزش داد:
فرض كنيد جداول زير رو داريم:(دروس، روزهاي هفته و ترم)
Courses:
ID,Name(1-riazi; 2-zaban; 3-farsi,...)
--------
Days
ID,Name(0-shanbe;1-yekshanbe,2-doshanbe,...)
--------
Term:
StudentID(foreign key),CourseID(foreign key),DayID(foreign),Hour(between 8-18)
(1,1,0,8)
كوئري برنامه كلاسي را به شكل زير بنويسيد (شماره دانشجويي را ثابت در نظر بگيريد يعني لازم نيست به يك پروسيجر پاسش بديد و ... در ضمن جدول دانشجو زياد مهم نيست)
http://www.barnamenevis.org/at...1&d=1288507238
راهنمايي:
از توابع هم بايد استفاده كنيد:لبخندساده:
(حاج حميد تازه ديدمت! تبريك :تشویق::لبخندساده:)
سلام
منم با اینکه جواب با یه ctr+c ctr+v معلوم بشه مخالفم پست قبلیم رو هم به همین منظور زدم
با تشکر از اقای حیمدرضا صادقیان
ويرايش شده براي پاسخ:
اينم پاسخ پست 13
با توجه به خروجي مورد نظر ما بايد از جدول روزها Select بگيريم
select name from days
و براي اينكه بفهميم مثلا در روز جاري در select ، ساعت 8 دانشجوي x چه درسي را انتخاب كرده نياز به يك تابع داريم كه اين موارد رو گرفته و خروجي متني برابر با نام درس را به ما ميدهد.
پس شكل كلي كوئري به اين صورت خواهد بود
select
d.name as [rooze hafte],
fGetCourseName(@studentID,d.code,8) as [8-10],
fGetCourseName(@studentID,d.code,10) as [10-12],
fGetCourseName(@studentID,d.code,12) as [12-14],...
from
days d
بدنه تابع هم ميتونه چيزي توي اين مايه ها باشه
create function fGetCourseName (@studentID int, @dayCode int, @hour int) returns nvarchar(50) as
begin
declare @cource nvarchar(50);
set @course=(
select
c.name
from courses c,students s,days d,term t
where
c.code=t.course and
t.studentid=@studentID and
t.day=@dayCode and
t.hour=@hour
)
if @course is null set @course='--'
return @course;
end
من بخاطر حل اين مسئله حدود 2 نمره به پايان ترمم اضافه شد. مشكلي كه توي حلش داشتم اين بود كه نميدونستم بايد ديدم رو برعكس كنم. چون خروجي هاي اس كيو ال معمولا از چپ به راسته و اينجا از راست به چپ نمايش داديم كمي گيج شده بودم
مسئله بعدي نمايش جدول ليگ برتره! اگه تكراريه بگيد كه روش كار نكنم و برم بعدي
ميخواهيم جدول ليگ فوتبال و يا هر ورزش ديگه اي رو توسط كوئري ها ايجاد كنيم
جداولي كه داريم به اين شكل خواهند بود:
------
جدول تيم:
-شماره
-نام تيم
------
جدول بازي ها:
-شماره تيم 1
-شماره تيم 2
-گل زده تيم 1
-گل زده تيم 2
-------------------------
*جدول ليگ رو به شكل زير ازين جداول بگيريد:
خب دوستان بابت تاخير عذر ميخوام
و اما جواب (ظاهرا كسي حوصله حلش رو نداشته!) به هر حال.
view ها اينجا كاربردشون رو نشون ميدن.
فرض كنيد جدول ما داده هاي زير رو دارن:
ما اگه يك ديد از جدول بالا به صورت زير داشته باشيم:
كار كوئري گيري ازون بسيار راحت تر ميشه. ساختار جدول رو كه نميشه تفيير داد. پس مجبوريم يك view بسازيم تا قالب مورد رو به
ما بده و ازون قالب كوئري نهايي رو بگيريم
اين view شكل بالا رو به ما ميده
create view leagueView as
select
t1 [teamID],
g1 [zade],
g2 [khorde],
3 [emtiaz],
1 [bord],
0 [bakht],
0 [tasavi]
from
league
where
g1>g2
union all
select
t1,
g1,
g2,
1,
0,0,1
from
league
where
g1=g2
union all
select
t1,
g1,
g2,
0,
0,1,0
from
league
where
g1<g2
---------
union all
select
t2,
g2,
g1,
3,
1,0,0
from
league
where
g2>g1
union all
select
t2,
g2,
g1,
1,
0,0,1
from
league
where
g1=g2
union all
select
t2,
g2,
g1,
0,
0,1,0
from
league
where
g2<g1
و اين select خروجي نهايي رو خواهد داد
select
teamid,
sum(bord)[bord],
sum(bakht)[bakht],
sum(tasavi)[tasavi],
sum(zade)[zade],
sum(khorde)[khorde],
sum(zade)-sum(khorde)[tafazol],
sum(emtiaz)[emtiaz]
from
leagueView
group by teamid
http://www.barnamenevis.org/at...1&d=1288792965
براي نمايش نام تيم هم كافيه يك جوين به جدول تيمها بزنيم
شايد شما از راههاي ديگه هم حلش كنيد. (اين راه حل قطعي نيست)
سلام
امیدوارم همگی خوب باشید ،
این تاپیک توسط آقای صادقیان ایجاد شده،نمی دونم ما هم اجازه داریم معمای خودمان را در این تاپیک بزاریم در هر حال با اجازه ایشون،
حالا دو معما ساده ،
1.یک دستور row insertنوشتیم بعد قبل از اینکه این دستور را commitکنیم یک کاربر دیگه میاد select * می زنه تا داده های این جدول را ببیند ،آیا اون row درج شده توسط اون کاربر را می بینه؟
2.یک دستور insert row نوشتیم بعد قبل از اینکه این دستور را commitکنیم خود این کاربر میاد select * می زنه تا داده های این جدول را ببیند ،آیا قادر است اون row درج شده توسط خودش را ببیند؟
با توضیحات کامل لطفا
سلام.ممنون از دوستان. عزیزانی که معما میخواهند مطرح کنند به صورت خصوصی برای من ارسال کنند تا پس از بررسی درج شود که خط مشی این تاپیک حفظ شده و بتوان نکات مثبتی را درآن درج نمود.
باتشکر
اگر دستور commit نشده کاربر چی رو میخواد ببینه؟یا این هست که دستور اجرا شده و به صورت dirty page در log file وجود داره که در اونصورت با تغییر در select میتوان اونو دید.ولی اگر منظور این هست که دستور insert اصلا اجرا نشده!! ( که فکر نمیکنم اینطوری باشه) خیر در این صورت کاربر نمیتونه ببینه.
در مورد commit بیشتر توضیح بدین
تا اونجا که من متوجه شدم commit شدن یک دستور یعنی دستور اجرا بشه و داده ها را در جداول database ثبت کنه،ولی تا زمانی که فقط دستورtransaction شده (begin tran)فقط در logfile موجوده،
پس در مورد اول چیزی نمی بینه چون تغییرات یک کاربر زمانی برای کاربر دیگه قابل رویت است که در دیتابیس ثبت شده باشه.
ولی در مورد دوم،چون کاربر با session مربوط به خودش داره کار می کنه حتی با شروع transaction قبل از commit داده ها را می بینه چون در logfile مربوطش هست؟!
سلام.خیر به این صورت نیست. شما وقتی که یک دستور رو ثبت میکنید در log File ذخیره میشه و log file در بازه های زمانی خاصی با توجه به نوع Recovery Model دیتابیس اون دستورات رو در دیتابیس اضافه میکنه. وقتی که یک Transaction صورت میگیره اگر در بین اون Transaction باشه میتونه به وسیله استفاده از Dirty Page محتویات جدول رو ببینه.
در مورد ثبت مشكلي نيست يعني در هر صورت بايد در هارد ذخيره بشه حالا چه logfile چه database اصلي كه در هارد هست.
من منظورم قبل از commit هست يعني حين transaction هست.كه دستورات و داده ها در buffer ذخيره مي شند.چه data buffer cash باشه چه log buffer cash .يعني داده ها و دستورات در RAM هستند و هر يوزر براي خودش يك instance از ديتابيس داره.
ما کلا یک Buffer داریم که اونهم به این صورت عمل میکنه که Page های فایل Data رو خوانده و در RAM نگهداری میکند . اونهم برای سرعت عمل بیشتر. اگر قرار باشه SQL Server برای نوشتن با RAM کار کنه که مشکل ساز خواهد شد. تمام عملیات نوشتن در فایل LOG ذخیره میشه و اگر Transaction کامل انجام بشه دستورات Commit شده و در فایل data نوشته می شوند در غیر اینصورت برگشت داده خواهند شد.
حالا شما وقتی دارید درون یک Transaction یک عملیاتی رو انجام میدید معمولا جدول Lock میشه (البته میتونید نوع قفل شدن رو نیز مشخص کنید) و در Select کردن کاربر میتونه Data رو به همون روشی که عرض کردم بخونه.
موفق باشید
سلام
جواب معما:
ديگران نمي تونند مقدار insert شده رو ببينند چون هنوز commit نشده
اما خود اون فرد اگه قبل از commit يه select بزنه، مي تونه ببينه
ولی برای نوشتن از RAM هم استفاده میشه،پس وظیفه Database Writer process چیست؟
datafile ها که در RAM قرار دارند اگر تغییر کنند مگر در همون datafile ها update نمی شند و بعد توسط writer در database ذخیره میشند.
موردی که میزان Insert یا Update بیش از حجم Buffer ها تعریف شده باشه،درست، برای نوشتن یک راست میره سراغ hard،دستورات توسط log writer از Log Buffer بروی Log نوشته می شود،وما بدون اینکه داده ای در Database ذخیره شده باشد پیغام Commit Successfully را می بیینیم،بعد بمرور زمان اطلاعات روی دیتابیس ذخیره میشود یا Rollback میشند.
سلام. این مواردی که دارید میفرمائید مربوط به Oracle هست که میتونید در این لینک هم توضیحاتشو ببینید
http://msdn.microsoft.com/en-us/libr...=SQL.100).aspx
می تونید به من بگید dirty page ها چه هستند؟مگر همان داده موجود در بافر نیستند که update شده اند،یا فقط بعنوان تغییر یافته علامت گذاری شده اند؟مگر log در ابتدا در بافر ذخیره نمی شند؟
می تونید بیشتر توضیح بدید؟
من اصلا در مورد oracle صحبت نمی کنم!
با سلام خدمات دوستان عزیز
در این موضوع خاص تا اینجا که نوشته شده بنظر میرسد که هر کدام از دوستان از یک منظر خاص به موضوع نگاه میکند و لذا آنچه دیگری مطرح میکند بنظر وی اشتباه میرسد:
1- دیدگاه اول تنها سمت سرور داده را مد نظر داشته و از آن جایگاه به آن نگاه میکند
2- دیدگاه دوم به نظر میرسد که از سمت کاربر و در رابط کاربر نگاه میکند که دارای Session بوده و مفهوم حافظه موقت سمت کاربر است جدا از آنکه داده به سمت SQL رفته باشد.
آیا این نظر درست است یا اشتباه است؟
اصلا دیدگاه سمت کلاینت معنا ندارد. SQL Server داده ها رو به سمت کلاینت cache نمیکنه. بلکه page های مورد نظر رو از هارد خونده و در RAM نگهداری میکند و در صورت نیاز کاربر نتیجه را به کاربر ارسال میکند.نقل قول:
دیدگاه اول تنها سمت سرور داده را مد نظر داشته و از آن جایگاه به آن نگاه میکند
2- دیدگاه دوم به نظر میرسد که از سمت کاربر و در رابط کاربر نگاه میکند که دارای Session بوده و مفهوم حافظه موقت سمت کاربر است جدا از آنکه داده به سمت SQL رفته باشد.
آیا این نظر درست است یا اشتباه است؟
با تشکر از جناب صادقیان:
آیا این جمله درسته و مفهومش چیه؟
نقل قول:
An instance can exist without a database
چه تاپیکه باحالیه اینجا... میشه از اساتید 2 تا خواهش بکنم:
1- معما ها و سوال ها توسط یک نفر مطرح بشه ( مدیر تاپیک)و هر کسی که می خواد مساله طرح بکنه اونو واسه ایشون بفرسته.... اینجوری واسه کسائی که می خواند از این تاپیک استفاده کنند دنبال کردن مطالب راحتتر میشه
2-تستهای آزمونهای 70-433 و 70-432 هم مطرح و تحلیل بشند.
سلام
سوال:آیا یک instance می تونه بدون database موجودیت داشته باشه؟
بله می تونه،اول که sql رو Run می کنیم در واقع هیچ database رو باز نکردیم یا ایجاد نکردیم پس Instance ما بدون وجود database وجود داره.
روی این Instance باید یک دیتابیس قرار بگیره یا سوار بشه،تا داده های اون دیتابیس برای ما مفهوم پیدا کنه.درواقع Instance مجموعه ای از Memory و Processes های هست که داده های هارد را برای ما معنادار می کنه.
هر Instance فقط می تونه روی یک دیتابیس سوار بشه.
هدف من از طرح این سوالات بحث در مورد مفاهیم هست.
ولی استقبالی دیده نمی شه!
سلام.
دارم روی مباحثی کار میکنم انشالله به زودی این قسمت رو پربار خواهیم کرد.
سلام.
انشالله دوباره این تاپیک رو فعل خواهیم کرد ولی با سوالات جالب و جدید.سعی می کنم سوالات امتحانات Microsoft هم بررسی کنیم.
خوب اینم برای شروع :
فرض کنید در یک جدول دو ستون داریم به نام Id و Description .
این جدول حاوی اطلاعات زیر می باشد :
Id Description
-------------------------------
1 Line1
2 Line2
3 Line3
...
1000 Line1000
حال می خواهیم اطلاعات رو به شکل زیر نمایش بدیم:
Description
--------------
Line1,Line2,Line3,Line4,....,Line1000
یک دستور بهینه و مناسب برای اینکار ارائه دهید.
نقل قول:
یک دستور بهینه و مناسب برای اینکار ارائه دهید.
DECLARE @Descriptions ntext
SET @Descriptions = ''
SELECT @Descriptions = COALESCE(@Descriptions + ', ', '') + CAST([Description] AS nvarchar(50))
FROM [TableName]
SELECT @Descriptions
ممنون از جواب. جواب صحیح هست.
البته بهتره به جای استفاده از ntext از nvarchar استفاده بشه تا Query بهینه تر باشه.چون این تعداد با nvarchar هم به راحتی جواب میده.ntext برای متون بزرگ هست که البته الان در نسخه های جدید دیگه ازش استفاده نمیشه و به جاش میشه از varbinary استفاده کرد.
تا جایی که میدونم دستور دوستمون فقط ساده ترین روش بود نه بهینه ترین!!:متفکر:
تنها نکته دستور استفاده از تابع COALESCE است که در اینجا برای هندل کردن مقدارهای NULL و ترفندی برای مدیریت کاماها به کار رفته ، فکر نمیکنم این تابع نسبت به تابع ISNULL از سرعت پردازش بالاتری برخوردار باشه. برای کاما هم میشه با استفاده از تابع Substring این موضوع رو درست کرد.
اگر دستور بالا رو بصورت زیر تغییر بدیم سرعت اجرایی بسیار بالاتری پیدا میکنه
DECLARE @Descriptions Nvarchar(max)
SET @Descriptions = ''
SELECT @Descriptions = (SELECT CAST([Description] AS Nvarchar) + ','
FROM [TableName]
FOR XML PATH(''))
SELECT @Descriptions
فرض کنید جدولی داریم دارای چندین میلیون رکورد. نیاز داریم تعداد کل رکوردهای موجود در جدول را فراخوانی کنیم.
برای اینکار چه راهی پیشنهاد می دهید؟
نکته: جدول دارای Clustered Index نیز می باشد.
سلام
سوال خیلی کلی بنظر میاد.چون دقیقا query مشخص نیست چیه ؟
بهترین گزینه برای بازیابی تعداد زیادی رکورد بشکل مرتب شده استفاده از clustered index هست.
چون ذکر شده clustered index داریم،Composite index بهترین حل از نظر من هست چون در اینصورت خود table به عنوان ساختار index در نظر گرفته میشود و حجم اضافه برای ذخیره ایندکس لااقل نداریم.:متفکر: