PDA

View Full Version : سوال: با خصوصیت Identity برای افزاینده ی اتوماتیک کلید اصلی مشکل دارم



mirahsani
جمعه 19 آذر 1389, 22:59 عصر
سلام.
من در حال انجام یک پروژه با asp.net زبانc# میباشم.
در جداولم در sql server برای کلید اصلی خصوصیت Identity را فعال کردم تا به طور خودکار موقع ایجاد رکورد جدید یک واحد زیاد شود . اما مشکل من اینجاست:
فرض کنید 7 تا رکورد در یک جدول دارم و در نتیجه کلید اصلی به ترتیب مقادیر 1 تا 7 را داراست. وقتی طی فرایندی در اجرای برنامه چند تا رکورد حذف میشن مثلا فرض کنید رکوردهای 3و4و6 حذف میشن من دیگه تو فیلد کلید اصلیم این 3تا رکورد را ندارم و وقتی طی فرایندی دیگه میخوام رکوردهایی به این جدول اضافه کنم خصوصیت Identity که کلید اصلی را به طور اتوماتیک اضافه می کرد ادامه کار را از شماره 8 ادامه می دهد. بدون توجه به این که من رکورد های 3و4و6 را ندارم. در واقع من می خوام این شماره رکوردهای حذف شده اول پر بشن بعد بقیه.
چون این بی نظمی تو فراخوانیهای بعدی برنامم مشکل ایجاد می کنه و پروژمو خراب میکنه.
تورو خدا هر چیزی به ذهنتون میرسه بگید. خیلی لنگم.(حتی اگه میشه این مشکلو از توی visual studio حل کنم راه حلشو بگید)
یه دنیا 3پاس.

Rezahak
جمعه 19 آذر 1389, 23:07 عصر
دوست عزیز فکر می کنم هدف شما از بکاربردن فیلد از نوع autonumber نگهداری ردیف هر رکورد می باشد اگر این طور است کاملا در اشتباهید چون کاربرد این نوع فیلد این نیست اگر می خواهید برای هر رکورد شماره ردیف داشته باشید بهتر است به طور دستی آنرا handle کنید

mirahsani
جمعه 19 آذر 1389, 23:14 عصر
دوست عزیز فکر می کنم هدف شما از بکاربردن فیلد از نوع autonumber نگهداری ردیف هر رکورد می باشد اگر این طور است کاملا در اشتباهید چون کاربرد این نوع فیلد این نیست اگر می خواهید برای هر رکورد شماره ردیف داشته باشید بهتر است به طور دستی آنرا handle کنید

ممنون از پاسختون ولی مثلا کسی که می خواد در سایت ثیت نام کنه آیا خودش باید شماره رکوردشو وارد کنه؟ یا خود برنامه باید این کارو بکنه؟ این ID منه بیشتر موقع ها on هستم. اگه خواستید گفتگو کنیم:okrandeman

Rezahak
جمعه 19 آذر 1389, 23:20 عصر
این ID منه بیشتر موقع ها on هستم. اگه خواستید گفتگو کنیم:okrandeman
دوست عزیز من ترجیح می دم گفتگوها از طریق همین فروم انجام بشه تا هم برای بقیه دوستان با مشکلات مشابه جنبه آموزشی داشته باشه و هم سایر صاحب نظرین مطالب را اصلاح و تایید نمایند .
اما درخصوص پست قبلی خودم آنرا این طور تکمیل می کنم که یک دستور به شکل زیر برای برگرداندن و یا تغییر آخرین seed فیلدهای identity وجوددارد ولی سعی کن خودت را درگیرش نکنی چون بعد handle کردن دستی راحتتر خواهد بود :

DBCC CHECKIDENT
(
table_name
[ , { NORESEED | { RESEED [ , new_reseed_value ] } } ]
)
[ WITH NO_INFOMSGS ]

Rezahak
جمعه 19 آذر 1389, 23:23 عصر
در خصوص این که یک کاربر در سایت ثبت نام کند شماره رکورد یا ID فقط این کاربرد را خواهد داشت که در جدول کاربران شما یکتا باشد و به عنوان primary key در سایر جداولی که با آن ارتباط دارد استفاده شود حالا می خواهد پشت سر هم باشد یا گپ داشته باشد!!!!

mirahsani
جمعه 19 آذر 1389, 23:31 عصر
دوست عزیز من ترجیح می دم گفتگوها از طریق همین فروم انجام بشه تا هم برای بقیه دوستان با مشکلات مشابه جنبه آموزشی داشته باشه و هم سایر صاحب نظرین مطالب را اصلاح و تایید نمایند .
اما درخصوص پست قبلی خودم آنرا این طور تکمیل می کنم که یک دستور به شکل زیر برای برگرداندن و یا تغییر آخرین seed فیلدهای identity وجوددارد ولی سعی کن خودت را درگیرش نکنی چون بعد handle کردن دستی راحتتر خواهد بود :

DBCC CHECKIDENT
(
table_name
[ , { NORESEED | { RESEED [ , new_reseed_value ] } } ]
)
[ WITH NO_INFOMSGS ]

دوست عزیزم این کد که نوشتی چجوری و کجا ازش استفاده کنم؟
بلد نیستم! درضمن این رکوردا تو برنامم حتما باید پشت سر هم باشه وگرنه تو یه بخش دیگه error میگیرم.

Rezahak
جمعه 19 آذر 1389, 23:39 عصر
این کد نیست شکل کلی دستور هست برای مطالعه بیشتر لینک MSDN را هم می گذارم :
http://msdn.microsoft.com/en-us/library/ms176057.aspx

chasbonakam
جمعه 19 آذر 1389, 23:57 عصر
فکر نکنم این مشکل رو تو sql بتونی حل کنی

بهتره که خودت دستی بهش مقدار بدی

البته این نکته رو هم یاد اور بشم که اگر sql شماره رکورد هایی رو که پاک کردی به رکورد جدیدی که درج می کنی نسبت نمیده ، مطمئننا یه دلیل عقلانی پشتش خوابیده

در هر صورت موفق باشی

حمیدرضاصادقیان
شنبه 20 آذر 1389, 06:54 صبح
فکر نکنم این مشکل رو تو sql بتونی حل کنی

تونستنش که میتونند حل کنند. یک راهش این هست که هر بار رکوردی حذف میشه شماره identity ها ریست بشه. که به شخصه این راه رو پیشنهاد نمیدم چون یک عمل اضافی روی دیتابیس داره انجام میشه.
مناسبترین راه برای شما این هست که از حالت Identityخارج کنید و هربار که میخواهید مقدار جدیدی درج کنید با استفاده از تابع max آخرین مقدار فیلد رو خوانده یک واحد بهش اضافه کرده و در دیتابیس اضافه کنید. که این کارو هم میتونید با استفاده از یک تابع انجام بدید.
توجه : البته در این حالت هم اگر از بین رکوردها کاربر بیاد رکوردی رو حذف کنه بازهم Gap ایجاد میشه.در این حالت شما باید بیای ابتدا در اون تابع دنبال مقادیر خالی بگردی و هرکاربر جدیدی که ثبت نام میکنه از اون مقادیر خالی بهش نسبت بدی.
موفق باشید

tooraj_azizi_1035
شنبه 20 آذر 1389, 10:32 صبح
سلام،
تو این لینک مایکروسافت به این نکته در قالب یک کادر زرد رنگ اشاره کرده: http://msdn.microsoft.com/en-us/library/ms191131(v=SQL.100).aspx
http://i.msdn.microsoft.com/Hash/030c41d9079671d09a62d8e2c1db6973.gif
:قلب: Note
If an identifier column exists for a table that has frequent deletions, gaps can occur between identity values. Deleted identity values are not reused. To avoid such gaps, do not use the IDENTITY property. Instead, you can create a trigger that determines a new identifier value, based on existing values in the identifier column, as rows are inserted.


همانطوری که می بینید پیشنهاد می شه که این کار به یک Trigger سپرده بشه. این کار به همون روشی که جناب صادقیان گفتند یعنی یافتن Max و اضافه کردن 1 به اون می تونه انجام بشه.

mbasirati
شنبه 20 آذر 1389, 21:58 عصر
سلام
با اجازه اساتید
به نظر من یه کاری میشه کرد فقط یه کم کار میبره
فرض کنید جدولی که شما درموردش صحبت میکنید اسمش a باشه. شما ابتدا یه جدول به نام b با یه فیلد ایجاد کنید. بعد یه تریگر after delete‌برای جدول a بنویسید که موقع حذف مقدار فیلد identity‌ رو توی جدول b درج کنه. بعد هروقت که میخواید یه رکورد تو جدول a درج کنید اول برید سراغ جدول b و ببینید اگه رکوردی توش هست اول خصوصیت identity‌ جدول a رو off‌کنید و بعد مقدار معادل در جدول b رو توی فیلد‌identity‌جدول a درج کنید. و دوباره خصوصیت identity رو on کنید و بعد رکورد موردنظر تو جدول b‌رو پاک کنید. امیدوارم متوجه شده باشید.
برای on و off کردن خصوصیت identity میتونید از تابع SET IDENTITY_INSERT استفاده کنید.
موفق باشید

حمیدرضاصادقیان
یک شنبه 21 آذر 1389, 07:49 صبح
سلام
با اجازه اساتید
به نظر من یه کاری میشه کرد فقط یه کم کار میبره
فرض کنید جدولی که شما درموردش صحبت میکنید اسمش a باشه. شما ابتدا یه جدول به نام b با یه فیلد ایجاد کنید. بعد یه تریگر after delete‌برای جدول a بنویسید که موقع حذف مقدار فیلد identity‌ رو توی جدول b درج کنه. بعد هروقت که میخواید یه رکورد تو جدول a درج کنید اول برید سراغ جدول b و ببینید اگه رکوردی توش هست اول خصوصیت identity‌ جدول a رو off‌کنید و بعد مقدار معادل در جدول b رو توی فیلد‌identity‌جدول a درج کنید. و دوباره خصوصیت identity رو on کنید و بعد رکورد موردنظر تو جدول b‌رو پاک کنید. امیدوارم متوجه شده باشید.
برای on و off کردن خصوصیت identity میتونید از تابع SET IDENTITY_INSERT استفاده کنید.
موفق باشید

خوب اینکار سربار زیادی روی کار شما داره.
شما فرض کنید روی برنامه شبکه 10 تا کاربر دارند با همین جدول شما کار میکنند با این کار میدونید چقدر زمان Lock کردن جدول افزایش پیدا خواهد کرد؟
به جزاین شما دارید یک عمل insert,Select رو اضافه انجام میدید. که میتونید اینکارو با تبدیل فیلد به یک فیلد عددی معمولی و استفاده از یک تابع حل کنید.