SQL - konwersja typu danych varchar na typ danych typu data / godzina spowodowała, że ​​wartość spoza zakresu

88

Otrzymuję następujący błąd podczas uruchamiania kodu SQL w celu przekonwertowania wartości typu danych z varcharna datetime.

Msg 242, poziom 16, stan 3, wiersz 1 Konwersja typu danych varchar na typ danych typu data i godzina spowodowała, że ​​wartość spoza zakresu.

Sprawdziłem dane i nie widzę nic dziwnego: uruchomiłem następujące sprawdzenia i wszystkie nie zwróciły żadnych wyników

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

Czy jest coś jeszcze, na co warto zwrócić uwagę i być może warte wskazówek lub pomocy w tej kwestii? Wydaje się, że nie mogę tego zrozumieć.

user23495
źródło
3
Jaki jest typ danych w kolumnie daty? Czy możesz mi pokazać schemat tabeli i stwierdzenie, że błąd występuje na proszę?
Spikeh
3
która z sześciu podanych instrukcji SQL nie działa?
Mureinik
1
Wszystkie sześć stwierdzeń działa i nie weryfikuje żadnych problemów z danymi.
user23495
3
nie sprawdzałeś pod kątem nieprawidłowych dat, np. 2013-10-31 lub 2013-02-30. Prawdopodobnie błąd, z którym się spotykasz, odnosi się do tego rodzaju problematycznych dat
Dalen
2
Cześć Dalen, sprawdziłem to. Sposób konfiguracji danych to 31.10.2013, 30.10.2013. Jest w formacie brytyjskim. Czy będzie to miało jakiś wpływ podczas próby zmiany typu kolumny, nie sądziłem, że tak.
user23495

Odpowiedzi:

84

Tydzień temu stanąłem przed tym samym problemem. Problem tkwi w ustawieniu strefy czasowej. Określ w innych formatach, takich jak mm / dd / rrrr (zwykle działa).

Podanie daty jako 30/12/2013 spowodowało u mnie błąd. Jednak określenie go jako formatu mm / dd / rrrr zadziałało.

Jeśli chcesz przekonwertować dane wejściowe, możesz spróbować spojrzeć na CONVERTmetodę. Składnia to

CONVERT(VARCHAR,@your_date_Value,103)

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

Końcowe 103 to format daty i godziny.

Skorzystaj z tego linku, aby uzyskać informacje o formatach konwersji i dalsze czytanie. https://www.w3schools.com/sql/func_sqlserver_convert.asp

Mahe
źródło
1
Dzięki za pomoc. Próbowałem to przekonwertować, ale nadal nie miałem szczęścia. Czy może to być spowodowane tym, że tabela jest nadal varchar lub cokolwiek innego, co może spowodować niepowodzenie?
user23495
2
Byłoby bardzo pomocne, gdybyś opublikował swoje przykładowe dane (które są w tabeli). W komentarzu powiedziałeś, że chcesz go w formacie rrrr-mm-dd. Więc spróbuj tego SELECT CONVERT(char(10), GetDate(),126). Po prostu zastąp GETDATE () wymaganą wartością.
Mahe
61

Wpadłem na ten problem z powodu głupiej pomyłki. Upewnij się, że data faktycznie istnieje!

Na przykład:

31 września 2015 nie istnieje.

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

Więc to kończy się niepowodzeniem z komunikatem:

Error converting data type varchar to datetime.

Aby to naprawić, wprowadź prawidłową datę:

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

I działa dobrze.

Pan C.
źródło
2
Tak, właśnie znalazłem datę wygaśnięcia 29 lutego 2015 w bazie danych, z którą muszę pracować. Ciekawe, jak to się tam dostało. Zastanawiam się, ile ich tam jest więcej ...
Zasoby
4
Po prostu użyłem cast (SUBSTRING ([MyDateField], 1,2) as integer)> 31 i znalazłem rekord z 60. grudnia. Kto w to wchodzi, doktorze Suess?
SteveCav
3
Dzięki! To był mój problem. Miałem złe dane w swoim zestawie - 01.01.1113, haha.
Sev09
2
Dla mnie podczas formatowania daty w celu zbudowania instrukcji SQL wstawiłem zły ciąg formatu. Użyłem, Format(DateTime.Now, "yyyymmdd")kiedy powinnoFormat(DateTime.Now, "yyyyMMdd")
Jay Imerman,
1
Argh Amerykańskie konwencje randkowe! Trochę się potknąłem, bo „26 października 2017” tj. „26-10-2017” to całkowicie aktualna data :)
Antimony
29

Niedawno miałem podobny problem. Ustawienia regionalne zostały poprawnie skonfigurowane zarówno w aplikacji, jak i na serwerze bazy danych. Jednak wykonanie SQL spowodowało

„Konwersja typu danych varchar na typ danych typu data / godzina spowodowała uzyskanie wartości spoza zakresu”.

Problemem był domyślny język użytkownika db.

Aby sprawdzić lub zmienić to w SSMS, przejdź do Security -> Logins i kliknij prawym przyciskiem myszy nazwę użytkownika, który uruchamia zapytania. Wybierz właściwości -> ogólne i upewnij się, że domyślny język u dołu okna jest taki, jakiego oczekujesz.

Powtórz to dla wszystkich użytkowników, którzy uruchamiają zapytania.

ali
źródło
1
To mi pomogło. Tylko mała poprawka: domyślny język server loginnot db user. top-password.com/blog/…
Baz Guvenkaya
1
Ponieważ został ustawiony w kodzie programu i nie miałem dostępu do kodu, zmieniłem go z Englishna British Englishi działa!
vaheeds
1
To samo dla mnie, ahd zmienić angielski na brytyjski angielski - Ali, ratujesz życie!
david-giorgi
10

Możesz skorzystać z

Set dateformat <date-format> ;

w twojej funkcji sp lub procedurze składowanej, aby załatwić sprawę.

Sachin Mishra
źródło
1
To rozwiązało mój problem. Nie rozumiem tylko, dlaczego to zaczyna się nagle dziać :(
VictorEspina
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)))
sonu yadav
źródło
5
Dodaj więcej opisu do swojej odpowiedzi. Pomoże to pytającemu w zrozumieniu Twojej odpowiedzi.
Pramod S. Nikam
2

Miałem ten sam problem i ustaliłem, że pojawia się on, ponieważ SQL Server nie przeprowadza porównań znaków przekonwertowanych na liczby całkowite w identyczny sposób. W moim teście odkryłem, że niektóre porównania przekonwertowanych znaków, takie jak wykrzyknik, zwrócą błędy konwersji typu, podczas gdy inne porównania przekonwertowanych znaków, takie jak spacja, zostaną określone jako poza zakresem.

Ten przykładowy kod testuje różne możliwe scenariusze i przedstawia rozwiązanie przy użyciu zagnieżdżonych instrukcji REPLACE. REPLACE określa, czy w ciągu znajdują się znaki, które nie są cyframi ani ukośnikiem, a jeśli takie istnieją, długość ciągu będzie większa od zera, co oznacza, że ​​istnieją „złe” znaki, a data jest nieprawidłowa .

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

Wynik:

--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
RSax
źródło
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
shashank m
źródło
Wystąpił problem z wierszem z ciągiem daty „19610010” (format: RRRRMMDD), co spowodowało błąd „Konwersja typu danych nvarchar na typ danych typu data-godzina spowodowała wystąpienie wartości spoza zakresu”. SELECT CONVERT (datetime, 'yourdate') FROM [yourtable] WHERE ISDATE ('yourdate') = 1 zapisany dzień :)
J Pollack
2

Ja też napotkałem ten problem podczas automatycznego wstawiania sysdate do kolumny.

Zmieniłem format daty w systemie, aby dopasować go do formatu daty serwera SQL. np. mój format SQL to mm / dd / rrrr, a mój format systemowy to dd / mm / rrrr. Zmieniłem format systemu na mm / dd / rrrr i błąd zniknął

-kb

user5714464
źródło
2

Jak wiesz, jest to kwestia formatu brytyjskiego. Możesz dokonać konwersji daty pośrednio za pomocą funkcji.

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

Aby wywołać tę funkcję

SELECT dbo.ChangeDateFormatFromUK([dates]) from table

Konwertuj go normalnie na datę i godzinę

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

W Twoim przypadku możesz to zrobić

SELECT [dates] from table where CONVERT(DATETIME,dbo.ChangeDateFormatFromUK([dates])) > GetDate()   -- or any date
Sumit
źródło
2

Test na rok> 2079. Odkryłem, że użytkownik wpisał 2106 zamiast 2016 w roku (10/12/2106) i boom; więc w dniu 10/12/2016 przetestowałem i stwierdziłem, że SQL Server zaakceptował do 2078, zacząłem zgłaszać ten błąd, jeśli rok jest 2079 lub wyższy. Nie przeprowadziłem żadnych dalszych badań dotyczących tego, jakiego rodzaju przesunięcie daty robi SQL Server.

Gordon
źródło
1

Po prostu przekonwertowałem pole varchar, które chciałem przekonwertować na nową tabelę (ze złożonym DateTime) na układ zgodny z DateTime, a następnie SQL bez problemów dokona konwersji z varchar na DateTime.

W poniższej tabeli (nie w mojej utworzonej tabeli z tymi nazwami!) Po prostu ustawiam pole varchar tak, aby było podobne do DateTime, jeśli chcesz:

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)  
Andre
źródło
1
Varchar Date Convert to Date and Change the Format

12 listopada 2016 12:00, 21.12.2016, 21-12-2016 to zapytanie działa dla powyższego, aby zmienić na ten format dd / MM / rrrr SELECT [Member_ID],[Name] , Convert(varchar(50),Convert(date,[DOB],103),103) as DOB ,[NICNO],[Relation] FROM [dbo].[tbl_FamilMember]

Khalid
źródło
0

Ten błąd wystąpił dla mnie, ponieważ próbowałem zapisać minimalną datę i godzinę w kolumnie przy użyciu zapytań wbudowanych bezpośrednio z kodu C #.

Zmienna daty została ustawiona na 01/01/0001 12:00:00 w kodzie, biorąc pod uwagę fakt, że DateTime w C # jest inicjowana tą datą i godziną, jeśli nie jest ustawiona w inny sposób. Najmniejsza możliwa data dozwolona w typie daty i godziny MS-SQL 2008 to 1753-01-01 12:00:00.

Zmieniłem datę z kodu i ustawiłem na 01/01/1900 i żadne błędy nie zostały dalej zgłoszone.

Talha Imam
źródło
0

Użyłem ToString () w dniu z mm zamiast MM.

L0uis
źródło
0

Po prostu upewnij się, że Twoje daty są zgodne lub mogą być poprawnie uruchomione w menedżerze bazy danych (np. SQL Server Management Studio). Na przykład funkcja DateTime.Now C # jest nieprawidłowa w SQL Server, co oznacza, że ​​zapytanie musi zawierać prawidłowe funkcje, takie jak GETDATE () dla SQL Server.

Ta zmiana zadziałała idealnie dla mnie.

tonderaimuchada
źródło
0

Nieco nietypowa przyczyna tego problemu, ale na wypadek, gdyby ktoś tego potrzebował. Kod, nad którym pracowałem, używał:

java.text.DateFormat.getDateTimeInstance()

aby uzyskać formatter daty. Wzorzec formatowania zwrócony przez to wywołanie zmienił się z Java 8 na Java 9, jak opisano w tym raporcie o błędzie: https://bugs.openjdk.java.net/browse/JDK-8152154 najwyraźniej formatowanie, które zwracał, było dla mnie nieodpowiednie dla bazy danych. Zamiast tego rozwiązanie było następujące:

DateTimeFormatter.ISO_LOCAL_DATE_TIME
wobblycogs
źródło