PDA

View Full Version : گفتگو: تغییر در کلید اصلی در جدول دیتابیس



ordebehesht
چهارشنبه 14 فروردین 1392, 23:54 عصر
با سلام نمیدونم تا بحال با این مشکل برخوردین یا نه سوال من اینه ما جدولی داریم که شامل تعداد 1000 تا سطر که شماره از 1 تا 1000 گرفته حال ما میخوایم یک یا چند سطر رو از وسط حذف کنیم به نظر شما راهکاری برای این که شماره سطور ما مرتب باشه بعد حدف چیه به شکل ساده تر می پرسم سر 100 رو خدف میکنیم حال میخوایم سرطر 101 به بعد یک واخد کم بشن تا 100 رو به بعد مرتب بشه
بارها پرسیده شده جوابی نگرفتیم دوستان اگه راهکاری با نمونه کدی دارین ممنون میشم

ordebehesht
پنج شنبه 15 فروردین 1392, 11:59 صبح
یعنی کسی راه حای نداره ایده نداره

tooraj_azizi_1035
پنج شنبه 15 فروردین 1392, 12:31 عصر
شما باید Renumber کنید:

WITH UpdateCTE
AS
(SELECT item_no,
ROW_NUMBER() OVER(ORDER BY item_no) AS new_value
FROM WO_Items)
UPDATE UpdateCTE
SET item_no = new_value;

khokhan
پنج شنبه 15 فروردین 1392, 12:34 عصر
یعنی کسی راه حای نداره ایده نداره

درود بر شما

اگه منظور دیتابیس sql باشه با استفاده از دستور RESEED می تونین ستون Identity رو مجبور کنین که دوباره از 0 شروع به شماره گذاری کنه


DBCC CHECKIDENT('Tablename', RESEED, 0)


منبع :
http://blog.sqlauthority.com/2007/03/15/sql-server-dbcc-reseed-table-identity-value-reset-table-identity/


http://msdn.microsoft.com/en-us/library/aa258817%28v=sql.80%29.aspx

veniz2008
پنج شنبه 15 فروردین 1392, 12:46 عصر
سلام.
معمولا چنین شماره گذاری در جدول ها کاربرد نداره. ما داخل جدول اگر چنین فیلدی مثلا از 1 تا 1000 داشته باشیم حکم کلید رو داره که ممکنه در جداول دیگه استفاده شده باشه پس تغییر این مقدار کار صحیحی نیست. ولی اگر به شماره نیاز دارید بهترین راه اینه که در هنگام ایجاد کوئری با استفاده از تابع Row_Number یا Rank برای هر رکورد یک عدد ایجاد کنید. مثلا وقتی همه رکوردها وجود داره از شماره 1 تا 1000 ایجاد میشه. حالا اگه 100 یا هر عدد دیگه ای رو حذف کنید از 1 تا 999 براتون ایجاد میکنه. اگر بیشتر درباره اون فیلد توضیح بدید که چه کاری شما نجام میده و اصلا چرا میخواید چنین عمل حذفی رو انجام بدید، بهتر میشه راهنمایی کرد.

khokhan
پنج شنبه 15 فروردین 1392, 12:53 عصر
سلام.
معمولا چنین شماره گذاری در جدول ها کاربرد نداره. ما داخل جدول اگر چنین فیلدی مثلا از 1 تا 1000 داشته باشیم حکم کلید رو داره که ممکنه در جداول دیگه استفاده شده باشه پس تغییر این مقدار کار صحیحی نیست. ولی اگر به شماره نیاز دارید بهترین راه اینه که در هنگام ایجاد کوئری با استفاده از تابع Row_Number یا Rank برای هر رکورد یک عدد ایجاد کنید. مثلا وقتی همه رکوردها وجود داره از شماره 1 تا 1000 ایجاد میشه. حالا اگه 100 یا هر عدد دیگه ای رو حذف کنید از 1 تا 999 براتون ایجاد میکنه. اگر بیشتر درباره اون فیلد توضیح بدید که چه کاری شما نجام میده و اصلا چرا میخواید چنین عمل حذفی رو انجام بدید، بهتر میشه راهنمایی کرد.

با سلام

به نظر می رسه هدف دوستمون فقط جنبه شماره ردیف باشه نه استفاده به عنوان کلید اصلی و ............

veniz2008
پنج شنبه 15 فروردین 1392, 13:13 عصر
با سلام

به نظر می رسه هدف دوستمون فقط جنبه شماره ردیف باشه نه استفاده به عنوان کلید اصلی و ............
اگر هدفشون همین چیزی باشه که شما گفتید بهترین راه همون ایجاد شماره ردیف با Row_Number یا Rank در هنگام ایجاد کوئری هست و نیازی به ایجاد یک فیلد جداگانه برای این کار نیست و اگر اون فیلد کلید باشه باز هم تغییر در اون فیلد به هیچ عنوان صحیح به نظر نمیرسه(معمولا کلید رو دست نمیزنن. به همون دلیلی که در بالا گفتم). پس بهترین راه در هر دو حالت استفاده از متدهای ذکر شده برای تولید ردیف در هنگام کوئری هست.
موفق باشید.

mohammad kafiyan
پنج شنبه 15 فروردین 1392, 13:13 عصر
من هم همین مشکل را دارم ولی چگونه

به نظر می رسه هدف دوستمون فقط جنبه شماره ردیف باشه

DBCC CHECKIDENT('Tablename', RESEED, 0)

WITH UpdateCTE
AS
(SELECT item_no,
ROW_NUMBER() OVER(ORDER BY item_no) AS new_value
FROM WO_Items)
UPDATE UpdateCTE
SET item_no = new_value;


از این کده در کدام قسمت از sql باید استفاده کنم من از stroredprocdure استفاده می کنم

ordebehesht
پنج شنبه 15 فروردین 1392, 13:14 عصر
درسته پروژم بایگانی نامها تو اداره هستش که شماره نامه صرفا فقط شماره نامه هستن نه چیزه دیگه ممنون میشم توضیحاتتون طوری باشه که تو خود سی شارپ کد نویسی بشه

در ضمن بگم آشنایی به storeprocedure ندارم یعنی استفاده نمیکنم

khokhan
پنج شنبه 15 فروردین 1392, 13:26 عصر
من هم همین مشکل را دارم ولی چگونه



از این کده در کدام قسمت از sql باید استفاده کنم من از stroredprocdure استفاده می کنم
فکر کنم منظورتون یه همچی چیزی باشه

http://go4answers.webhost4life.com/Example/update-question-57972.aspx

tooraj_azizi_1035
پنج شنبه 15 فروردین 1392, 13:36 عصر
معمولا چنین شماره گذاری در جدول ها کاربرد نداره.
کاربرد داره.


ما داخل جدول اگر چنین فیلدی مثلا از 1 تا 1000 داشته باشیم حکم کلید رو داره که ممکنه در جداول دیگه استفاده شده باشه پس تغییر این مقدار کار صحیحی نیست.

اگه اینطوری باشه که نباید هیچوقت یک فیلد که کلید اصلی هست رو به روز کرد.


ولی اگر به شماره نیاز دارید بهترین راه اینه ....
بهترین نیست یک راه ممکن است.

veniz2008
پنج شنبه 15 فروردین 1392, 15:01 عصر
کاربرد داره.
نگفتم اصلا کاربرد نداره، گفتم معمولا کاربرد نداره. ولی اگه میتونید موردی رو مثال بزنید که نشه هنگام ایجاد کوئری براش ردیف ایجاد کرد.


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

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

tooraj_azizi_1035
پنج شنبه 15 فروردین 1392, 17:26 عصر
نگفتم اصلا کاربرد نداره، گفتم معمولا کاربرد نداره. ولی اگه میتونید موردی رو مثال بزنید که نشه هنگام ایجاد کوئری براش ردیف ایجاد کرد.
مثال بالا رو ندیدید؟


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



خوشحال میشم راه بهتری رو یاد بگیرم
راه بهتر رو اول گفتم.


من قصد جر و بحث ندارم. شما روی چیزی اصرار می کنید که از نظر شما درسته!

veniz2008
پنج شنبه 15 فروردین 1392, 17:50 عصر
مثال بالا رو ندیدید؟
حرف آخر شما رو اول مینویسم تا مطمئن بشید که منم قصد جر و بحث و لجبازی رو ندارم.(این کار مال بچه کوچولو هاست).
همه بحث ما سر همینه که من میگم چنین پیاده سازی اشتباه هست. یه فیلدی رو فقط به عنوان شماره ردیف در نظر بگیریم و بعدش مرتبا بخوایم اونو دستخوش تغییرات کنیم. چرا باید چنین هزینه ای رو مرتبا به سیستم تحمیل کنیم؟

منظور شما رو کاملاً متوجه شدم. با این جمله شما دیگه هیچ کسی نباید ستونی رو که به عنوان کلید اصلی در نظر گرفته بروز کنه!باز که حرف خودتون رو میزنید. من گفتم اگر اشتباه تایپی در فیلد کلید باشه بایستی تصحیح بشه ولی مثال دوستمون چه ربطی به اشتباه تایپی داره؟
در مثال دوستمون(اگر 1000 رکورد داشته باشیم)، یک حذف باعث تغییر در سلسله رکوردهای بعد از اون میشه. کافیه 200 رو حذف کنه اونوقت باید 201 تا 1000 رو تصحیح کنیم. این کار به نظر من اشتباهه.


راه بهتر رو اول گفتم.شما میای یه Row_Number میسازی و بعد به مقدار فعلی فیلد نسبتش میدی. خوب دستور شما علاوه بر Row_Number یه عمل آپدیت هم انجام میده در صورتیکه من میگم فقط یه Row_Number کافیه. کدومشون بهینه تره؟ فرض رو بر 1 میلیون رکورد بگیر دوست من.

tooraj_azizi_1035
پنج شنبه 15 فروردین 1392, 18:08 عصر
پاسخی که در بالا دادم به این شرط بود که همیشه بخواهیم شماره گذریمان از 1 شروع شود.
اما در مورد چیزی مثل سند حسابداری تصور من این هست که باید از جایی که شکاف بوجود اومده به بعد رو Renumber کرد. مثلاً اگه سند 10 حذف بشه باید 11 به بعد رو Renumberکرد.
اما اگه سندهای شماره 1 تا 10 حذف شدند اسناد 11 الی آخر نباید دستخوش تغییر قرار بگیرند. (نمی دانم در واقعیت اینطور هست یا خیر)
در چنین سناریویی RowNumber درست نیست بلکه باید به روز کرد. نظر شما چیست؟

veniz2008
پنج شنبه 15 فروردین 1392, 18:24 عصر
پاسخی که در بالا دادم به این شرط بود که همیشه بخواهیم شماره گذریمان از 1 شروع شود.
فرض رو بر شرط شما استوار میکنیم. من باز هم درک نمیکنم چرا باید چنین فیلدی رو در نظر بگیریم. آیا منطقی هست برای جدولی که بالای 500 هزار رکورد داره، دوباره Renumber کرد؟. این عمل آپدیت چه مزیت و حسنی داره؟. تاره من ارتباطی برای این فیلد با فیلدهای جداول دیگه در نظر نگرفتم (کلید خارجی باشه).

اما در مورد چیزی مثل سند حسابداری تصور من این هست که باید از جایی که شکاف بوجود اومده به بعد رو Renumber کرد. مثلاً اگه سند 10 حذف بشه باید 11 به بعد رو Renumberکرد.
در چنین سناریویی RowNumber درست نیست بلکه باید به روز کرد. نظر شما چیست؟من خیلی با اصول حسابداری آشنا نیستم ولی از گفته شما میخوام نکته ای رو بیرون بکشم. خوب این کار چه فرقی با Renumber کردن داره؟. شاید منظورتون وارد نشدن سربار اضافی بخاطر رکوردهای قبل از نقطه شکاف هستش!.(مثلا با 1 میلیون رکورد شماره 500 هزار رو حذف کنیم. منطقی نیست که 499999 رکورد قبلی رو دوباره شماره گذاری کرد. چراکه نیازی به چنین تغییری نیست چون خودش مرتبه).
سوال بعدی اینه که سندی که شماره میخوره چه اصراری بر تغییر شماره سند هست؟

Mahmoud.Afrad
پنج شنبه 15 فروردین 1392, 18:32 عصر
به نظر میرسه شماره نامه حکم شناسایی اون نامه هست و نباید شماره ها رو تغییر داد.
اصلا چه نیازیه که به ترتیب پشت سر هم باشند؟
در سیستم بایگانی اگر سطری حذف نشه بهتره(اسمش روشه تا جای ممکن اطلاعات بایگانی نباید حذف بشن). میتونید یک فیلد از نوع bit به جدول اضافه کنید با مقدار true برای نامه ها. اگر هم نیاز به حذف بود به جای حذف از جدول ، کافیه اون بیت را false کرد و این بیت را در کوئری ها دخیل کرد.

khokhan
پنج شنبه 15 فروردین 1392, 19:08 عصر
به نظر میرسه شماره نامه حکم شناسایی اون نامه هست و نباید شماره ها رو تغییر داد.
اصلا چه نیازیه که به ترتیب پشت سر هم باشند؟
در سیستم بایگانی اگر سطری حذف نشه بهتره(اسمش روشه تا جای ممکن اطلاعات بایگانی نباید حذف بشن). میتونید یک فیلد از نوع bit به جدول اضافه کنید با مقدار true برای نامه ها. اگر هم نیاز به حذف بود به جای حذف از جدول ، کافیه اون بیت را false کرد و این بیت را در کوئری ها دخیل کرد.

با سلام

دستتون درد نکنه آقا محمود شدیدا با نظرتون موافقم اصول کار همینه که شما فرمودید . حکما هرکاری بایستی با روال منطقی انجام پذیرد :چشمک:

ordebehesht
پنج شنبه 15 فروردین 1392, 21:01 عصر
مرسی از اینکه میحواین منطق کار رو برام تشریح کنین ولی فرض کنیم لازم بشه یک نامه رو حذف کنین اونوقت چه

tooraj_azizi_1035
پنج شنبه 15 فروردین 1392, 21:07 عصر
ته مانده مغزم:
باید هر رویکردی که نیاز شما رو برآورده می کنه رو بررسی کنید یعنی هزینه تحمیلی اون رو به سیستم بسنجید.
اغلب Update زیاد روی ستونی که Clustered Index هست خوشایند نیست چون Performance Impact رو به همراه داره. Page Split، جا به جائی صفحات اندیس و افزایش خواندن های فیزیکی و منطقی پیامدهای Update مکرر است. باید از این موضوع در صورت ممکن اجتناب کنید.

veniz2008
پنج شنبه 15 فروردین 1392, 21:20 عصر
ته مانده مغزم:
باید هر رویکردی که نیاز شما رو برآورده می کنه رو بررسی کنید یعنی هزینه تحمیلی اون رو به سیستم بسنجید.
اغلب Update زیاد روی ستونی که Clustered Index هست خوشایند نیست چون Performance Impact رو به همراه داره. Page Split، جا به جائی صفحات اندیس و افزایش خواندن های فیزیکی و منطقی پیامدهای Update مکرر است. باید از این موضوع در صورت ممکن اجتناب کنید.
حالا شد.
منم حرفم همینه چنین فیلدی با این رویکرد، قرار گرفتنش در جدول اشتباهه چون با هر حذف، منابع زیادی رو از سیستم برای مرتب سازی دوباره باید اختصاص داد.
ولی اگر قرار بر بودن چنین فیلدی هست یا طبق گفته دوستمون آقا محمود عمل کنید یا بعد از حذف، مرتب سازی رو انجام ندید و در کوئری که مینویسید واسه هر رکورد یه ردیف بذارید.

ordebehesht
پنج شنبه 15 فروردین 1392, 21:52 عصر
حالا که بحث به هزینه تحمیلی برای بروز کردن رسیده وقتی مبخوایم از یک ردیف 24 فیلدی(مثلا) 4 تا بروز کنیم همه بروز میشن هزینه تحمیلی اینجا که بیشتره یا اونجا حداقل کاری میکنه اینجا که نمیکنه اشتباه میگم بگین

اما در مورد سوال بالا هزینه کم برابر با بی محتوا بودن هرچند من جواب نگرفتم و ذکر کردنم با منطق کاری ندارم و واردم به منطق ممنون از دوستان در کل خیلی راهنمایی شدم و ایده های جدید گرفتم

veniz2008
پنج شنبه 15 فروردین 1392, 22:15 عصر
حالا که بحث به هزینه تحمیلی برای بروز کردن رسیده وقتی مبخوایم از یک ردیف 24 فیلدی(مثلا) 4 تا بروز کنیم همه بروز میشن هزینه تحمیلی اینجا که بیشتره یا اونجا حداقل کاری میکنه اینجا که نمیکنه اشتباه میگم بگین
از اون 24 فیلد، اگر 4 فیلد رو ذکر کنید خوب همون 4 فیلد ویرایش میشن نه تمام فیلدها. در مثال شما بحث بر سر یک رکورد نیست. اگر یک رکورد حذف بشه، تمام رکوردهای بعدی(تا آخرین رکورد) فیلد ردیفشون باید تصحیح بشه یا دوباره از اولین رکورد ReNumber کنیم که چون رکوردهای زیادی رو باید تصحیح کنیم هزینه زیادی رو متحمل میشیم. مخصوصا اگر اون فیلد کلید هم باشه در اونصورت clusterd index هم هست و هزینه این جابه جایی ها بیشتر هم خواهد بود.


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

tooraj_azizi_1035
جمعه 16 فروردین 1392, 19:42 عصر
این دیگه واقعاً آخرین جوابمه:بامزه::
امروز متوجه شدم که Microsoft در SQL Server 2012 شیئی به نام Sequence Object رو اضافه کرده که بر خلاف ستون Identity فقط خاص یک جدول نیست.
بر خلاف ستون های Identity که وقتی ردیف به جدول اضافه می شود تولید می شوند Application ها می توانند از تایع NEXT VALUE FOR برای گرفتن مقدار جدید استفاده کنند.

یک Sequence Object که از 1 شروع می شود و 1 واحد 1 واحد به آن افزوده می شود:

ALTER SEQUENCE dbo.CustomerSequence RESTART WITH 1 ;

UPDATE dbo.Customer SET CustomerID=NEXT VALUE FOR dbo.CustomerSequence



منبع: http://msdn.microsoft.com/en-us/library/ff878091.aspx