PDA

View Full Version : autonumber



linux
یک شنبه 14 خرداد 1385, 01:28 صبح
یک فیلدی بصورت autonumber هست برنامه با ado.net 2 کار می کنه
بعضی از وقتها کاربران رکوردی را می خواهند ایجاد کنند و اشتباده می کنند و این رکورد را پاک می کنند این autonumber به هم می خورده یعنی
رکورد اول مقدار autonumber را 1 ست می کند
رکورد دوم باید 2 باشد ولی 3 ثبت می کند
چطور می توان کاری کرد که این درست شود؟

AminSobati
یک شنبه 14 خرداد 1385, 02:20 صبح
دوست عزیزم،
نکته اول این که Identity برای ارائه ترتیب نیست، بلکه صرفا یک راه آسان برای تولید اعداد یونیک هستش. از اونجاییکه بعضی رکوردها ممکنه حذف بشن، شما انتظار پر شدن این فضاهای خالی رو نباید داشته باشید. وقتی در گزارش نیاز به ارائه شماره ردیف دارید، با شیوه های ابتکاری در Query گرفتن میتونین یک ستون بعنوان شماره سطر ایجاد کنید. البته در SQL Server 2005 امکانات جالبی برای این کار وجود داره.
در مورد اینکه چرا بلافاصله بعد از عدد 1، عدد 2 تولید نمیشه این هست که وقتی یکی از اعداد، اصطلاحا "دست خورده" بشه، دوباره مورد استفاده قرار نمیگیره. مثلا یک کاربر رکورد جدید وارد میکنه. باید عدد 2 براش بدست بیاد. اما این رکورد به جهت مغایرت با یک Constraint در جدول پذیرفته نمیشه و Transaction بلافاصله Rollback میشه. اینجا عدد 2 دست خورده شده و اگر همین رکورد دوباره قصد ورود داشته باشه، عدد 3 رو هم دست خورده میکنه و عدد بعدی 4 خواهد بود.
دیدن DBCC CHECKIDENT خالی از لطف نیست!

linux
یک شنبه 14 خرداد 1385, 11:40 صبح
توی access با کامپک و ریپر کردن فایل این مشکلات حل می شه آیا تو sql 2000 راهی برای این کار هست؟

AminSobati
یک شنبه 14 خرداد 1385, 12:31 عصر
کدوم مشکل؟ چیزی که میفرمایید در منطق SQL Server مشکل محسوب نمیشه. در حقیقت این مشکل Access هستش که امکان انجام Queryهای خاص رو نداره و شما مجبورید همون ترتیبی که در دیتابیس دارید رو به User نشون بدین. اما در SQL Server به دلیل قابلیتهای بیشتر، حتی بدون وجود ترتیب خاص (یا فیلد Auto Number) در جدول میتونین یک فیلد ردیف (یا شماره سطر) ایجاد کنید و به کاربر نمایش بدین. همونطور که در پست قبلی اشاره شد، فلسفه فیلد Identity یا Auto Number، نمایش ترتیب به کاربر نیست. از دید یک SQL Server Developer، اگر بعد از شماره 1، رکورد بعدی شماره 200 بگیره هیچ اشکالی رخ نداده.

linux
یک شنبه 14 خرداد 1385, 15:18 عصر
منم از اتونامبر برای نمایش ردیف به کاربر استفاده نمی کنم برای کدگذاری و identity استفاده می کنم ولی کاربر این را زیاد حالیش نیست ببینید یک جدول داریم که مشتری ها را تعریف می کنیم ، کاربر دوست داره کدمشتری ها همه به ترتیب باشه این کد باید یونیک باشه منم هم از اتو نامبر استفاده کردم حالا این وسط چندتا رکورد را دستزدند!
از نظر من هم زیاد مهم نیست ولی اونها اینچزها حالیشون نیست

AminSobati
یک شنبه 14 خرداد 1385, 18:42 عصر
راه حل ساده ای وجود نداره. خودتون باید Max بگیرید و یکی بهش اضافه کنید تا ID رکورد جدید بدست بیاد. وقتی رکوردی حذف میشه، ID رو باید ذخیره کنید تا برای یک رکورد جدید، این ID رو اختصاص بدین تا Gap رو پر کنه.
اما اجازه بدین بررسی کنیم ببینیم اگر SQL Server می خواست مثل Access این Gapها رو پر کنه (مثلا Compact and Repair) چه اشکالی پیش میامد:
فرض کنید جدول مشتریهای شما 1000 مشتری داره و ID از یک تا 1000 رفته. هر مشتری میتونه چندین سفارش داشته باشه که در جدول Orders ثبت میشه. یعنی CustomerID در جدول Orders هم شرکت داره. اگر هر مشتری به طور متوسط 5 سفارش داشته باشه، حدودا 5000 سفارش وجود داره. حالا مشتری شماره 2 رو حذف میکنیم، و بعدش Repair انجام میدیم. اینجا CustomerID شماره 3 باید به 2 تبدیل بشه. لذا در جدول Orders هم همه 3 ها به 2 باید تبدیل بشن. اما شما 998 مشتری بعد از 2 دارید که همگی باید یکی ازشون کم بشه:
998*5= 4990
4990 رکورد در Orders باید Update بشن و 998 رکورد در Customers:
4990+998= 5988
پس میبینیم که با یک تغییر کوچک حدودا 6000 عمل Update نیازه. تازه صرف نظر از اینکه هر عمل Update ممکنه باعث اجرای Triggerها بشه و این یعنی یک Cost قابل توجه!
مثال من برای مقیاس خیلی کوچک بود. با توجه به اینکه SQL Server برای مقیاسهای چند ترابایتی هم کاربرد داره، لذا حتی تصور مکانیزمی برای Auto Number مشابه Access نمیشه داشت! Access برای بانکهای سبک پیشنهاد میشه. در SQL Server بهترین روش برای هدف شما چیزیه که ابتدا عرض کردم. خودتون Max بگیرید...
اما مراقب بحث همزمانیه کاربرها باشید، چون ممکنه دو کاربر همزمان IDهای یکسان تولید کنند که این مشکل با رعایت Isolation Levelها به خوبی قابل حله.

hmm
یک شنبه 14 خرداد 1385, 19:46 عصر
امین جان تا جایی که میدونم فیلدهای autonumber در اکسس هم در موقع Repair یا Compact فضای خالی رو پر نمیکنن.

AminSobati
دوشنبه 15 خرداد 1385, 00:00 صبح
من در مورد Access اطلاعی ندارم. عطف به فرمایش دوستمون نظر دادم:

توی access با کامپک و ریپر کردن فایل این مشکلات حل می شه آیا تو sql 2000 راهی برای این کار هست؟

Omid Rekabsaz
دوشنبه 15 خرداد 1385, 13:54 عصر
در طراحی یک جدول از دو روش می توان استفاده نمود ...
1 - PK تجاری
2 - PK غیر تجاری
هر کدام از این دو روش مزایا و معایب خود را دارند که روش دوم به روش اول ترجیح داده می شود...
زمان که PK غیرتجاری است شما معمولا از فیلد غیرتجاری ID بصورت AutoIncrement استفاده می نمایید... در این صورت کاربر نهایی به هیچ وجه با این فیلد ID نباید در ارتباط باشد... در فیلد های تجاری به هیچ وجه نباید از ویژگی Identity استفاده نمود...

linux
سه شنبه 16 خرداد 1385, 10:04 صبح
راه حل ساده ای وجود نداره. خودتون باید Max بگیرید و یکی بهش اضافه کنید تا ID رکورد جدید بدست بیاد. وقتی رکوردی حذف میشه، ID رو باید ذخیره کنید تا برای یک رکورد جدید، این ID رو اختصاص بدین تا Gap رو پر کنه.
اما اجازه بدین بررسی کنیم ببینیم اگر SQL Server می خواست مثل Access این Gapها رو پر کنه (مثلا Compact and Repair) چه اشکالی پیش میامد:
فرض کنید جدول مشتریهای شما 1000 مشتری داره و ID از یک تا 1000 رفته. هر مشتری میتونه چندین سفارش داشته باشه که در جدول Orders ثبت میشه. یعنی CustomerID در جدول Orders هم شرکت داره. اگر هر مشتری به طور متوسط 5 سفارش داشته باشه، حدودا 5000 سفارش وجود داره. حالا مشتری شماره 2 رو حذف میکنیم، و بعدش Repair انجام میدیم. اینجا CustomerID شماره 3 باید به 2 تبدیل بشه. لذا در جدول Orders هم همه 3 ها به 2 باید تبدیل بشن. اما شما 998 مشتری بعد از 2 دارید که همگی باید یکی ازشون کم بشه:
998*5= 4990
4990 رکورد در Orders باید Update بشن و 998 رکورد در Customers:
4990+998= 5988
پس میبینیم که با یک تغییر کوچک حدودا 6000 عمل Update نیازه. تازه صرف نظر از اینکه هر عمل Update ممکنه باعث اجرای Triggerها بشه و این یعنی یک Cost قابل توجه!
مثال من برای مقیاس خیلی کوچک بود. با توجه به اینکه SQL Server برای مقیاسهای چند ترابایتی هم کاربرد داره، لذا حتی تصور مکانیزمی برای Auto Number مشابه Access نمیشه داشت! Access برای بانکهای سبک پیشنهاد میشه. در SQL Server بهترین روش برای هدف شما چیزیه که ابتدا عرض کردم. خودتون Max بگیرید...
اما مراقب بحث همزمانیه کاربرها باشید، چون ممکنه دو کاربر همزمان IDهای یکسان تولید کنند که این مشکل با رعایت Isolation Levelها به خوبی قابل حله.
من این روش را استفاده نکردم منظور از max و ایسولیشن... اگر مثالی بگید ممنون می شم

AminSobati
چهارشنبه 17 خرداد 1385, 12:17 عصر
SELECT Max(MyColumn) FROM MyTable
مبحث Isolation Levelها بسیار مفصله، باید در Books Online مطالعه بفرمایید