PDA

View Full Version : وارد کردن تاریخ در اس کیو ال سرور



javacanker
دوشنبه 03 آذر 1393, 12:53 عصر
با عرض سلام خدمت تمامی دوستان عزیز
توی برنامم تاریخ رو به شمسی تبدیل کردم و فیلد پایگاه رو به صورت date (یا date Time)قرار دادم، وقتی میخوام تاریخ رو وارد دیتابیس کنم ارور میده...
فیلد پایگاه رو به string تغییر دادم. حالا میخواستم از برنامم گزارش گیری کنم، یعنی اطلاعات بین دو تاریخ رو بگیرم( ی ستون تاریخ دارم که توی هر سطرش ی سری اطلاعات ذخیره شده، میخوام اطلاعات بین دو تاریخ رو از پایگاه بگیرم ) ولی نمیدونم چطوری با string اینکارو انجام بدم
میخواستم بپرسم که فیلد پایگاه حتما باید به صورت date Time یا date باشه یا نه، اگه بله لطفا بهم بگین چطوری تاریخ شمسی رو وارد پایگاه date time کنم که ارور نده و اگه هم به صورت string میشه گزارش گیری کرد لطفا بهم بگین چطوری اینکارو انجام بدم.
ممنون از همه شما دوستان

fakhravari
دوشنبه 03 آذر 1393, 13:45 عصر
با پرشین کلندر به صورت فارسی save کنید

Jean Reno
دوشنبه 03 آذر 1393, 16:15 عصر
تابع زیر در SQL ، رشته تاریخ شمسی رو میگیره و تاریخ میلادی از نوع DateTime بر میگردونه



CREATE FUNCTION [dbo].[ShamsiToMiladi] ( @DateStr VARCHAR(10) )
RETURNS DATETIME
AS
BEGIN
DECLARE @YYear INT
DECLARE @MMonth INT
DECLARE @DDay INT
DECLARE @epbase INT
DECLARE @epyear INT
DECLARE @mdays INT
DECLARE @persian_jdn INT
DECLARE @i INT
DECLARE @j INT
DECLARE @l INT
DECLARE @n INT
DECLARE @TMPRESULT VARCHAR(10)
DECLARE @IsValideDate INT
DECLARE @TempStr VARCHAR(20)
DECLARE @TmpDateStr VARCHAR(10)

SET @i = CHARINDEX('/', @DateStr)

IF LEN(@DateStr) - CHARINDEX('/', @DateStr,
CHARINDEX('/', @DateStr, 1) + 1) = 4
BEGIN
SET @TmpDateStr = dbo.ReversDate(@DateStr)
IF ( ISDATE(@TmpDateStr) = 1 )
RETURN @TmpDateStr
ELSE
RETURN NULL
END
ELSE
SET @TmpDateStr = @DateStr

IF ( ( @i <> 0 )
AND ( CHARINDEX('/', @TmpDateStr) = 5 )
AND ( ISNUMERIC(REPLACE(@TmpDateStr, '/', '')) = 1 )
AND ( CHARINDEX('.', @TmpDateStr) = 0 )
)
BEGIN
SET @YYear = CAST(SUBSTRING(@TmpDateStr, 1, @i - 1) AS INT)
IF ( @YYear < 1300 )
SET @YYear = @YYear + 1300
IF @YYear > 9999
RETURN NULL

SET @TempStr = SUBSTRING(@TmpDateStr, @i + 1, LEN(@TmpDateStr))

SET @i = CHARINDEX('/', @TempStr)
SET @MMonth = CAST(SUBSTRING(@TempStr, 1, @i - 1) AS INT)
SET @MMonth = @MMonth-- -1

SET @TempStr = SUBSTRING(@TempStr, @i + 1, LEN(@TempStr))

SET @DDay = CAST(@TempStr AS INT)
SET @DDay = @DDay-- - 1

IF ( @YYear >= 0 )
SET @epbase = @YYear - 474
ELSE
SET @epbase = @YYear - 473
SET @epyear = 474 + ( @epbase % 2820 )

IF ( @MMonth <= 7 )
SET @mdays = ( ( @MMonth ) - 1 ) * 31
ELSE
SET @mdays = ( ( @MMonth ) - 1 ) * 30 + 6

SET @persian_jdn = ( @DDay ) + @mdays
+ CAST(( ( ( @epyear * 682 ) - 110 ) / 2816 ) AS INT)
+ ( @epyear - 1 ) * 365 + CAST(( @epbase / 2820 ) AS INT)
* 1029983 + ( 1948321 - 1 )



IF ( @persian_jdn > 2299160 )
BEGIN
SET @l = @persian_jdn + 68569
SET @n = CAST(( ( 4 * @l ) / 146097 ) AS INT)
SET @l = @l - CAST(( ( 146097 * @n + 3 ) / 4 ) AS INT)
SET @i = CAST(( ( 4000 * ( @l + 1 ) ) / 1461001 ) AS INT)
SET @l = @l - CAST(( ( 1461 * @i ) / 4 ) AS INT) + 31
SET @j = CAST(( ( 80 * @l ) / 2447 ) AS INT)
SET @DDay = @l - CAST(( ( 2447 * @j ) / 80 ) AS INT)
SET @l = CAST(( @j / 11 ) AS INT)
SET @MMonth = @j + 2 - 12 * @l
SET @YYear = 100 * ( @n - 49 ) + @i + @l
END

SET @TMPRESULT = CAST(@MMonth AS VARCHAR(2)) + '/'
+ CAST(@DDay AS VARCHAR(2)) + '/'
+ CAST(@YYear AS VARCHAR(4))
RETURN CAST(@TMPRESULT AS DATETIME)

END
RETURN NULL

END
GO



نحوه فراخوانی :

SELECT dbo.ShamsiToMiladi('1393/09/01')

Jean Reno
دوشنبه 03 آذر 1393, 17:00 عصر
و تابع زیر تاریخ میلادی از نوع DateTime رو می گیره و به تاریخ شمسی از نوع رشته ای تبدیل می کنه


CREATE FUNCTION [dbo].[MiladiTOShamsi]
(
@MDate DateTime
)
RETURNS Varchar(10)
AS
BEGIN
Declare
@Year Integer,
@Month Integer,
@Day Integer,
@F_Year Integer,
@F_Month Integer,
@F_Day Integer,
@F_Day_Name NVarchar(10),
@F_Month_Name NVarchar(10),
@LastDay Integer,
@Plus Integer,
@Minus Integer,
@Intercalary Integer,
@S_Year Varchar(5),
@S_Month Varchar(5),
@S_Day Varchar(5),
@E_Date Varchar(20),
@Ret Varchar(10)

Set @Plus = 0

Set @Year = Year(@MDate)
Set @Month = Month(@MDate)
Set @Day = Day(@MDate)

----- بدست آوردن تاریخ میلادی
Set @S_Year = Cast(@Year AS VarChar(5))
Set @S_Month = Cast(@Month AS VarChar(5))
Set @S_Day = Cast(@Day AS VarChar(5))

IF Len(@S_Month) < 2
Set @S_Month = '0'+@S_Month

IF Len(@S_Day) < 2
Set @S_Day = '0'+@S_Day

Set @E_Date = @S_Year + @S_Month + @S_Day
----- بدست آوردن تاریخ میلادی

----- بدست آوردن نام روز به فارسی
--Set @F_Day_Name = Case DATEPART(dw, Getdate())
-- When 1 Then N'یکشنبه'
-- When 2 Then N'دوشنبه'
-- When 3 Then N'سه شنبه'
-- When 4 Then N'چهارشنبه'
-- When 5 Then N'پنجشنبه'
-- When 6 Then N'جمعه'
-- When 7 Then N'شنبه'
--End
----- بدست آوردن نام روز به فارسی

IF ((@Month = 1) or (@Month = 5) or (@Month = 6))
Set @Plus = 10

IF ((@Month = 2) or (@Month = 4))
Set @Plus = 11

IF ((@Month = 3) or (@Month = 7) or (@Month = 8) or
(@Month = 9) or (@Month = 11) or (@Month = 12))
Set @Plus = 9

IF (@Month = 10)
Set @Plus = 8

Set @Year = @Year % 100

Set @Intercalary = @Year

IF (@Intercalary % 4 = 0)
IF (@Month > 2)
Set @Plus = @Plus + 1

IF ((@Intercalary - 1) % 4 = 0)
begin
Set @LastDay = 30
IF (@Month <= 3)
Set @Plus = @Plus + 1
end
Else
Set @LastDay = 29

Set @F_Year = @Year - 22

IF (@F_Year < 0)
Set @F_Year = @F_Year + 100

Set @F_Month = @Month + 9

IF (@F_Month > 12)
begin
Set @F_Month = @F_Month - 12
Set @F_Year = @F_Year + 1
end

Set @F_Day = @Day + @Plus

IF (@F_Month <= 6)
Set @Minus = 31
Else
IF ((@F_Month > 6) and (@F_Month<12))
Set @Minus = 30
Else
Set @Minus = @LastDay

IF (@F_Day > @Minus)
begin
Set @F_Day = @F_Day - @Minus;
Set @F_Month = @F_Month + 1
end

IF (@F_Month > 12)
begin
Set @F_Month = @F_Month - 12;
Set @F_Year = @F_Year + 1
end;

IF @F_Year >= 10
Set @Ret = '13' + Cast(@F_Year As Varchar(4))
Else
Set @Ret = '130'+ Cast(@F_Year As Varchar(4))


IF @F_Month >= 10
Set @Ret = @Ret + '/' + Cast(@F_Month As Varchar(4))
Else
Set @Ret = @Ret +'/0'+ Cast(@F_Month As Varchar(4))

----- بدست آوردن نام ماه به فارسی
--Set @F_Month_Name = Case @F_Month
-- When 1 Then N'فروردین'
-- When 2 Then N'اردیبهشت'
-- When 3 Then N'خرداد'
-- When 4 Then N'تیر'
-- When 5 Then N'مرداد'
-- When 6 Then N'شهریور'
-- When 7 Then N'مهر'
-- When 8 Then N'آبان'
-- When 9 Then N'آذر'
-- When 10 Then N'دی'
-- When 11 Then N'بهمن'
-- When 12 Then N'اسفند'
--End
----- بدست آوردن نام ماه به فارسی

IF @F_Day >= 10
Set @Ret = @Ret + '/' + Cast(@F_Day As Varchar(4))
Else
Set @Ret = @Ret + '/0'+ Cast(@F_Day As Varchar(4))


RETURN @Ret

END
GO

Jean Reno
دوشنبه 03 آذر 1393, 17:02 عصر
تجربه خودم :نوع فیلد تو دیتابیس رو از نوع DateTime قرار میدادم و زمانی که رکوردی رو می خوندم تو پروسیجرم از متد بالا جهت تبدیل به شمسی استفاده می کردم و مقدار فارسی رو بر می گردوندم و زمانی که قصد داشتم رکوردی رو ثبت کنم فیلد تاریخ شمسی رو به پروسیجر ثبت رکورد می دادم و داخل پروسیجر با استفاده از متد مبدل بالا به میلادی تبدیلش می کردم و ثبتش می کردم ...

javacanker
دوشنبه 03 آذر 1393, 22:51 عصر
اینیکه شما میفرمایید یعنی تو دیتابیس کلا تاریخ شمسی رو نمیشه ثبت کرد، حتما باید به میلادی تبدیلش کرد؟؟

Jean Reno
سه شنبه 04 آذر 1393, 09:24 صبح
اینیکه شما میفرمایید یعنی تو دیتابیس کلا تاریخ شمسی رو نمیشه ثبت کرد، حتما باید به میلادی تبدیلش کرد؟؟

تاریخ شمسی رو هم می تونی ذخیره کنی اما تجربه نشون داده که زمانی که نیاز به نوشتن کوئری های جستجو و گزارشات داشته باشی و نیاز به مقایسه و فیلتر بر اساس تاریخ ها باشی تاریخ های میلادی که برای SQL Server موجه تر هستند بهتر جواب میده ...

javacanker
سه شنبه 04 آذر 1393, 10:35 صبح
ممنون از توضیحاتتون
فقط ی سوال دیگه، من تاحالا تو اس کیو ال تابع ننوشتم، میشه راهنماییم کنید که چطوری این توابعی رو که نوشتید وارد اس کیو ال کنم و ازشون استفاده کنم؟؟
و همینطور نحوه فراخوانی اون از برنامه
با تشکر

Jean Reno
سه شنبه 04 آذر 1393, 10:40 صبح
2 تا کد تابع تو 2 تا کامنت جداگانه در بالا قراردادم هر کدوم رو جداگانه کپی کنید و

در SQL Server یک New Query ایجاد کنید یا کلید های CTRL+N رو فشار دهید

در پنجره کوئری نویسی کدها رو کپی کنید و دکمه Execute رو فشار دهیدتابع مورد نظر ایجاد میشه

برای استفاده هم می تونید از مثال زیر استفاده کنید :




SELECT [FactorID] ,

[InsertDate] = [dbo].[MiladiTOShamsi]([InsertDate]) ,

[UpdateDate] = [dbo].[MiladiTOShamsi]([UpdateDate])

FROM [dbo].[Resource_Factor]

..Johnny
سه شنبه 04 آذر 1393, 11:51 صبح
ببخشید تابع نویسی در اس کیو ال رو چطوری میشه یاد گرفت؟؟
میشه لطفا راهنمایی کنید
ممنون

javacanker
سه شنبه 04 آذر 1393, 12:41 عصر
ممنون از توضیحات خوب و کاملتون
اگه بازم به مشکل برخوردم حتما باهاتون درمیون میذارم
با تشکر فراوووووووووووون.........

Jean Reno
سه شنبه 04 آذر 1393, 14:37 عصر
ببخشید تابع نویسی در اس کیو ال رو چطوری میشه یاد گرفت؟؟
میشه لطفا راهنمایی کنید
ممنون

پیشنهاد می کنم چند کتاب الکترونیکی در زمینه کوئری نویسی در SQL مطالعه بفرمایید یا از فیلم های آموزشی در این زمینه استفاده کنید
در اینترنت منابع زیادی تو این زمینه ها یافت میشه
معمولا از ابتدایی ترین حالت شروع به آموزش می کنن تا متوسطه
برای پیشرفت در این زمینه ها تجربه بهترین معلم تون خواهد بود

Behnam6670
سه شنبه 04 آذر 1393, 15:58 عصر
من خودم بصورت شمسی ذخیره میکنم مثلا 1393/09/04 جستجوهامم رو همین رشته انجام میدم!!!!!!!:متفکر:

این کار تو LINQ خیلی راحت انجام میشه کد زیر رو نگاه کنید


var filter = from p in Program.db.tblSMIOMasterVKHs
orderby p.fDate
select new
{
p.fId,
p.fIdentity,
p.fKind,
p.fTime,
p.fDate,
fDateS = Convert.ToInt64(p.fDate.Replace("/", "")),

};


var _filter = filter.Where(c => c.fDateS >= Convert.ToInt64(txtDateF.SelectedDate) && c.fDateS <= Convert.ToInt64(txtDateE.SelectedDate));







اول میام select رو انجام میدم قسمت Replace کردن رو دقت کنید:چشمک:

بعد از select الان یه کوری دارم که که رشته تبدیل شده به رشته ی بدون ممیز یعنی "1393/09/04" تبدیل شده به 13930904 :متعجب:

قسمت بعدی برای فیلتر کردن تو بازه تاریخ هستش که میبینید به چه شکل انجام شده.

راستی نمیخوام تبلیغ کنم ولی تو کوری دوم من از کامپوننت تاریخ شمسی که خودم نوشتم استفاده کردم که وقتی شما یه تاریخ رو انتخاب میکنید یه فیلدی براش تعریف کردم که معادل بدون ممیز تاریخ انتخاب شده تو اون ذخیره میشه همون SelectedDate که تو کد بالا میبینید .
تو ابزارتون dll رو اضافه کنید یه کامپوننتی به ابزاراتون اضافه میشه به نام BPersianCalender که میتونید بندازید رو فرمتون و از امکاناتش استفاده کنید.رو کامپوننت میتونید کلیک راست کنید یا اینکه رو آیکون تقویم کیک کنید تا تقویم رو انتخاب کنید.

لینک دانلودش هم اینه