PDA

View Full Version : معما از نوع SQL Server .



حمیدرضاصادقیان
شنبه 08 آبان 1389, 08:23 صبح
سلام. دوستان. قصد دارم در این تاپیک یک سری سوال بنویسم و جوابهاشو نیز بعد از یکی دو روز قرار میدم. دوستان سعی کنند مسائل رو حل کنند . در هر مسئله ای نکته ریزی وجود دارد که قدرت شما رو در دستورات TSQL افزایش میده.
باتشکر.

حمیدرضاصادقیان
شنبه 08 آبان 1389, 08:31 صبح
سوال اول:

جدول زیر رو در نظر بگیرید:
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

لطفا جواب خود را با توضیح بیان فرمائید.

sajjadrazmi
شنبه 08 آبان 1389, 11:34 صبح
سلام

جواب برابر 1 مي باشد.

چون بعد از truncate كردن همه چيز براي جداول مورد نظر reset مي شود. مثلا حافظه اختصاص داده شده.

حمیدرضاصادقیان
شنبه 08 آبان 1389, 12:42 عصر
سلام

جواب برابر 1 مي باشد.

چون بعد از truncate كردن همه چيز براي جداول مورد نظر reset مي شود. مثلا حافظه اختصاص داده شده.

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

sepahan82
شنبه 08 آبان 1389, 13:01 عصر
جواب گزینه 2 .
چون کلید اصلی جدول customerMaster در جدول CustomerDocuments به عنوان
ForeignKeyتعریف شده و در این موارد جدول Master قابل truncate شدن نیست.

حمیدرضاصادقیان
شنبه 08 آبان 1389, 13:33 عصر
تشکر میکنم از جناب sepahan82 . جواب صحیح گزینه دو می باشد و همونطور که فرمودند در جدولی که foreignkey هست شما نمیتونید از Truncate استفاده کنید.
فقط در صورتی میشه با وجود Foreignkey عمل Truncate رو انجام داد که Foreignkey به خود جدول اشاره شده باشه نه به یک جدول دیگه.

سوال دوم رو در اسرع وقت مطرح خواهم کرد.

حمیدرضاصادقیان
یک شنبه 09 آبان 1389, 07:48 صبح
سوال دوم:

نتیجه 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

sajjadrazmi
یک شنبه 09 آبان 1389, 08:12 صبح
جواب گزینه 2 .
چون کلید اصلی جدول customerMaster در جدول CustomerDocuments به عنوان
ForeignKeyتعریف شده و در این موارد جدول Master قابل truncate شدن نیست.

سلام

ولي شما اول دارين جدول detail رو truncate مي كنين بعد جدول master رو.
اگر برعكس انجام مي دادين اونوقت خطا رخ مي داد.

حمیدرضاصادقیان
یک شنبه 09 آبان 1389, 08:47 صبح
سلام.توضیح که دادم چون به صورت Foreignkey هست اجازه Truncate به شما نمیده. میتونید کد فوق رو تست کنید.

r00tkit
یک شنبه 09 آبان 1389, 09:08 صبح
00:00:00.000 30-04-2010

Reza_Yarahmadi
یک شنبه 09 آبان 1389, 09:10 صبح
سوال دوم:

نتیجه 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
قبل از هر چيزي از زحماتي كه ميكشيد واقعا ممنونم.
جواب : گزينه 1
جناب صادقيان اگر اين كد رو اجرا كنم به راحتي به جواب ميرسم!!
اگر قراره معما طرح كنيد معماهايي طرح كنيد كه با اجرا كردن كد شما به جواب نرسيم و نياز به تجزيه تحليل بيشتري داشته باشه. ممكنه بعضي از دوستان سعي كنند نكته كد رو با فكر كردن بفهمند ولي دوستان ديگه با اجرا جواب رو بدست ميارن و ...
اگر هم قصد داريد در مورد نكته كدها صحبت كنيد بهتره تاپيكي فرضا با عنوان نكته هايي در SQL Server درست كنيد و اين نكات رو اونجا قرار بديد تا ماهيت تاپيك حفظ بشه و كارايي تالار بالا بره.

حمیدرضاصادقیان
یک شنبه 09 آبان 1389, 09:49 صبح
سلام.

جناب صادقيان اگر اين كد رو اجرا كنم به راحتي به جواب ميرسم!!
اگر قراره معما طرح كنيد معماهايي طرح كنيد كه با اجرا كردن كد شما به جواب نرسيم و نياز به تجزيه تحليل بيشتري داشته باشه. ممكنه بعضي از دوستان سعي كنند نكته كد رو با فكر كردن بفهمند ولي دوستان ديگه با اجرا جواب رو بدست ميارن و ...
اگر هم قصد داريد در مورد نكته كدها صحبت كنيد بهتره تاپيكي فرضا با عنوان نكته هايي در SQL Server درست كنيد و اين نكات رو اونجا قرار بديد تا ماهيت تاپيك حفظ بشه و كارايي تالار بالا بره.
ممنون از جناب یاراحمدی. نکته شما در معماهای بعدی رعایت خواهدشد.

Rejnev
یک شنبه 09 آبان 1389, 09:54 صبح
با اجازه
اينم ازون معماهاي جالب كه استاد سر كلاس به ما آموزش داد:
فرض كنيد جداول زير رو داريم:(دروس، روزهاي هفته و ترم)



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/forum/attachment.php?attachmentid=59356&stc=1&d=1288507238

راهنمايي:
از توابع هم بايد استفاده كنيد:لبخندساده:

(حاج حميد تازه ديدمت! تبريك :تشویق::لبخندساده:)

r00tkit
یک شنبه 09 آبان 1389, 10:42 صبح
سلام

منم با اینکه جواب با یه ctr+c ctr+v معلوم بشه مخالفم پست قبلیم رو هم به همین منظور زدم

با تشکر از اقای حیمدرضا صادقیان

Rejnev
دوشنبه 10 آبان 1389, 09:42 صبح
ويرايش شده براي پاسخ:
اينم پاسخ پست 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 نمره به پايان ترمم اضافه شد. مشكلي كه توي حلش داشتم اين بود كه نميدونستم بايد ديدم رو برعكس كنم. چون خروجي هاي اس كيو ال معمولا از چپ به راسته و اينجا از راست به چپ نمايش داديم كمي گيج شده بودم

مسئله بعدي نمايش جدول ليگ برتره! اگه تكراريه بگيد كه روش كار نكنم و برم بعدي

Rejnev
دوشنبه 10 آبان 1389, 15:58 عصر
ميخواهيم جدول ليگ فوتبال و يا هر ورزش ديگه اي رو توسط كوئري ها ايجاد كنيم
جداولي كه داريم به اين شكل خواهند بود:
------
جدول تيم:
-شماره
-نام تيم
------
جدول بازي ها:
-شماره تيم 1
-شماره تيم 2
-گل زده تيم 1
-گل زده تيم 2
-------------------------
*جدول ليگ رو به شكل زير ازين جداول بگيريد:

http://www.barnamenevis.org/forum/attachment.php?attachmentid=59452&stc=1&d=1288615747

Rejnev
چهارشنبه 12 آبان 1389, 17:14 عصر
خب دوستان بابت تاخير عذر ميخوام
و اما جواب (ظاهرا كسي حوصله حلش رو نداشته!) به هر حال.
view ها اينجا كاربردشون رو نشون ميدن.
فرض كنيد جدول ما داده هاي زير رو دارن:

http://www.barnamenevis.org/forum/attachment.php?attachmentid=59567&stc=1&d=1288792965


ما اگه يك ديد از جدول بالا به صورت زير داشته باشيم:

http://www.barnamenevis.org/forum/attachment.php?attachmentid=59568&stc=1&d=1288792965


كار كوئري گيري ازون بسيار راحت تر ميشه. ساختار جدول رو كه نميشه تفيير داد. پس مجبوريم يك 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/forum/attachment.php?attachmentid=59569&stc=1&d=1288792965

براي نمايش نام تيم هم كافيه يك جوين به جدول تيمها بزنيم
شايد شما از راههاي ديگه هم حلش كنيد. (اين راه حل قطعي نيست)

zizi_zizi69
چهارشنبه 12 آبان 1389, 21:37 عصر
سلام
امیدوارم همگی خوب باشید ،
این تاپیک توسط آقای صادقیان ایجاد شده،نمی دونم ما هم اجازه داریم معمای خودمان را در این تاپیک بزاریم در هر حال با اجازه ایشون،
حالا دو معما ساده ،
1.یک دستور row insertنوشتیم بعد قبل از اینکه این دستور را commitکنیم یک کاربر دیگه میاد select * می زنه تا داده های این جدول را ببیند ،آیا اون row درج شده توسط اون کاربر را می بینه؟

2.یک دستور insert row نوشتیم بعد قبل از اینکه این دستور را commitکنیم خود این کاربر میاد select * می زنه تا داده های این جدول را ببیند ،آیا قادر است اون row درج شده توسط خودش را ببیند؟

با توضیحات کامل لطفا

حمیدرضاصادقیان
چهارشنبه 12 آبان 1389, 21:53 عصر
سلام.ممنون از دوستان. عزیزانی که معما میخواهند مطرح کنند به صورت خصوصی برای من ارسال کنند تا پس از بررسی درج شود که خط مشی این تاپیک حفظ شده و بتوان نکات مثبتی را درآن درج نمود.
باتشکر

حمیدرضاصادقیان
چهارشنبه 12 آبان 1389, 22:07 عصر
1.یک دستور row insertنوشتیم بعد قبل از اینکه این دستور را commitکنیم یک کاربر دیگه میاد select * می زنه تا داده های این جدول را ببیند ،آیا اون row درج شده توسط اون کاربر را می بینه؟

2.یک دستور insert row نوشتیم بعد قبل از اینکه این دستور را commitکنیم خود این کاربر میاد select * می زنه تا داده های این جدول را ببیند ،آیا قادر است اون row درج شده توسط خودش را ببیند؟


اگر دستور commit نشده کاربر چی رو میخواد ببینه؟یا این هست که دستور اجرا شده و به صورت dirty page در log file وجود داره که در اونصورت با تغییر در select میتوان اونو دید.ولی اگر منظور این هست که دستور insert اصلا اجرا نشده!! ( که فکر نمیکنم اینطوری باشه) خیر در این صورت کاربر نمیتونه ببینه.

در مورد commit بیشتر توضیح بدین

zizi_zizi69
پنج شنبه 13 آبان 1389, 00:44 صبح
تا اونجا که من متوجه شدم commit شدن یک دستور یعنی دستور اجرا بشه و داده ها را در جداول database ثبت کنه،ولی تا زمانی که فقط دستورtransaction شده (begin tran)فقط در logfile موجوده،
پس در مورد اول چیزی نمی بینه چون تغییرات یک کاربر زمانی برای کاربر دیگه قابل رویت است که در دیتابیس ثبت شده باشه.
ولی در مورد دوم،چون کاربر با session مربوط به خودش داره کار می کنه حتی با شروع transaction قبل از commit داده ها را می بینه چون در logfile مربوطش هست؟!

حمیدرضاصادقیان
پنج شنبه 13 آبان 1389, 09:09 صبح
سلام.خیر به این صورت نیست. شما وقتی که یک دستور رو ثبت میکنید در log File ذخیره میشه و log file در بازه های زمانی خاصی با توجه به نوع Recovery Model دیتابیس اون دستورات رو در دیتابیس اضافه میکنه. وقتی که یک Transaction صورت میگیره اگر در بین اون Transaction باشه میتونه به وسیله استفاده از Dirty Page محتویات جدول رو ببینه.

zizi_zizi69
پنج شنبه 13 آبان 1389, 15:26 عصر
سلام.خیر به این صورت نیست. شما وقتی که یک دستور رو ثبت میکنید در log File ذخیره میشه و log file در بازه های زمانی خاصی با توجه به نوع Recovery Model دیتابیس اون دستورات رو در دیتابیس اضافه میکنه. وقتی که یک Transaction صورت میگیره اگر در بین اون Transaction باشه میتونه به وسیله استفاده از Dirty Page محتویات جدول رو ببینه.

در مورد ثبت مشكلي نيست يعني در هر صورت بايد در هارد ذخيره بشه حالا چه logfile چه database اصلي كه در هارد هست.
من منظورم قبل از commit هست يعني حين transaction هست.كه دستورات و داده ها در buffer ذخيره مي شند.چه data buffer cash باشه چه log buffer cash .يعني داده ها و دستورات در RAM هستند و هر يوزر براي خودش يك instance از ديتابيس داره.

حمیدرضاصادقیان
شنبه 15 آبان 1389, 07:53 صبح
در مورد ثبت مشكلي نيست يعني در هر صورت بايد در هارد ذخيره بشه حالا چه 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 رو به همون روشی که عرض کردم بخونه.
موفق باشید

odiseh
شنبه 15 آبان 1389, 10:42 صبح
سلام

جواب معما:

ديگران نمي تونند مقدار insert شده رو ببينند چون هنوز commit نشده
اما خود اون فرد اگه قبل از commit يه select بزنه، مي تونه ببينه

zizi_zizi69
شنبه 15 آبان 1389, 20:07 عصر
ما کلا یک Buffer داریم که اونهم به این صورت عمل میکنه که Page های فایل Data رو خوانده و در RAM نگهداری میکند . اونهم برای سرعت عمل بیشتر. اگر قرار باشه SQL Server برای نوشتن با RAM کار کنه که مشکل ساز خواهد شد. تمام عملیات نوشتن در فایل LOG ذخیره میشه و اگر Transaction کامل انجام بشه دستورات Commit شده و در فایل data نوشته می شوند در غیر اینصورت برگشت داده خواهند شد.
حالا شما وقتی دارید درون یک Transaction یک عملیاتی رو انجام میدید معمولا جدول Lock میشه (البته میتونید نوع قفل شدن رو نیز مشخص کنید) و در Select کردن کاربر میتونه Data رو به همون روشی که عرض کردم بخونه.
موفق باشید

ولی برای نوشتن از RAM هم استفاده میشه،پس وظیفه Database Writer process چیست؟
datafile ها که در RAM قرار دارند اگر تغییر کنند مگر در همون datafile ها update نمی شند و بعد توسط writer در database ذخیره میشند.
موردی که میزان Insert یا Update بیش از حجم Buffer ها تعریف شده باشه،درست، برای نوشتن یک راست میره سراغ hard،دستورات توسط log writer از Log Buffer بروی Log نوشته می شود،وما بدون اینکه داده ای در Database ذخیره شده باشد پیغام Commit Successfully را می بیینیم،بعد بمرور زمان اطلاعات روی دیتابیس ذخیره میشود یا Rollback میشند.

حمیدرضاصادقیان
یک شنبه 16 آبان 1389, 08:30 صبح
ولی برای نوشتن از 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://www.sql-server-performance.com/articles/dba/oracle_sql_server_comparison_ii_p1.aspx) هم توضیحاتشو ببینید

zizi_zizi69
دوشنبه 17 آبان 1389, 17:31 عصر
http://msdn.microsoft.com/en-us/library/aa337560(v=SQL.100).aspx

می تونید به من بگید dirty page ها چه هستند؟مگر همان داده موجود در بافر نیستند که update شده اند،یا فقط بعنوان تغییر یافته علامت گذاری شده اند؟مگر log در ابتدا در بافر ذخیره نمی شند؟
می تونید بیشتر توضیح بدید؟
من اصلا در مورد oracle صحبت نمی کنم!

aebrs@yahoo.com
جمعه 21 آبان 1389, 10:44 صبح
با سلام خدمات دوستان عزیز
در این موضوع خاص تا اینجا که نوشته شده بنظر میرسد که هر کدام از دوستان از یک منظر خاص به موضوع نگاه میکند و لذا آنچه دیگری مطرح میکند بنظر وی اشتباه میرسد:
1- دیدگاه اول تنها سمت سرور داده را مد نظر داشته و از آن جایگاه به آن نگاه میکند
2- دیدگاه دوم به نظر میرسد که از سمت کاربر و در رابط کاربر نگاه میکند که دارای Session بوده و مفهوم حافظه موقت سمت کاربر است جدا از آنکه داده به سمت SQL رفته باشد.
آیا این نظر درست است یا اشتباه است؟

حمیدرضاصادقیان
جمعه 21 آبان 1389, 11:20 صبح
دیدگاه اول تنها سمت سرور داده را مد نظر داشته و از آن جایگاه به آن نگاه میکند
2- دیدگاه دوم به نظر میرسد که از سمت کاربر و در رابط کاربر نگاه میکند که دارای Session بوده و مفهوم حافظه موقت سمت کاربر است جدا از آنکه داده به سمت SQL رفته باشد.
آیا این نظر درست است یا اشتباه است؟

اصلا دیدگاه سمت کلاینت معنا ندارد. SQL Server داده ها رو به سمت کلاینت cache نمیکنه. بلکه page های مورد نظر رو از هارد خونده و در RAM نگهداری میکند و در صورت نیاز کاربر نتیجه را به کاربر ارسال میکند.

zizi_zizi69
پنج شنبه 27 آبان 1389, 12:29 عصر
با تشکر از جناب صادقیان:
آیا این جمله درسته و مفهومش چیه؟


An instance can exist without a database

clearsky
پنج شنبه 27 آبان 1389, 21:51 عصر
چه تاپیکه باحالیه اینجا... میشه از اساتید 2 تا خواهش بکنم:
1- معما ها و سوال ها توسط یک نفر مطرح بشه ( مدیر تاپیک)و هر کسی که می خواد مساله طرح بکنه اونو واسه ایشون بفرسته.... اینجوری واسه کسائی که می خواند از این تاپیک استفاده کنند دنبال کردن مطالب راحتتر میشه
2-تستهای آزمونهای 70-433 و 70-432 هم مطرح و تحلیل بشند.

zizi_zizi69
شنبه 29 آبان 1389, 20:16 عصر
سلام
سوال:آیا یک instance می تونه بدون database موجودیت داشته باشه؟
بله می تونه،اول که sql رو Run می کنیم در واقع هیچ database رو باز نکردیم یا ایجاد نکردیم پس Instance ما بدون وجود database وجود داره.
روی این Instance باید یک دیتابیس قرار بگیره یا سوار بشه،تا داده های اون دیتابیس برای ما مفهوم پیدا کنه.درواقع Instance مجموعه ای از Memory و Processes های هست که داده های هارد را برای ما معنادار می کنه.
هر Instance فقط می تونه روی یک دیتابیس سوار بشه.
هدف من از طرح این سوالات بحث در مورد مفاهیم هست.
ولی استقبالی دیده نمی شه!

حمیدرضاصادقیان
یک شنبه 30 آبان 1389, 07:46 صبح
سلام.
دارم روی مباحثی کار میکنم انشالله به زودی این قسمت رو پربار خواهیم کرد.

حمیدرضاصادقیان
شنبه 25 دی 1389, 21:23 عصر
سلام.
انشالله دوباره این تاپیک رو فعل خواهیم کرد ولی با سوالات جالب و جدید.سعی می کنم سوالات امتحانات Microsoft هم بررسی کنیم.
خوب اینم برای شروع :
فرض کنید در یک جدول دو ستون داریم به نام Id و Description .
این جدول حاوی اطلاعات زیر می باشد :


Id Description
-------------------------------
1 Line1
2 Line2
3 Line3
...
1000 Line1000

حال می خواهیم اطلاعات رو به شکل زیر نمایش بدیم:


Description
--------------
Line1,Line2,Line3,Line4,....,Line1000

یک دستور بهینه و مناسب برای اینکار ارائه دهید.

raziee
شنبه 25 دی 1389, 22:01 عصر
یک دستور بهینه و مناسب برای اینکار ارائه دهید.

DECLARE @Descriptions ntext
SET @Descriptions = ''

SELECT @Descriptions = COALESCE(@Descriptions + ', ', '') + CAST([Description] AS nvarchar(50))
FROM [TableName]

SELECT @Descriptions

حمیدرضاصادقیان
شنبه 25 دی 1389, 23:19 عصر
ممنون از جواب. جواب صحیح هست.
البته بهتره به جای استفاده از ntext از nvarchar استفاده بشه تا Query بهینه تر باشه.چون این تعداد با nvarchar هم به راحتی جواب میده.ntext برای متون بزرگ هست که البته الان در نسخه های جدید دیگه ازش استفاده نمیشه و به جاش میشه از varbinary استفاده کرد.

Reza_Yarahmadi
یک شنبه 26 دی 1389, 16:20 عصر
تا جایی که میدونم دستور دوستمون فقط ساده ترین روش بود نه بهینه ترین!!:متفکر:
تنها نکته دستور استفاده از تابع COALESCE است که در اینجا برای هندل کردن مقدارهای NULL و ترفندی برای مدیریت کاماها به کار رفته ، فکر نمیکنم این تابع نسبت به تابع ISNULL از سرعت پردازش بالاتری برخوردار باشه. برای کاما هم میشه با استفاده از تابع Substring این موضوع رو درست کرد.
اگر دستور بالا رو بصورت زیر تغییر بدیم سرعت اجرایی بسیار بالاتری پیدا میکنه

DECLARE @Descriptions Nvarchar(max)
SET @Descriptions = ''

SELECT @Descriptions = (SELECT CAST([Description] AS Nvarchar) + ','
FROM [TableName]
FOR XML PATH(''))

SELECT @Descriptions

حمیدرضاصادقیان
یک شنبه 26 دی 1389, 22:54 عصر
فرض کنید جدولی داریم دارای چندین میلیون رکورد. نیاز داریم تعداد کل رکوردهای موجود در جدول را فراخوانی کنیم.
برای اینکار چه راهی پیشنهاد می دهید؟
نکته: جدول دارای Clustered Index نیز می باشد.

zizi_zizi69
دوشنبه 27 دی 1389, 17:53 عصر
سلام
سوال خیلی کلی بنظر میاد.چون دقیقا query مشخص نیست چیه ؟
بهترین گزینه برای بازیابی تعداد زیادی رکورد بشکل مرتب شده استفاده از clustered index هست.
چون ذکر شده clustered index داریم،Composite index بهترین حل از نظر من هست چون در اینصورت خود table به عنوان ساختار index در نظر گرفته میشود و حجم اضافه برای ذخیره ایندکس لااقل نداریم.:متفکر:

حمیدرضاصادقیان
دوشنبه 27 دی 1389, 23:05 عصر
منظور من این هست که میخواهیم ببینیم در یک جدول چند تا رکورد داریم.همین.

Rejnev
سه شنبه 28 دی 1389, 10:04 صبح
اگه ستونی که ایندکس گذاشتی بی همتا باشه بهتره count(FieldName) رو بنویسیم.
ولی اگه یونیک نباشه، خود sql تصمیم میگیره از کدوم ستون استفاده کنه و مینویسیم count(*)

zizi_zizi69
سه شنبه 28 دی 1389, 12:42 عصر
اول اینکه روی فیلدی که clustered index تعریف میشه حتما باید یونیک باشه.

وقتی count(*) مینویسیم خود optimizer تصمیم می گیره از کدام فیلد استفاده کنه ، باعث میشه scan روی جدول صورت بگیره که سربار زبادی داره.
ولی اگر count(clustered index) بنویسسیم مجبور می کنیم ازستون ایندکس برای شمارش استفاده می کنه، گویا اینجا هم باز scan انجام میشه و تفاوتی با مورد قبلی نداره.

ویا می تونیم از دستور زیر استفاده کنیم select count(*) from table with (index=index name) که من چندین مورد سعی کردم query خودم رو مجبود به استفاده از ایندکس بکنم ولی همیشه جوابگو نبوده و اصلا اجباری رو ایجاد نمی کنه و optimizer هر کاری رو صلاح بدونه انجام می ده.

بهترین حل استفاده از اطلاعات ذخیره شده در Sysindexes است.که دیگه table scan نداره.

tooraj_azizi_1035
سه شنبه 28 دی 1389, 15:19 عصر
سلام،


– Row Count without doing full table Scan
– This will include provide total number of rows in all partition (if table is partitioned)
SELECT
Total_Rows= SUM(st.row_count)
FROM
sys.dm_db_partition_stats st
WHERE
object_name(object_id) = ‘Your_Table_Name_Goes_Here’



AND (index_id < 2) – Only Heap or clustered index

حمیدرضاصادقیان
سه شنبه 28 دی 1389, 20:11 عصر
سلام.
دوستان جواب مناسبی ارائه ندادند.شما وقتیی که ایندکس دارید خود ایندکس تعداد رکوردهای جدول رو در جدول sys.sysindexes نگهداری میکنه.کافیه مقدار ستون rowcnt رو از این جدول بخونید.با این روش نیازی نیست که یک بار کل جدول scan بشه و سرعتش بسیار بالاتر از دستور Count هست. البته این دستور زمانی کاربرد داره که شما میخواهید تعداد رکوردهای کل جدول رو بدونید.

tooraj_azizi_1035
چهارشنبه 29 دی 1389, 10:02 صبح
نظرتان درباره کد پست شده چیست؟

حمیدرضاصادقیان
چهارشنبه 29 دی 1389, 19:34 عصر
کدی که شما ارسال کردید برای موقعی هست که از table partition استفاده کردیم.
درحالت عادی موردی که عرض کردم جواب سوال می باشد.

حمیدرضاصادقیان
چهارشنبه 29 دی 1389, 19:45 عصر
فرض کنید اطلاعاتی داریم که دارای یک رابطه درختی با هم هستند یعنی هر یک از این مجموعه اطلاعات یکی از گره های یک درخت هستند، برای پیاده سازی این موضوع جدولی با ساختار زیر طراحی کرده ایم


ID : int
Name : varchar(50)
ParentId : int

که در این ساختار گره های Root دارای ParentId = 0
و برای بقیه گره های فیلد ParentId برابر فیلد Id پدر خود هستند.

1 - دستوری بنویسید که با گرفتن Id یک گره اطلاعات تمام فرزندان اون گره رو نمایش بده
2 - دستوری بنویسید که با گرفتن Id یک گره اطلاعات تمام پدران اون گره رو نمایش بده

JavanSoft
سه شنبه 12 بهمن 1389, 23:14 عصر
فكر كنم از خاصيت formula با ارجاع بخ خود جدول بتوان حل نمود

NewLife2008
سه شنبه 19 بهمن 1389, 11:11 صبح
احتمالا راه حلی به جز استفاده از سلکتهای تو در تو و کرسر داره! اگه با دو مورد ذکر شده باشه که کار خاصی نداره!
مشتاقم راه حل بهتر رو ببینم.

Mahbod Rad
سه شنبه 19 بهمن 1389, 14:25 عصر
سلام
خدا قوت
میتونیم یک فاکنشن به صورت زیر ایجاد کنیم تا با ارسال سریال اصلی همه فرزندان آنرا نمایش دهد


CREATE FUNCTION [dbo].[Fn_AllSon] (@IdSi int)
RETURNS @RepTable TABLE(IdSon int)
AS
begin
insert into @RepTable(IdSon) values (@IdSi)
WHILE (exists (SELECT 1 from TableName where [Id] not in (select IdSon from @RepTable)
and ParentId in (select IdSon from @RepTable)))
insert @RepTable
select [Id] from TableName where [Id] not in (select IdSon from @RepTable)
and ParentId in (select IdSon from @RepTable)
Return
END

حمیدرضاصادقیان
چهارشنبه 20 بهمن 1389, 22:41 عصر
سلام.
من مدت طولانی صبر کردم ولی دوستان جواب مناسبی ارسال نکردند.
من جوابها رو قرار میدهم.
ابتدا رکوردهای زیر رو وارد میکنیم.



Create Table #Temp (
ID int NULL,
Name varchar(50) NULL,
ParentId int NULL
)
Insert Into #Temp Values(1,'AB1',0)
Insert Into #Temp Values(2,'AB2',0)
Insert Into #Temp Values(3,'CD1',1)
Insert Into #Temp Values(4,'CD2',1)
Insert Into #Temp Values(5,'CD3',1)
Insert Into #Temp Values(6,'EF1',2)
Insert Into #Temp Values(7,'GH1',3)
Insert Into #Temp Values(8,'GH2',5)
Insert Into #Temp Values(9,'IJ1',6)
Insert Into #Temp Values(10,'KL1',7)
Insert Into #Temp Values(11,'MN',10)
Insert Into #Temp Values(12,'OP',11)


جواب سوال 1 :



Declare @Id int
Set @Id = 1

;With RES as(
Select * From #Temp Where Id = @Id
UNION ALL
Select t.*
From #Temp T INNER JOIN RES R
On T.ParentID = R.ID
)
Select * From RES


جواب سوال 2 :



Declare @Id int
Set @Id = 7

;With RES as(
Select * From #Temp Where Id = @Id
UNION ALL
Select t.*
From #Temp T INNER JOIN RES R
On T.ID = R.ParentId
)
Select * From RES

mannai29
پنج شنبه 21 بهمن 1389, 09:41 صبح
سلام
البته اگه اشتباه نکنم این روش محدودیت تعدادی داره. یعنی چون از الگوریتم Recursive استفاده می کنه در بیشترین حالت 32767 رکورد رو برمی گردونه و اگه تعداد رابطه پدر و فرزندی بیشتر از این باشه , مشکل پیش می آد. اگرچه در مورد درخت به ندرت پیش می آد , اما به هر حال یک ریسک هست.
SQL Server 2008 help:
ms-help://MS.SQLCC.v10/MS.SQLSVR.v10.en/s10de_1devconc/html/4acf8a3e-6dcc-420c-9088-9c57b976113e.htm

Rejnev
پنج شنبه 21 بهمن 1389, 10:58 صبح
سلام
البته اگه اشتباه نکنم این روش محدودیت تعدادی داره. یعنی چون از الگوریتم Recursive استفاده می کنه در بیشترین حالت 32767 رکورد رو برمی گردونه و اگه تعداد رابطه پدر و فرزندی بیشتر از این باشه , مشکل پیش می آد. اگرچه در مورد درخت به ندرت پیش می آد , اما به هر حال یک ریسک هست.
SQL Server 2008 help:
ms-help://MS.SQLCC.v10/MS.SQLSVR.v10.en/s10de_1devconc/html/4acf8a3e-6dcc-420c-9088-9c57b976113e.htm
البته توي اين مثال هرگز چنين نميشه.
بفرض فاصله بين نسلها 1 سال باشه، ميشه شجره نامه 30 هزار ساله كه مشكلي پيش نمياره!

SaeidBehfar
دوشنبه 25 بهمن 1389, 10:16 صبح
سلام
با تشکر فراوان ن ن ن واقعا استفاده میکینیم
من معمای آخر و درباره ی ساختار درختی اجراش میکنم خطلای زیر و میده
Server: Msg 156, Level 15, State 1, Line 22
Incorrect syntax near the keyword 'With'.

حمیدرضاصادقیان
سه شنبه 09 آبان 1391, 10:54 صبح
سلام.
این تاپیک رو بالا آوردم تا دوباره معماهای جدید رو مطرح کنیم.

خوب برای شروع به سوال زیر پاسخ دهید.

دستورات زیر رو اجراکنید.

CREATE TABLE Employee
(
EmployeeID INT,
EmployeeName VARCHAR(30),
Country VARCHAR(20)
);

CREATE TABLE Orders
(
EmployeeId INT,
OrderId INT,
Price Money
);


INSERT INTO Employee
VALUES(1,'Martin','Canada'),
(2,'Jim','USA'),
(3,'Steve','Turkey');

INSERT INTO Orders
VALUES(1,1,10000),
(1,2,20000),
(1,3,54000),
(3,1,18700),
(3,2,9768),
(3,3,7577887);


خوب حالا ما میخواهیم لیست مشتریانی که فروش نداشتند و کشور آنها USA هست رو بدست بیاریم.
ابتدا دستور زیر رو اجرا میکنیم.

SELECT E.EmployeeId,E.EmployeeName,O.EmployeeId,o.OrderId ,o.Price
FROM Employee e
LEFT OUTER JOIN
Orders o
ON o.EmployeeId=E.EmployeeID
AND E.Country='USA'


ولی نتیجه دلخواه رو به مانمیده و جواب اشتباه برمیگردونه در صورتی که ما میتوانیم شرط رو در عبارت ON هم بنویسیم.
حال به شکل زیر دستورو مینویسیم.



SELECT E.EmployeeId,E.EmployeeName,O.EmployeeId,o.OrderId ,o.Price
FROM Employee e
LEFT OUTER JOIN
Orders o
ON o.EmployeeId=E.EmployeeID
Where E.Country='Usa'


الان مشتری شماره 2 را برمیگرداند.
چه تفاوتی بین نوشتن شرط در ON و Where هست؟
چرا با تغییر شرط نتیجه ما تغییر کرد؟

pashna
چهارشنبه 10 آبان 1391, 09:48 صبح
سلام،
دلیلش اینه که WHERE Clauseروی نتیجهٔ Join اجرا می‌شه یعنی‌ اول Join رو روی کلید انجام میده بعد نتیجهٔ حاصل رو طبق WHERE Clause محدود می‌کنه ولی‌ در ON Clause اینطور نیست.
It means ON Clause applies before JOIN but WHERE Clause applies on complete result so it removes all rows which are not in criteria.
PLEASE NOTE : There is no difference between WHERE Clause and ON Clause when used with INNER JOIN.

حمیدرضاصادقیان
چهارشنبه 10 آبان 1391, 21:48 عصر
ممنون توضیح شما درسته ولی کامل توضیح ندادین.
ببینید وقتی که دستورات Parse می شوند در Outer Join ابتدا به صورت یک Inner join عمل کرده و هردو جدول براساس قیدهایی که در On ذکر شده باهم Join می شوند و بعد از آن دوباره عمل Join با جدول فوق صورت میگیرد که سبب می شود رکوردهایی که الان در جدول اصلی نیست رو به صورت null به ما نشون میده و در واقع دوبار عمل join انجام میشه یک بار با استفاده از on یک بار بعد از اینکه جدول از on تشکیل شد. به همین خاطر باید در Outer Join شرط رو در where بنویسید تا نتیجه درست بگیرید ولی در Inner join چون یک بار عملیات تشکیل جدول مجازی صورت گرفته و دیگه join اضافی انجام نمی شود به همین خاطر در همون مرحله اولیه ON نیز بر روی جدول صورت میگیرد. به همین خاطر در Inner join تفاوتی نداره که شرط رو در on بنویسید یا در where.
دلیل کندی Outer join نسبت به Inner join نیز همین امر هست.

hramezani
دوشنبه 06 خرداد 1392, 16:33 عصر
سلام
کاش این تاپیک ادامه پیدا کنه ...
یه نکته ای رو خواستم بگم که به اصل نکته سوال کاری نداره , در مورد آخرین کوئری , شما فرموده بودین مشتریانی که فروش نداشتن , برای همین تو شرط where باید
and o.price is null رو هم اضافه کنیم
باز هم از ایجاد این تاپیک ممنون

pashna
جمعه 10 آبان 1392, 20:52 عصر
SELECT T.name AS TableName ,
P.rows
FROM sys.partitions AS P
INNER JOIN sys.tables AS T ON T.object_id = P.object_id
WHERE T.name = 'TableName'

JavadAmeri
سه شنبه 16 اردیبهشت 1393, 18:44 عصر
تو mysql کافیه یک select * بزنیم.بعدش با یک mysql_num_rows()
کار تمومه.:لبخند:

supporter
یک شنبه 19 اردیبهشت 1395, 23:47 عصر
سلام.
دوستان جواب مناسبی ارائه ندادند.شما وقتیی که ایندکس دارید خود ایندکس تعداد رکوردهای جدول رو در جدول sys.sysindexes نگهداری میکنه.کافیه مقدار ستون rowcnt رو از این جدول بخونید.با این روش نیازی نیست که یک بار کل جدول scan بشه و سرعتش بسیار بالاتر از دستور Count هست. البته این دستور زمانی کاربرد داره که شما میخواهید تعداد رکوردهای کل جدول رو بدونید.
آيا صحت اين عدد (در جدول sysindexe) منوط به Update بودن Statistic data ی مربوط به Index مربوط نيست؟

akpa125
یک شنبه 06 تیر 1395, 23:28 عصر
سلام ممنون از تایپیک جالبتون
در راه حل دوم جدول Employee به همراه تمام سفارشاتشون برمیگرده و سپس با شرط WHERE اون هایی که کشورشون USA هست فیلتر میشن
برای بررسی دستور اول ایتدا برای دستور زیر به همراه خروجیش رو بررسی میکنیم


SELECT E.EmployeeId,E.EmployeeName ,e.country,O.EmployeeId,o.OrderId,o.PriceFROM
Employee eLEFT OUTER JOINOrders oON o.EmployeeId=E.EmployeeID
+------------+--------------+---------+------------+---------+---------+
| EmployeeId | EmployeeName | country | EmployeeId | OrderId | Price |
+------------+--------------+---------+------------+---------+---------+
| 1 | Martin | Canada | 1 | 1 | 10000 |
| 1 | Martin | Canada | 1 | 2 | 20000 |
| 1 | Martin | Canada | 1 | 3 | 54000 |
| 2 | Jim | USA | NULL | NULL | NULL |
| 3 | Steve | Turkey | 3 | 1 | 18700 |
| 3 | Steve | Turkey | 3 | 2 | 9768 |
| 3 | Steve | Turkey | 3 | 3 | 7577887 |
+------------+--------------+---------+------------+---------+---------+

و دستور زیر

SELECT E.EmployeeId,E.EmployeeName,O.EmployeeId,o.OrderId ,o.PriceFROM Employee eLEFT OUTER JOINOrders oONo.EmployeeId=E.EmployeeIDAND E.Country='Canada'
+------------+--------------+------------+---------+-------+
| EmployeeId | EmployeeName | EmployeeId | OrderId | Price |
+------------+--------------+------------+---------+-------+
| 1 | Martin | 1 | 1 | 10000 |
| 1 | Martin | 1 | 2 | 20000 |
| 1 | Martin | 1 | 3 | 54000 |
| 2 | Jim | NULL | NULL | NULL |
| 3 | Steve | NULL | NULL | NULL |
+------------+--------------+------------+---------+-------+
در واقع میبینیم شرطon روی نوع تلفیق اثر گذار هست و چون تلیق خارجی هست ستون های جدول Employee در هر صورت بازگردانده میشن

gerdioz2018
پنج شنبه 24 خرداد 1397, 08:40 صبح
سلام
خطا میده
چون در این دستور وقتی پیوندی باشه امکان حذف نیست

mbsmbf
یک شنبه 05 خرداد 1398, 09:29 صبح
سلام میخواستم عدد صفر جز کوچکترین عدد حساب نشود
(5,8.0,33,45)math.min