# پایگاه‌های داده > SQL Server > T-SQL > تحلیل و طراحی بانک اطلاعات >  100  میلیارد ریال بدهی رو در چه DataType ای میشه ذخیره کرد؟

## Developer Programmer

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

نگران اینم که چنین عدد بزرگی در SQL server 2008 تولید خطا کنه... کسی میدونه با چه Data Type ای باید در SQL  و  VB.NET کار کنم ؟

----------


## حمیدرضاصادقیان

سلام.
شما میتوانید از نوع bigint استفاده کنید.




> کاربر ممکنه حتی تا 100 میلیارد ریال بدهی داشته باشه


آقا برنامه چی هست؟؟

----------


## Galawij

نوع داده (تعداد ارقام اعشار عدد,تعداد کلی ارقام عدد) Decimal را استفاده کنید.
برای مورد شما (Decimal(12,0 جواب می ده.

----------


## vcldeveloper

> شما میتوانید از نوع bigint استفاده کنید.





> نوع داده (تعداد ارقام اعشار عدد,تعداد کلی ارقام عدد) Decimal را استفاده کنید.


برای مقادیر مالی هیچ وقت نباید از نوع داده های عادی مثل انواع داده های Decimal یا Integer استفاده کنید!




> کسی میدونه با چه Data Type ای باید در SQL  و  VB.NET کار کنم ؟


100 میلیارد ریال یک عدد 12 رقمی هست، نوع داده money در SQL Server که مخصوص نگهداری مقادیر مالی هست، میتونه تا 15 رقم صحیح با معنی، و 4 رقم اعشاری رو با دقت یک هزارم واحد پول مورد نظرت، برات نگهداری کنه. از اون استفاده کن.

در ضمن، اسم اون فرد با بدهی 100 میلیاردی رو هم بده به این گروه مبارزه با مفاسد اقتصادی، مژدگانی دریافت کن  :چشمک:

----------


## حمیدرضاصادقیان

> برای مقادیر مالی هیچ وقت نباید از نوع داده های عادی مثل انواع داده های Decimal یا Integer استفاده کنید!


البته این حرف به هیچ وجه صحیح نیست. با یک جستجوی کوچک در اینترنت متوجه خواهید شد.
در اینجا آقای Joe Celko نویسنده کتابهای معروف SQL Server پیشنهاد می کنند که بهتره از نوع Decimal استفاده کنید.

----------


## Developer Programmer

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

----------


## Open-Source

> برای مقادیر مالی هیچ وقت نباید از نوع داده های عادی مثل انواع داده های Decimal یا Integer استفاده کنید!
> 
> 
> 100 میلیارد ریال یک عدد 12 رقمی هست،* نوع داده money در SQL Server که مخصوص نگهداری مقادیر مالی هست*، میتونه تا 15 رقم صحیح با معنی، و 4 رقم اعشاری رو با دقت یک هزارم واحد پول مورد نظرت، برات نگهداری کنه. از اون استفاده کن.
> 
> در ضمن، اسم اون فرد با بدهی 100 میلیاردی رو هم بده به این گروه مبارزه با مفاسد اقتصادی، مژدگانی دریافت کن


این حرفتون درسته ولی نه برای پول ایران.(واحد پول ایران ریال هستش و چیزی مثل ۱٫۵ ریال نداریم) ، چون مقادیر پول ایران صحیح هستش.
از این داده برای مبالغی مثل دلار استفاده میشه که مقدار اعشاری هم دارند(۱٫۵ دلار داریم).

من خودم همیشه از  bigint استفاده میکنم(فکر کنم تا ۱۶−۱۷ رقم رو جواب میده) ، یعنی ممکنه به مشکل بخورم؟؟!!!


راستی اگه ۴ تا صفر از جلوی پول بردارن ممکنه واحد هایی مثل درهم دوباره استفاده بشه ، اون موقع میشه از money استفاده کرد.(چون مبالغ اعشاری داریم) :لبخند گشاده!:

----------


## حمیدرضاصادقیان

البته با توجه به لینکی که در پست 5 دادم بهتره از نوع Decimal استفاده کنید. اگر فعلا به همین صورت بمونه با Bigint مشکل حل خواهد شد و نیازی به استفاده از Decimal نمی باشد.
ولی اگر بحث حذف 4 صفر عملی شود باید به سمت Decimal روی آورد. همچنین نمونه Script در همون لینک هست که دقت Decimal نسبت به Money رو در قسمت اعشاری بررسی میکنه.

----------


## vcldeveloper

> در اینجا آقای Joe Celko نویسنده کتابهای معروف SQL Server پیشنهاد می کنند که بهتره از نوع Decimal استفاده کنید.


اگر همون مطلبی که بهش لینک دادید رو با دقت می خواندید، میدید که اون فرد گفته:

1- MONEY is proprietary and will not port.
2- but you need to check with the
accounting department about the precision and scale

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





> این حرفتون درسته ولی نه برای پول ایران.(واحد پول ایران ریال هستش و چیزی مثل ۱٫۵ ریال نداریم) ، چون مقادیر پول ایران صحیح هستش.
> از این داده برای مبالغی مثل دلار استفاده میشه که مقدار اعشاری هم دارند(۱٫۵ دلار داریم).


همچنان باید از نوع داده Currency استفاده کنید، چون در صورت استفاده از اون نوع داده، در صورتی که یک واحد پولی خاص به طور رسمی پشتیبانی بشه، یا تغییراتی در اون واحد پولی بوجود بیاد، توسعه دهندگان SQL Server مسئول پیاده سازی جزئیات مربوطه هستند، و شما به عنوان کاربر SQL Server تا زمانی که فیلدتان Currency هست، نباید دغدغه چگونگی پیاده سازی آن را داشته باشید. البته بماند که اگر فردا به هر دلیلی بخواید همین نرم افزارتان را برای سایر واحد های پولی توسعه بدید (مثلا بخواید اون رو به مشتری خارجی بفروشید، یا مشتری ایرانی شما نیاز به ثبت معاملات ارزی داشته باشه)، با مشکل مواجه میشید!

روش های من در آوردی مثل توصیه های ارائه شده در این تاپیک، باعث میشه که هزینه و مدت زمان توسعه نرم افزار شما افزایش پیدا کنه، و نرم افزار شما هم قابلیت تطبیق با شرایط مختلف کاربر رو از دست بده. مثل همون استفاده از string با طول ثابت برای نگهداری تاریخ در بانک اطلاعاتی، به جای استفاده از نوع داده Date که بعدا در صورت تغییر بازار هدف، یا لزوم پشتیبانی از چند سیستم تاریخ، باید کلی از بخش های برنامه تغییر کنه! در حالی که در صورت استفاده از فیلد داده با نوع مناسب، همچین حالتی پیش نمیامد.

----------


## حمیدرضاصادقیان

بهتره قبل از اظهار نظر کردن های صریح و اینکه راهکارهای دوستان من درآوردی قلمداد بشه متن زیر رو با دقت مطالعه کنید.
کلاً Data Type Money اصلاً از نظر طراحان دیتابیس پیشنهاد نمیشه به دلایل زیر که عرض خواهم کرد و منبعش رو هم اعلام میکنم که دوستان بتونند به صورت حرفه ای! در مورد چیزی تصمیم بگیرند.

نوع داده Money دارای 4 رقم اعشار ثابت که 8 بایت نیز حافظه اشغال میکند. این نوع تایپ برمبنای تایپ Integer هست با یک مقدار اعشاری.( محدوده رنج نوع SmallMoney از 214748.3648- تا 214748.3647 می باشد و محدوده اعداد Integer از 2147483648- تا 2147483647 است)
اولین ایراد وارد شده به مقادیر Money این هست که شما هنگام ذخیره سازی میتوانید با واحدهای مختلف پولی آنرا ذخیره کنید ولی در دیتابیس هیچکدام از این مقدارها باهم تفاوت ندارند و معلوم نیست به چه واحدی ذخیره شده اند.
به این مثال توجه کنید:

CREATE TABLE Dbo.TestMoney
(
    MoneyValue MONEY    
)
GO
INSERT INTO Dbo.testMoney
VALUES($100)
INSERT INTO dbo.testMoney
VALUES(100)
INSERT INTO dbo.TestMoney
VALUES(£100)
GO

SELECT * FROM dbo.testMoney
GO


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



> Moneyvalue
> -------------
> 100.00
> 100.00
> 100.00


خوب حالا بریم سر دومین ایراد وارد شده این نوع داده.
در محاسبات اعداد رو Round میکند.
وقتی در نتیجه اعداد به صورت بینابین ظاهر می شوند آنها رو Round میکند .
به مثال زیر توجه کنید.


DECLARE @Money1 Money,@Money2 MONEY
SET @Money1=1.00
SET @Money2=800.00

SELECT CAST(@Money1/@money2 AS MONEY)

--Result = 0.0012


--Try the following code
DECLARE @Decimal1 DECIMAL(19,4),@Decimal2 DECIMAL(19,4)

SET @Decimal1 =1.00
SET @Decimal2 =800.00
SELECT CAST(@Decimal1/@Decimal2 AS DECIMAL(19,4))

--Result = 0.0013


در اینجا Query اول نتیجه 0.0012 رو برمیگردونه در صورتی که در نوع دوم نتیجه 0.0013 برگردانده میشود. حالا دستورات زیر رو اجرا کنید.


SELECT @Money1/@Money2

--Result = 0.0012

SELECT @Decimal1/@Decimal2

--Result = 00.0012500000000000000


مشکل اینجاست که چون Money بر مبنای نوع integer هست و فقط اعشار به آن اضافه شده ، مقادیر اعشاری بالای 4 رقم رو Round میکند. که در مثال سوم کاملا قابل درک هست.

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



> The common consensus among database architects is to
> avoid the money datatype and use a numeric type instead, because of the following reasons:
> • It gives the answers to math problems in the natural manner that’s expected.
> • It has no built-in units to confuse matters.
> Even in the previous version of SQL Server, the following statement was included in the monetary
> data section: “If a greater number of decimal places are required, use the decimal datatype
> instead.” Using a decimal type instead gives you the precision needed. To replicate the range for
> money, use DECIMAL(19,4), or for smallmoney, use DECIMAL (10,4). However, you needn’t use such
> large values if you don’t need them. Otherwise, if you happen to be calculating the national debt or
> ...


امیدوارم دوستان با خواندن این مطالب بتونن حرفه ای! تصمیم بگیرند.
نکته آخر اینکه شایعه شده که ممکنه این نوع داده در مدل های جدید SQL Server دیگه پشتیبانی نشه.



> مثل همون استفاده از string با طول ثابت برای نگهداری تاریخ در بانک  اطلاعاتی، به جای استفاده از نوع داده Date که بعدا در صورت تغییر بازار  هدف، یا لزوم پشتیبانی از چند سیستم تاریخ، باید کلی از بخش های برنامه  تغییر کنه!


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

موفق باشید.

----------


## vcldeveloper

> اولین ایراد وارد شده به مقادیر Money این هست که شما هنگام ذخیره سازی  میتوانید با واحدهای مختلف پولی آنرا ذخیره کنید ولی در دیتابیس هیچکدام از  این مقدارها باهم تفاوت ندارند و معلوم نیست به چه واحدی ذخیره شده اند.


این مشکل ربطی به یک نوع داده خاص نداره، مقادیر مربوطه چه در فیلد از نوع Money، و چه در فیلد از نوع Decimal یا Integer که ذخیره بشند، مشکل پا بر جا ست، پس این ایراد از نوع داده Money نیست.




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


بله، باید هم اون کار رو بکنه؛ چون اولا فیلد Money فقط و فقط برای محاسبات مالی طراحی شده، نه محاسبات اعشاری با دقت بالاتر از چهار رقم اعشار؛ و ثانیا، عمل گردن کردن در این نوع داده با توجه به استانداردهای رایج حسابداری انجام میشه. ایراد شما وقتی منطقی بود که یکی برای نگهداری نتیجه یک محاسبه ریاضی پیچیده، نوع داده Money رو پیشنهاد می کرد! این ایراد شما مثل این هست که یکی بگه، از نوع داده Integer برای نگهداری اعداد صحیح استفاده نکنید، و به جاش از varchar استفاده کنید (!!) چون در varchar میشه علاوه بر عدد، کارکترهای حرفی را هم ذخیره کرد! 




> Row Compression Effect:
> The money types are simply integer types with their decimal places shifted. As such, they are
> compressed in the same manner that integer types would be. However, since the values would
> be larger than they appear (because of the value 10 being stored as 10.000, or 10000 in the
> physical storage), the compression would be less than for an integer of the same magnitude.


میمونه این بخش از مطلب نقل قول شده ...
اینجا هم داره میگه نوع داده Money مثل نوع داده Integer به صورت فشرده شده در بانک ذخیره میشه، ولی از اونجایی که هر مقدار در فیلد Money همیشه 4 رقم اضافی برای اعشار داره، میزان فشرده سازی داده از نوع Money کمتر از فشرده سازی داده معمولی Integer هست؛ که اساسا ربطی به بحث نداره، و قیاس بین Integer و Money هست.




> الزامی نداره وقتی شما تاریخ رو به صورت فارسی میخواهید ذخیره کنید بیاید یک بار یک عمل تبدیل انجام بدید.
> لزوما ارائه یک قالب کلی برای همه شرایط مناسب نخواهد بود.بهتره تصمیم گیری ها برمبنای شرایط موجود و مقداری *آینده نگری* گرفته بشه.


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

----------


## حمیدرضاصادقیان

لطفا اگر مطلبی رو می نویسید مقداری دقت کنید.



> این مشکل ربطی به یک نوع داده خاص نداره، مقادیر مربوطه چه در فیلد از نوع  Money، و چه در فیلد از نوع Decimal یا Integer که ذخیره بشند، مشکل پا بر  جا ست، پس این ایراد از نوع داده Money نیست.


از کی تاحالا میشه در نوع داده integer  یا decimal با علامت $ یا علامت £ ذخیره کرد؟؟؟ پس این ایراد ربطی به انواع دیگه نداره و فقط در money هست.




> ر این نوع داده با توجه به استانداردهای رایج حسابداری انجام میشه


ببخشید کدوم استاندارد!!!همینجوری که نمیشه گفته های خودمون رو استاندارد تلقی کنیم.!




> ایراد شما وقتی منطقی بود که یکی برای نگهداری نتیجه یک محاسبه ریاضی پیچیده، نوع داده Money رو پیشنهاد می کرد!


این ایراد رو من نگرفتم. چون اساسا با این نوع داده اصلا کار نمیکنم. این ایراد رو بزرگان طراحی دیتابیس و برنامه نویسان حرفه ای TSQL وارد کردند.



> این ایراد شما مثل این هست که یکی بگه، از نوع داده Integer برای نگهداری  اعداد صحیح استفاده نکنید، و به جاش از varchar استفاده کنید (!!) چون در  varchar میشه علاوه بر عدد، کارکترهای حرفی را هم ذخیره کرد!


این مورد اصلا ربطی به گفته من نداره.من دارم دقت محاسبات رو بررسی میکنم نه اینکه بگم کاراکترهای بیشتری میتوان داخل متغیر ذخیره کرد. پس این مقایسه اساسا غلطه.




> اینجا هم داره میگه نوع داده Money مثل نوع داده Integer به صورت فشرده شده  در بانک ذخیره میشه، ولی از اونجایی که هر مقدار در فیلد Money همیشه 4  رقم اضافی برای اعشار داره، میزان فشرده سازی داده از نوع Money کمتر از  فشرده سازی داده معمولی Integer هست؛ که اساسا ربطی به بحث نداره، و قیاس  بین Integer و Money هست.


ربطش به بحث در اینجاست که زمانی که شما دیتا رو در هارد ذخیره سازی میکنید در page ها ذخیره میشه. و هر فیلدی جایگاه خاص خودش رو داره. و هنگام خواندن اطلاعات از Page ها همین خواندن و نوشتن در سرعت واکشی اطلاعات شما تاثیر داره. 

نکته آخری که در این تاپیک عرض خواهم کرد و دیگر ادامه نخواهم داد( چون ظاهرا داره به کل کل بیهوده شبیه میشه تا یک بحث علمی)
در انتخاب فیلدها و نوع آن ها باید دقت به خرج داد. اگر مواردی از قبیل سرعت خواندن اطلاعات ، Import/Export کردن داده ها، سرعت محاسبات ، دقت محاسبات براتون مهمه باید مقداری روی این موارد حساسیت بیش از حد به خرج داد و طبق نظر بزرگان این علم پیش رفت نه اینکه طبق دانسته های خودمون بخواهیم به خودمون بقبولونیم که حرف مادرسته و مابقی اشتباه میکنند.
تا زمانی که فکر کنیم همه چیز رو میدونیم ، هیچ وقت دانش ما بروز نخواهد شد و اطلاعات اشتباهی که گاها کسب میکنیم اصلاح نخواهد شد.
موفق باشید/.

----------


## tooraj_azizi_1035

با سلام خدمت همه اساتید
از توضیحاتتان مطالب جدیدی یادگرفتیم که جای تشکر دارد،
دوست ما در نظر دارد بدهی 1 میلیاردی را ذخیره کند و به احتمال خیلی زیاد نیازی به کار با اعشار ندارد. هر دوی نوع های Bigint و Money هشت بایت فضا اشغال می کنند. می توانیم احتمال بدهیم که SQL Server در کار با مقادیر اعشاری نسبت به صحیح مقداری سربار را تحمل می کند مخصوصاً در عملیات جستجو که مقایسه دو مقداری اعشاری باعث درگیر شدن واحد پردازشگر اعشاری می شود که باید فقط در صورت لزوم از آن استفاده کرد.
به استناد این دلایل نوع داده ای Bigint را پیشنهاد می دهم در صورت ایراد داشتن این پیشنهاد با ذکر منبع من را هم در یادگیری کمک کنید. :قلب:

----------


## m_omrani

شماها چرا این طوری با هم صحبت می کنید. نمی تونین خیلی راحت و با رعایت احترام همدیگه صحبت کنید؟ انگار همش می خواید از هم مچ گیری کنید، نادانی همدیگه رو به رخ هم بکشید، به هم کنایه بزنید. این با اخلاق علمی سازگار نیست، ولو این که آدم خدای علم هم باشه، اگه چنین خصلت هایی داشته باشه، به هر حال بازنده است.

من شخصاً اطلاعات زیادی درباره نوع داده money و currency ندارم. شاید یک بار هم ازشون استفاده نکرده باشم. اما این بحث برام جالب اومد.

سوالی که به هر حال می شه پرسید اینه که پس به هر حال نوع داده money به چه دردی می خوره؟ بالاخره هر نوع داده ای برای یه کاربردی به درد می خوره دیگه. می شه چند مثال از کاربرد این نوع داده بزنید. یا شایدم هیچ کاربردی نداره و به هیچ دردی نمی خوره؟

چیزی که من بعد از یه کمی چرخ زدن تو اینترنت فهمیدم اینه که *این نوع داده به هر حال از سرعت بالاتری برخورداره و performance بهتری می ده*. و اگه محاسبات ما عمدتاً به جمع و تفریق و ضرب مربوط بشه (نه تقسیم که باعث ایجاد اعداد اعشاری می شه) و اگه اعداد ما عمدتاً صحیح باشن و ارقام اعشاری نداشته باشیم این نوع داده بهتره.

استدعا دارم این قسمت از صحبتم رو با دقت بخونید.

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

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

من فکر می کنم اساساً خود وجود چنین دیتا تایپی (money) روشن کننده واقعیته. این نوع داده اختصاصاً برای کار با مقادیر پول ساخته شده. چون حیطه کاربردش یه چیز خاصه و محاسبات خاصی داره که به اون دقت بسیار زیاد محاسبات علمی اعداد اعشاری نیازی نیست.

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

----------


## حمیدرضاصادقیان

> شماها چرا این طوری با هم صحبت می کنید. نمی تونین خیلی راحت و با رعایت  احترام همدیگه صحبت کنید؟ انگار همش می خواید از هم مچ گیری کنید، نادانی  همدیگه رو به رخ هم بکشید، به هم کنایه بزنید. این با اخلاق علمی سازگار  نیست، ولو این که آدم خدای علم هم باشه، اگه چنین خصلت هایی داشته باشه، به  هر حال بازنده است.


من شخصا از تمام عزیزان که این بحث رو مطالعه کردن بابت رفتار تند عذرخواهی میکنم.




> چیزی که من بعد از یه کمی چرخ زدن تو اینترنت فهمیدم اینه که *این نوع داده به هر حال از سرعت بالاتری برخورداره و performance بهتری می ده*.


این موردی که شما میفرمائید زمانی کاربرد داره که بخواهیم اطلاعات رو به داخل OLAP اضافه کنیم که اینجا این مورد کمک میکنه.

درموارد دیگه که فرمودید این داده نیز ماننده دادهای image,Text ظاهرا قراره در نسخه های بعدی پشتیبانی نشه. اینم صحبتی هست که اکثر طراحان و نویسندگان مطرح SQL Server دارن درموردش صحبت میکنند.نمونش رو هم با ذکر منبع درج کردم.
روی همین حساب بهتره به نوع Decimal روی آورد.

من هم پیشنهادم نوع داده Bigint بود چون در کشور ما اعداد اعشاری برای سیستمهای مالی بی معنی است. در خارج از کشور چون با سنت نیز سرو کار دارند قاعدتا باید اعشاری هم داشته باشه.
درکشور ماهم اگر واقعا 4 صفر از پول حذف شود ، ماهم نیاز به اعشاری داریم که واحد Bigint کارساز نخواهد بود و بهترین گزینه همون واحد Decimal می باشد.
دلایل برتری این واحد هم در بالا به صورت کامل در چند پست با ذکر مثال عرض کردم.

----------


## vcldeveloper

> از کی تاحالا میشه در نوع داده integer  یا decimal با علامت $ یا علامت £  ذخیره کرد؟؟؟ پس این ایراد ربطی به انواع دیگه نداره و فقط در money هست.


نوع داده money در هنگام ورود داده، علائم پولی را skip میکنه. به این دلیل این علائم رو قبول میکنه که در اکثر موارد کاربر مقادیر مالی خودش را با یکی از همین علائم به بانک ارسال میکنه. این فقط یک اقدام تسهیل کننده هست، و همانطور که در پست قبلی هم گفتم، از این لحاظ، نوع های داده عددی همگی به یک صورت عمل می کنند، و وظیفه طراح بانک هست که واحد پولی را در طراحی فیلدهایش لحاظ کنه.




> این ایراد رو من نگرفتم. چون اساسا با این نوع داده اصلا کار نمیکنم. این  ایراد رو بزرگان طراحی دیتابیس و برنامه نویسان حرفه ای TSQL وارد کردند.


خوبه که آدم وقتی یک مطلب علمی رو مطالعه میکنه، به استناداتش هم توجه کنه و همینطوری هر چیزی رو قبول نکنه؛ شما دو مورد نقل قول ارائه کردید، در هر دو مورد هم نویسندگان مدنظر شما، دلایلی برای عدم استفاده از money ذکر کردند، ولی هیچکدام از اون دلایل عمومیت نداشت؛ مثلا یکی عنوان کرد که نوع داده money اختصاصا برای SQL Server هست، در حالی که در پیش فرض مورد نظر اون مطلب، portability مهم بود. یکی دیگه عنوان کرد که نوع money میتونه فشردگی کمتری نسبت به integer داشته باشه، که اساسا با بحث شما درباره Decimal ارتباطی نداشت، و الی آخر. هر وقت تونستید شرایط مد نظرتون رو با شرایط مندرج در اون نوشته ها انطباق بدید، اون وقت می تونید به اون نوشته ها استناد کنید، نه اینکه به صرف گفتن یک فرد، خارج از context ایی که اون حرف گفته شده، اون حرف رو به عنوان شاخص مطرح کنید.




> این مورد اصلا ربطی به گفته من نداره.من دارم دقت محاسبات رو بررسی میکنم  نه اینکه بگم کاراکترهای بیشتری میتوان داخل متغیر ذخیره کرد. پس این  مقایسه اساسا غلطه.


اتفاقا دقیقا به همون دلیلی که این مطلب رو نوشتید، قیاس صحیحی هست! چون شما مدعی شدید که Money دقت محاسبه کمتری از Decimal داره؛ من هم توضیح دادم که دقت محاسباتی Money برای محاسبات مالی کافی هست، و نیازی به دقت بالاتر در محاسبات نداره، و اساسا برای محاسبات دقیق طراحی نشده. مثال Varchar و Int را هم زدم که شما متوجه بشید، به صرف وجود یک قابلیت، ضرورتی برای استفاده از آن پیش نمیاد؛ همانطوری که شما برای ذخیره داده های عددی، از Varchar به خاطر قبول همزمان عدد و حروف استفاده نمی کنید (چون قبول حروف برای شما در اون حالت ارزشی نداره)، برای مقادیر مالی هم دقت بالای محاسباتی Decimal ارزشی نداره؛ پس اینکه کسی مدعی بشه Decimal دقت بالاتری از money داره، ضعف نوع داده money یا برتری decimal در نگهداری داده های مالی را نمیرسونه، چون اون قابلیت اساسا کاربردی برای اون داده ها نداره. اتفاقا همین محدود بودن دقت محاسباتی در money هست که باعث شده بشه اون رو به صورت یک مقدار صحیح ذخیره کرد که سربار کمتری از مقادیر اعشاری داره، و دقتش هم مطلق هست.




> ببخشید کدوم استاندارد!!!همینجوری که نمیشه گفته های خودمون رو استاندارد تلقی کنیم.!


میشه قبل از اظهار نظرهای عجولانه، و متهم کردن دیگران به تلقی کردن نظرات خودشان به عنوان استاندارد (!!) کمی درباره موضوع مربوطه تحقیق فارغ از جبهه گیری داشته باشید؟!
اعداد اعشاری در کامپیوتر هیچ وقت دقت صد در صد ندارند، به همین جهت، باید دقت مورد نیاز در محاسبه لحاظ بشه، و متناسب با اون دقت، عدد مربوطه نهایتا round بشه. Round کردن هم انواع مختلفی داره، از truncate کردن (برش زدن) ساده، تا گرد کردن به مقدار بالا و پایین و نزدیکترین مقدار و غیره. در محاسبات مالی، وقتی از نوع داده های شناور (floating-point data types) استفاده میشه، ممکنه در محاسبات مقدار ناچیزی رقم جابجا بشه، هر چند این مقدار در یک محاسبه ناچیز هست، ولی در حجم زیاد میتونه مشکل ساز بشه، مثلا شاید اگر یک سنت از حساب بانکی یک فرد کم بشه، اون فرد متوجه نشه، اما اگر قرار باشه 1 سنت از حساب 50 میلیون نفر کم بشه، میشه 500،000 دلار، که پول زیادی میشه. یکی از راه های متداول برای پرهیز از این موضوع، استفاده از نوع های داده fixed-point هست، که هم دقت مطلق داره، و هم در محاسبات سربار آن بسیار پایین تر از نوع های داده شناور هست. در نوع داده money در SQL Server که متناظر آن با نام currency در زبان های برنامه نویسی مختلف وجود داره، از یک عدد صحیح بزرگ برای این نوع محاسبات استفاده میشه، که تعدادی از رقم های آن (4 رقم) برای نگهداری اعشار استفاده شده. دقت یک عدد صحیح 1 واحد هست، پس دقت نوع  داده money که از عدد صحیح با ممیز ثابت 4 رقمی استفاده میکنه، همواره 1 ده هزارم (0.0001) هست. اگر نوع داده money یا currency در محاسبات به همراه نوع های داده اعشاری دیگه استفاده بشند، به طور خودکار مقادیر آنها (متناسب با نوع محاسبه) در 10000 ضرب یا تقسیم میشند. اگر میخواید درباره نوع های داده اعشاری در کامپیوتر و دقت آنها در محاسبات مطالعه کنید، مقاله زیر، میتونه بهتون کمک کنه:

http://www.codeproject.com/KB/dotnet...ingPoint1.aspx


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

روز خوش

----------


## mohammadi4net

برداشت  از صحبت های دوستان این بود:
برای نگهداری مقدار عددی در حسابداری با توجه به واحد پول کشورمون از نوع عدد صحیح استفاده کنیم ولی ایرادی که به اون وارد میشه دقت محاسبات رو پایین میاره و در صورت حذف 4 صفر از واحد پول ایران به سیستم طراحی شده آسیب جدی وارد میشه حالا اگه از عدد اعشاری با دقت مضاعف استفاده کنیم با توجه به اینکه* در حسابداری اعشار با دقت محدود کافیه* و بیشتر از اون کاربردی نداره و سربار زیادی ممکنه به سیستم وارد کنه  *مایکروسافت به این نتیجه رسید که نوع جدید Money طراحی کنه که عدد صحیح با دقت بالا و اعشار با دقت پایین رو ذخیره کنه* پس منطق ما و تحقیق چندین ساله مایکروسافت حکم می کنه که از نوع داده Money  استفاده کنیم.

در چه مواقعی از نوع داده Money  استفاده نکنیم:
نیاز به دقت بالا در محاسبات حسابداری 
طراحی سیستمی که وابستگی به هیچ نوع پلتفرم زبان سیستم عامل و پایگاه داده  ... ندارد.
اعلام رسمی مایکروسافت بر عدم استفاده از نوع داده Money و عدم پشتیبانی در نسخه های آتی همانند : نوع داده image
پیش بینی تغییر دیتابیس در آینده

----------


## Miladsob

سلام 
فکر کنم که این تصویر بتونه بهتون کمک کنه در انتخاب نوع داده ای مربوطه:

----------


## mahmoudy.log

میشه 1جدول دیگه طراحی کرد ک لیست رکوردهایی که فیلد money اونها reset شده ذخیره کرد.مثلا اگه از 1میلیارد بالا زد داده صفر کنه ولی تو جدول مذکور 1 رو به ازای پمیلیارد بزنه
اینجوری دیتابیس اصلی کوچکتری از طریق تعریف 1داده کوچکتر(int به جای decimmal) خواهید داشت

----------


## linux

فیلد money چیزی هست که احتیاجات شما را برآورده می کند. تمام گفته های آقای کشاورز کاملا صحیح است

----------


## linux

> برداشت  از صحبت های دوستان این بود:....
> 
> طراحی سیستمی که وابستگی به هیچ نوع پلتفرم زبان سیستم عامل و پایگاه داده  ... ندارد.
> اعلام رسمی مایکروسافت بر عدم استفاده از نوع داده Money و عدم پشتیبانی در نسخه های آتی همانند : نوع داده image
> پیش بینی تغییر دیتابیس در آینده


مایکروسافت تا حالا هیچ جا در مورد حذف money از sql server یک کلمه هم چیزی نگفته .

----------


## hamidkarimy

from stack overflow
Never ever should you use money it is not precise and it is pure garbage, always use decimal/numeric

run this to see what I mean

DECLARE
    @mon1 MONEY,
    @mon2 MONEY,
    @mon3 MONEY,
    @mon4 MONEY,
    @num1 DECIMAL(19,4),
    @num2 DECIMAL(19,4),
    @num3 DECIMAL(19,4),
    @num4 DECIMAL(19,4)

    SELECT
    @mon1 = 100, @mon2 = 339, @mon3 = 10000,
    @num1 = 100, @num2 = 339, @num3 = 10000

    SET @mon4 = @mon1/@mon2*@mon3
    SET @num4 = @num1/@num2*@num3

    SELECT @mon4 AS moneyresult,
    @num4 AS numericresult
Output: 2949.0000 2949.8525

کلیت موضوع اینه که money مشکل تقسیم داره البته بعضی ها معتقدن که تقسیم پول بر پول معنی نداره ولی عملا ما حالتهایی داریم که ممکنه این نیاز ایجاد بشه مثلا اگر بخوایم قیمت کل رو به فی تقسیم کنیم و نسبتش رو بگیریم حالا به هر دلیلی

----------


## hamid59022

سلام - ببخشید من یه مقدار تازه کارم پس اگر اشتباه نوشتم ببخشید 
میشه نوع داده ای عددی استفاده کرد با این محاسبه که n عدد اول اعشاری هستند چون مثل زمان نیست و اساسا بر نوع دهگانی سوار هست هیچ مشکلی نداره 
اینو برای این میگم که فکر میکنم سرباری روی بانک نداشته باشه - پس نوع big int فکر کنم جواب بده ( البته الان یادم نیست چند رقمی است ) :متفکر:

----------

