SQL - Перетворення типу даних varchar у тип даних datetime і часу призвело до значень, що виходять за межі діапазону


88

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

Повідомлення 242, рівень 16, стан 3, рядок 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

Чи є щось інше, на що варто подивитися, чи, можливо, варто підказати чи допомогти з цим питанням? Здається, не можу це зрозуміти.


3
Який тип даних стовпця дати? Не могли б ви показати схему таблиці та заяву про помилку, будь ласка?
Спайк

3
який із шести наданих вами операторів SQL не вдається?
Mureinik

1
Шість тверджень працюють і перевіряють відсутність проблем із даними.
user23495

3
Ви не перевіряли недійсні дати, наприклад, 2013-10-31 чи 2013-02-30. Можливо, помилка, з якою ви стикаєтесь, стосується такого роду проблемних дат
Дален,

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
Дякую за допомогу. Я намагався перетворити це, але все ще не маючи удачі. Чи це може бути пов’язано з тим, що varchar все ще є чи ще щось, що може спричинити невдачу?
user23495

2
Було б дуже корисно, якщо ви опублікуєте свої зразки даних (які є в таблиці). У коментарі ви сказали, що хочете його у форматі рррр-мм-дд. Отже, спробуйте це SELECT CONVERT(char(10), GetDate(),126). Просто замініть GETDATE () на необхідне значення.
Мае,

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
Щойно використаний привід (SUBSTRING ([MyDateField], 1,2) як ціле число)> 31 і знайдений запис 60 грудня. Хто вводить це, доктор Сьюс?
SteveCav

3
Дякую! Це була моя проблема. У мене було кілька поганих даних - 01/01/1113, ха-ха.
Sev09,

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

1
Арг американські конвенції про побачення! Був би мене тупив на деякий час, оскільки "26 жовтня 2017 р.", Тобто "26-10-2017" - цілком діюча дата :)
Сурма

29

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

Msgstr "Перетворення типу даних varchar у тип даних datetime і часу призвело до значень, що виходять за межі діапазону".

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

Щоб перевірити або змінити його в SSMS, перейдіть до Безпека -> Входи та клацніть правою кнопкою миші ім'я користувача того користувача, який запускає запити. Виберіть властивості -> загальне та переконайтеся, що мова за замовчуванням внизу діалогового вікна відповідає вашим очікуванням.

Повторіть це для всіх користувачів, які запускають запити.


1
Це мені допомогло. Просто невелика виправлення: мова за замовчуванням server loginне db user. top-password.com/blog/…
Баз Гувенкая

1
Оскільки він встановлений у програмному коді, і я не мав доступу до коду, я змінив його з Englishна, British Englishі він спрацював!
vaheeds

1
Те ж саме для мене, аби змінити англійську на британську - Алі, ти врятував життя!
david-giorgi


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 призводило до виходу за межі діапазону значення'. ВИБЕРІТЬ КОНВЕРТ (дата-час, 'yourdate') З [вашої таблиці], де ISDATE ('yourdate') = 1 збережено день :)
J Pollack

2

Я теж зіткнувся з цією проблемою, коли автоматично вставляв sysdate до стовпця.

Що я зробив, так це змінив формат системної дати, щоб він відповідав формату дати SQL-сервера. Наприклад, для мого формату SQL було вказано mm / dd / yyyy, а для мого системного формату встановлено dd / mm / yyyy. Я змінив системний формат на мм / дд / рррр, і помилка зникла

-кб


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

2

Тест для року> 2079. Я виявив, що користувач набрав 2106 замість 2016 року (10.12.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 00:00:00 AM в коді, враховуючи той факт, що DateTime в C # ініціалізується цією датою та часом, якщо не встановлено інакше. І найменш можливою датою, дозволеною для типу даних MS-SQL 2008 datetime, є 1753-01-01 00:00:00.

Я змінив дату з коду та встановив її на 01.01.1900, і більше не повідомлялося про помилки.


0

Я використовував ToString () на дату з мм замість MM.


0

Просто переконайтеся, що ваші дати сумісні або їх можна належним чином запустити у вашому менеджері баз даних (наприклад, SQL Server Management Studio). Наприклад, функція DateTime.Now C # недійсна на сервері 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.