SQL - преобразование типа данных varchar в тип данных datetime привело к значению вне допустимого диапазона


88

Я получаю следующую ошибку при запуске SQL для преобразования значения моего типа данных из varcharв datetime.

Msg 242, уровень 16, состояние 3, строка 1 Преобразование типа данных varchar в тип данных datetime привело к значению вне допустимого диапазона.

Я проверил данные и не вижу ничего странного: провел следующие проверки, и все они не дали результатов

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

Есть ли что-нибудь еще, на что стоит обратить внимание и, возможно, стоит указать или помочь с этой проблемой? Кажется, я не могу понять это.


3
Какой тип данных столбца даты? Не могли бы вы показать мне схему таблицы и указание на ошибку?
Спайк,

3
какой из шести предоставленных вами операторов SQL не работает?
Mureinik

1
Все шесть утверждений работают и подтверждают отсутствие проблем с данными.
user23495

3
вы не проверяли наличие недействительных дат, например, 31.10.2013 или 30.02.2013. Вероятно, ошибка, с которой вы столкнулись, относится к такого рода проблемным датам
Дален

2
Привет, Дален, я проверил. Данные настроены 31.10.2013, 30.10.2013. Это в британском формате. Будет ли это иметь какое-либо влияние при попытке изменить тип столбца, не думал, что это будет.
user23495

Ответы:


84

Неделю назад я столкнулся с той же проблемой. Проблема в настройке часового пояса. Укажите в других форматах, например мм / дд / гггг (обычно работает).

Указание даты 30.12.2013 привело к ошибке для меня. Однако указание формата мм / дд / гггг сработало.

Если вам нужно преобразовать введенные вами данные, вы можете попробовать изучить CONVERTметод. Синтаксис

CONVERT(VARCHAR,@your_date_Value,103)

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

Окончание 103 - это формат даты и времени.

Обратитесь к этой ссылке для форматов преобразования и дальнейшего чтения. https://www.w3schools.com/sql/func_sqlserver_convert.asp


1
Спасибо за помощь, дружище. Я попытался преобразовать это, но мне все равно не повезло. Может ли это быть из-за того, что table - это еще varchar или что-то еще, что может привести к сбою?
user23495

2
Было бы очень полезно, если вы разместите свои образцы данных (которые находятся в таблице). В комментарии вы сказали, что хотите его в формате гггг-мм-дд. Итак, попробуйте это SELECT CONVERT(char(10), GetDate(),126). Просто замените GETDATE () на необходимое значение.
Mahe

61

Я столкнулся с этой проблемой из-за глупой ошибки. Убедитесь, что дата действительно существует!

Например:

31 сентября 2015 г. не существует.

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

Итак, это не срабатывает с сообщением:

Error converting data type varchar to datetime.

Чтобы исправить это, введите действительную дату:

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

И он отлично работает.


2
Да, я только что обнаружил дату истечения срока действия 29 февраля 2015 года в базе данных, с которой мне нужно работать. Интересно, как оно туда попало. Интересно, сколько там еще ...
Ресурс

4
Просто использовал cast (SUBSTRING ([MyDateField], 1,2) as integer)> 31 и нашел запись с 60 декабря. Кто занимается этим, доктор Зюсс?
SteveCav

3
Благодарность! Это была моя проблема. У меня в наборе были плохие данные - 01.01.1113, ха-ха.
Sev09, 08

2
Для меня я поместил неправильную строку формата при форматировании даты для построения оператора SQL. Я использовал то, Format(DateTime.Now, "yyyymmdd")что должно было бытьFormat(DateTime.Now, "yyyyMMdd")
Джей Имерман

1
Ах, американские свидания! На какое-то время я был в тупике, так как «26 октября 2017», то есть «26-10-2017», является вполне допустимой датой :)
Antimony

29

Недавно у меня была аналогичная проблема. Региональные настройки были правильно настроены как в приложении, так и на сервере базы данных. Однако выполнение SQL привело к

«Преобразование типа данных varchar в тип данных datetime привело к значению вне допустимого диапазона».

Проблема заключалась в языке по умолчанию пользователя db.

Чтобы проверить или изменить его в SSMS, перейдите в раздел «Безопасность» -> «Логины» и щелкните правой кнопкой мыши имя пользователя, выполняющего запросы. Выберите «Свойства» -> «Общие» и убедитесь, что язык по умолчанию в нижней части диалогового окна соответствует вашим ожиданиям.

Повторите это для всех пользователей, выполняющих запросы.


1
Это мне помогло. Небольшая поправка: языка по умолчанию server loginнет db user. top-password.com/blog/…
База Гувенькая 08

1
Поскольку он задан в программном коде, и у меня не было доступа к нему, я изменил его с Englishна, British Englishи он заработал!
vaheeds

1
То же самое и со мной, если я поменяю английский на британский - Али, ты спасатель!
Давид Георгий,


4
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

У меня была такая же проблема, и я решил, что эта проблема возникает из-за того, что 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

2
+ 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

Возникла проблемная строка со строкой даты «19610010» (формат: ГГГГММДД), которая вызвала ошибку «Преобразование типа данных nvarchar в тип данных datetime привело к значению вне допустимого диапазона». SELECT CONVERT (datetime, 'yourdate') FROM [yourtable] WHERE ISDATE ('yourdate') = 1 сохранил день :)
Дж. Поллак,

2

Я тоже столкнулся с этой проблемой при автоматической вставке sysdate в столбец.

Я изменил свой системный формат даты, чтобы он соответствовал формату даты SQL-сервера. например, мой формат SQL был мм / дд / гггг, а мой системный формат был установлен на дд / мм / гггг. Я изменил системный формат на мм / дд / гггг, и ошибка исчезла

-kb


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

Преобразуйте его обычно в datetime

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

В вашем случае вы можете сделать

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

2

Тест для года> 2079. Я обнаружил, что пользователь опечатал 2106 вместо 2016 года (12.10.2106) и бум; поэтому 10/12/2016 я протестировал и обнаружил, что SQL Server принят до 2078 года, начал выдавать эту ошибку, если год 2079 или выше. Я не проводил никаких дальнейших исследований относительно того, что делает SQL Server со сдвигом даты.


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)  

1
Varchar Date Convert to Date and Change the Format

12 ноября 2016 12:00, 21/12/2016, 21-12-2016 этот запрос работает, чтобы изменить этот формат на этот формат dd / MM / yyyy SELECT [Member_ID],[Name] , Convert(varchar(50),Convert(date,[DOB],103),103) as DOB ,[NICNO],[Relation] FROM [dbo].[tbl_FamilMember]


0

Эта ошибка возникла у меня, потому что я пытался сохранить минимальную дату и время в столбце, используя встроенные запросы непосредственно из кода C #.

Переменная даты была установлена ​​в 01/01/0001 12:00:00 AM в коде с учетом того факта, что DateTime в C # инициализируется этими датой и временем, если не установлены иначе. И наименее возможная дата, разрешенная в типе данных datetime MS-SQL 2008, - 1753-01-01 12:00:00 AM.

Я изменил дату из кода и установил ее на 01.01.1900, и больше никаких ошибок не сообщалось.



0

Просто убедитесь, что ваши даты совместимы или могут правильно работать в вашем менеджере баз данных (например, SQL Server Management Studio). Например, функция C # DateTime.Now недопустима на сервере SQL, что означает, что ваш запрос должен включать допустимые функции, такие как GETDATE () для SQL Server.

Это изменение отлично сработало для меня.


0

Немного необычная причина этой проблемы, но на всякий случай она кому-то понадобится. Код, над которым я работал, использовал:

java.text.DateFormat.getDateTimeInstance()

чтобы получить средство форматирования даты. Шаблон форматирования, возвращаемый этим вызовом, изменился с Java 8 на Java 9, как описано в этом отчете об ошибке: https://bugs.openjdk.java.net/browse/JDK-8152154, очевидно, форматирование, которое он возвращал для меня, не подходило для базы данных. Вместо этого решение было таким:

DateTimeFormatter.ISO_LOCAL_DATE_TIME
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.