SQL - 将varchar数据类型转换为日期时间数据类型会导致超出范围的值

时间:2013-12-30 11:13:10

标签: sql-server tsql datetime

运行SQL时,我遇到以下错误,将我的数据类型值从​​varchar转换为datetime

  

Msg 242,Level 16,State 3,Line 1   将varchar数据类型转换为日期时间数据类型会导致超出范围的值。

我检查了数据并且看不到任何奇怪的内容:执行以下检查并且所有检查都没有结果

SELECT [Date] from table where [DATe] is null
SELECT [Date] from table where [DATe] = ''
SELECT [Date] from table where LEN([date])> 10
SELECT [Date] from table where LEN([date])< 10
SELECT top 100 [Date] , SUBSTRING([date],4,2) from [table where convert(int, SUBSTRING([date],4,2)) < 1 or convert(int, SUBSTRING([date],4,2)) > 12
SELECT top 100 [Date] , SUBSTRING([date],1,2) from table where convert(int, SUBSTRING([date],4,2)) < 1 or convert(int, SUBSTRING([date],4,2)) > 31

还有什么值得关注的东西,也许值得指点或帮助解决这个问题?似乎无法深入了解它。

18 个答案:

答案 0 :(得分:60)

一周前我遇到了同样的问题。 问题在于时区设置。以mm / dd / yyyy等其他格式指定(通常有效)。

将日期指定为 30/12/2013 会导致错误。但是,将其指定为mm / dd / yyyy格式。

如果您需要转换输入,可以尝试查看CONVERT方法。 语法是

CONVERT(VARCHAR,@your_date_Value,103)

CONVERT(VARCHAR, '12/30/2013', 103)

完成 103 是日期时间格式。

请参阅此链接以获取转换格式和进一步阅读。 http://www.w3schools.com/sql/func_convert.asp

答案 1 :(得分:47)

由于一个愚蠢的错误,我遇到了这个问题。 确保日期确实存在!

例如:

2015年9月31日不存在。

EXEC dbo.SearchByDateRange @Start = '20150901' , @End = '20150931'

因此失败并显示以下消息:

Error converting data type varchar to datetime.

要修复它,请输入有效日期:

EXEC dbo.SearchByDateRange @Start = '20150901' , @End = '20150930'

它执行得很好。

答案 2 :(得分:15)

我最近遇到过类似的问题。在应用程序和数据库服务器中正确设置了区域设置。但是,执行SQL导致

  

“将varchar数据类型转换为日期时间数据类型会导致超出范围的值”。

问题是db用户的默认语言。

要在SSMS中检查或更改它,请转到安全性 - &gt;登录并右键单击运行查询的用户的用户名。选择属性 - &gt;一般而言,确保对话框底部的默认语言符合您的期望。

对所有运行查询的用户重复此操作。

答案 3 :(得分:8)

您可以使用

Set dateformat <date-format> ;

在你的sp函数或存储过程中完成任务。

答案 4 :(得分:3)

Create procedure [dbo].[a]

@examdate varchar(10) ,
@examdate1 varchar(10)
AS
Select tbl.sno,mark,subject1,
Convert(varchar(10),examdate,103) from tbl
where 
(Convert(datetime,examdate,103)  >= Convert(datetime,@examdate,103) 
and (Convert(datetime,examdate,103) <=  Convert(datetime,@examdate1,103)))

答案 5 :(得分:2)

年度测试&gt; 2079。 我发现用户在一年(10/12/2106)和繁荣中错过了2106而不是2016年;所以在2016年12月10日我测试并发现SQL Server接受了2078年,如果年份是2079或更高,则开始抛出该错误。我还没有进一步研究过什么样的日期滑动SQL Server。

答案 6 :(得分:2)

如您所知,这是英国格式问题。 您可以使用函数间接进行日期转换。

CREATE FUNCTION  ChangeDateFormatFromUK
( 
   @DateColumn varchar(10)
)

RETURNS VARCHAR(10)
AS 
 BEGIN
    DECLARE @Year varchar(4), @Month varchar(2), @Day varchar(2), @Result varchar(10)
    SET @Year = (SELECT substring(@DateColumn,7,10))
    SET @Month = (SELECT substring(@DateColumn,4,5)) 
    SET @Day = (SELECT substring(@DateColumn,1,2))
   SET @Result  = @Year  + '/' @Month + '/' +  @Day

 RETURN @Result
END

调用此功能

SELECT dbo.ChangeDateFormatFromUK([dates]) from table

将其正常转换为日期时间

SELECT CONVERT(DATETIME,dbo.ChangeDateFormatFromUK([dates])) from table

在你的案例中,你可以做到

SELECT [dates] from table where CONVERT(DATETIME,dbo.ChangeDateFormatFromUK([dates])) > GetDate()   -- or any date

答案 7 :(得分:2)

我自动将sysdate插入列时遇到此问题。

我所做的是更改了系统日期格式以匹配SQL Server的日期格式。 例如 我的SQL格式是mm / dd / yyyy,我的系统格式设置为dd / mm / yyyy。 我将系统格式更改为mm / dd / yyyy并且错误消失了

-kb

答案 8 :(得分:2)

我遇到了同样的问题并确定出现此问题是因为SQL Server不会以相同的方式对转换为整数的字符进行比较。在我的测试中,我发现转换字符的某些比较(例如感叹号)将返回类型转换错误,而转换字符的其他比较(例如空格)将被确定为超出范围。

此示例代码测试不同的可能方案,并使用嵌套的REPLACE语句提供解决方案。 REPLACE确定字符串中是否有任何字符不是数字或斜杠,如果存在,则字符串的长度将大于零,从而表明存在“不良”字符。字符和日期无效。

DECLARE @str varchar(10)
SET @str = '12/10/2012'
IF convert(int, substring(@str,4,2)) <= 31 AND convert(int, substring(@str,4,2)) >= 1
    PRINT @str+': Passed Test'
    ELSE PRINT @str+': Failed Test'
GO

DECLARE @str varchar(10)
SET @str = '12/10/2012' 
PRINT 'Number of characters in ' + @str + ' that are not numerals or a slash (0 means the date is valid; all values greater than 0 indicate a problem): ' + convert(varchar(5),len(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(@str,'0',''),'1',''),'2',''),'3',''),'4',''),'5',''),'6',''),'7',''), '8',''),'9',''),'/',''),' ','+'))) --replace space with a + to avoid empty string
PRINT ''
GO

DECLARE @str varchar(10)
SET @str = '12/!0/2012'
    IF convert(int, substring(@str,4,2)) <= 31 AND convert(int, substring(@str,4,2)) >= 1
        PRINT @str+': Passed Test'
        ELSE PRINT @str+': Failed Test'
GO

DECLARE @str varchar(10)
SET @str = '12/!0/2012' 
PRINT 'Number of characters in ' + @str + ' that are not numerals or a slash (0 means the date is valid; all values greater than 0 indicate a problem): ' + convert(varchar(5),len(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(@str,'0',''),'1',''),'2',''),'3',''),'4',''),'5',''),'6',''),'7',''), '8',''),'9',''),'/',''),' ','+'))) --replace space with a + to avoid empty string
PRINT ''
GO

DECLARE @str varchar(10)
SET @str = '12/  /2012'
IF convert(int, substring(@str,4,2)) <= 31 AND convert(int, substring(@str,4,2)) >= 1
    PRINT @str+': Passed Test'
    ELSE PRINT @str+': Failed Test'
GO

DECLARE @str varchar(10)
SET @str = '12/  /2012' 
PRINT 'Number of characters in ' + @str + ' that are not numerals or a slash (0 means the date is valid; all values greater than 0 indicate a problem): ' + convert(varchar(5),len(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(@str,'0',''),'1',''),'2',''),'3',''),'4',''),'5',''),'6',''),'7',''), '8',''),'9',''),'/',''),' ','+'))) --replace space with a + to avoid empty string

<强>输出:

--Output
--12/10/2012: Passed Test
--Number of characters in 12/10/2012 that are not numerals or a slash (0 means the date is valid; all values greater than 0 indicate a problem): 0

--Msg 245, Level 16, State 1, Line 4
--Conversion failed when converting the varchar value '!0' to data type int.
--Number of characters in 12/!0/2012 that are not numerals or a slash (0 means the date is valid; all values greater than 0 indicate a problem): 1

--12/  /2012: Failed Test
--Number of characters in 12/  /2012 that are not numerals or a slash (0 means the date is valid; all values greater than 0 indicate a problem): 2

答案 9 :(得分:1)

我只是将我想要转换的varchar字段转换为一个新表(带有DateTime字段),然后首先转换为DateTime兼容布局,然后SQL将从varchar转换为DateTime而不会出现问题。

在下面(不是我创建的带有这些名称的表!)如果您想要,我只需将varchar字段设置为DateTime:

update report1455062507424 
set [Move Time] = substring([Move Time], 7, 4) + '-'+ substring([Move Time], 4, 2) + '-'+ substring([Move Time], 1, 2) + ' ' + 
    substring([Move Time], 12, 5)  

答案 10 :(得分:1)

Varchar Date Convert to Date and Change the Format

2016年11月12日12:00,2016年12月21日,2016年12月21日 此查询适用于上面更改为此格式dd / MM / yyyy SELECT [Member_ID],[Name] , Convert(varchar(50),Convert(date,[DOB],103),103) as DOB ,[NICNO],[Relation] FROM [dbo].[tbl_FamilMember]

答案 11 :(得分:1)

+ this happens because sql sometimes doesn't recognize dd/mm/yyyy format
+ so we should always check if the input string is a valid date or not and the accordingly convert it to mm/dd/yyyy and so , i have shown below how it can be done, i have created a function to rearrange in mm/dd/yyyy from dd/mm/yyyy

select case when isdate('yourdate')=1 then CAST('yourdate' AS datetime) 
  else (select * from dbo.fn_convertdate(yourdate))

Create function dbo.fn_convertdate( @Stringdate nvarchar(29))
RETURNS @output TABLE(splitdata NVARCHAR(MAX) 
)
Begin
Declare @table table(id int identity(1,1), data varchar(255))
Declare @firstpart nvarchar(255)
Declare @tableout table(id int identity(1,1), data varchar(255))

Declare @Secondpart nvarchar(255)
Declare @Thirdpart nvarchar(255)

declare @date datetime

insert into @table
select * from dbo.fnSplitString(@Stringdate,'/')
select @firstpart=data from @table where id=2
select @Secondpart=data from @table where id=1
select @Thirdpart=data from @table where id=3
set @date=@firstpart+'/'+@Secondpart+'/'+@Thirdpart
insert into @output(splitdata) values(
@date)


return
End

答案 12 :(得分:0)

这个错误发生在我身上,因为我试图直接从C#代码使用内联查询将最小日期和时间存储在列中。

如果没有设置elsewise,则在代码中将日期变量设置为01/01/0001 12:00:00 AM,并且使用此日期和时间初始化C#中的DateTime。 MS-SQL 2008 datetime数据类型中允许的最小日期是1753-01-01 12:00:00 AM。

我从代码中更改了日期并将其设置为01/01/1900,并且没有进一步报告错误。

答案 13 :(得分:0)

我在mm而不是MM的日期使用了ToString()。

答案 14 :(得分:0)

只需确保您的日期兼容,或者可以在数据库管理器中正常运行(例如SQL Server Management Studio)。例如,DateTime.Now C#函数在SQL Server中无效,这意味着您的查询必须包含有效的函数,如SQL Server的GETDATE()。

这一改变对我来说非常有效。

答案 15 :(得分:0)

此问题的原因略有不同,但以防万一有人需要它。我正在使用的代码正在使用:

java.text.DateFormat.getDateTimeInstance()

获取日期格式器。如错误报告中所述,此调用返回的格式从Java 8更改为Java 9:https://bugs.openjdk.java.net/browse/JDK-8152154显然为我返回的格式不适用于数据库。解决方案是改为:

DateTimeFormatter.ISO_LOCAL_DATE_TIME

答案 16 :(得分:0)

我遇到过类似的问题。我不认为很多人会面临我所面临的情况。尽管如此,我还是想分享我的经验。我在测试环境中工作,并且有日期时间数据设置为最小日期时间值 0001/01/01。该值小于 smalldatetime 数据类型的最小可能数据。因此,请务必检查数据类型的 Min Max 值。 对于 smalldatetime,您可以参考此页面:https://docs.microsoft.com/en-us/sql/t-sql/data-types/smalldatetime-transact-sql?view=sql-server-ver15

答案 17 :(得分:-1)

在顶部添加:

SET DATEFORMAT ymd; 

或您在查询中使用的任何格式