2009-07-16 13 views
10

Mam jedną zmienną char (8) sformatowaną jako ddmmyyyy w procedurze przechowywanej (jakość i ważność tej wartości jest nieznana i poza moją kontrolą). Jaki jest najlepszy najbardziej efektywny sposób przeniesienia wartości do zmiennej datetime i wygenerowania błędu, jeśli nie jest to poprawna data-godzina.najlepszy sposób konwertowania i sprawdzania ciągu daty

DECLARE @Source  char(8) 
DECLARE @Destination datetime 

SET @Source='07152009' 

--your solution here 


SELECT @Destination 

tutaj jest najlepszym sposobem mogę myśleć:

DECLARE @Source    char(8) 
DECLARE @Temp    varchar(10) 
DECLARE @Destination  datetime 

set @Source='07152009' 
SET @Temp=LEFT(@Source,2)+'/'+SUBSTRING(@Source,3,2)+'/'+RIGHT(@Source,4) 

IF ISDATE(@Temp)!=1 
BEGIN 
    RAISERROR('ERROR, invalid date',16,1) 
END 
SET @[email protected] 

SELECT @Source AS Source, @Temp AS Temp, @Destination AS Destination 

EDIT oto co mam zamiar iść z ...

DECLARE @Source    char(8) 
DECLARE @Destination  datetime 

set @Source='07152009' 
BEGIN TRY 
    SET @Destination=CONVERT(datetime,RIGHT(@Source,4)  -- YYYY 
             +LEFT(@Source,2)  -- MM 
             +SUBSTRING(@Source,3,2) -- DD 
          ) 
END TRY 
BEGIN CATCH 
    PRINT 'ERROR!!!' --I'll add a little more logic here and abort processing 
END CATCH 

SELECT @Source AS Source, @Destination AS Destination 
+0

wydaje się dobre dla mnie, to co bym napisał też. Jestem ciekaw, czy jest lepszy. –

Odpowiedz

12

Przede wszystkim, ponieważ używasz programu SQL Server 2005, powinieneś umieścić kod, który może zawieść w bloki BEGIN TRY.....END TRY BEGIN CATCH....END CATCH - try/catch bloki dla T-SQL!

drugie, data dla wszystkich manipulacji, chciałbym zawsze użycie ISO-8601 format która będzie działać niezależnie od tego, co obecny format daty jest ustawiony w SQL Server. Format

ISO-8601 jest właśnie dla YYYYMMDD daty lub YYYY-MM-DDTHH:MM:SS na bieżąco z czasem - tak bym napisać kod jako:

BEGIN TRY 
    SET @Source='07152009' 
    SET @Temp = RIGHT(@Source, 4) +    -- YYYY 
       LEFT(@Source, 2) +    -- MM 
       SUBSTRING(@Source, 3, 2)  -- DD 

    IF ISDATE(@Temp)!=1 
    BEGIN 
     RAISERROR('ERROR, invalid date',16,1) 
    END 

    SET @Destination = CAST(@Temp AS DATETIME) 
END TRY 
BEGIN CATCH 
     -- handle error if something bombs out 
END CATCH 

nie należy liczyć na jakiś konkretny format daty jest ustawiony !! Wyślij mi swój kod, a spróbuję go na systemie szwajcarsko-niemieckim - prawie gwarantuję, że się zepsuje, jeśli ślepo założysz "en-US", a więc "mm/dd/rrrr" - to jest , a nie to samo ustawienie wszędzie na tej planecie.

Niestety, SQL Server jest raczej słabym terminem obsługi - może to być punkt rozszerzenia, w którym użycie zestawu CLR w SQL Server miałoby sens, aby wykorzystać znacznie bogatsze funkcje obsługi daty w .NET?

Marc

PS: Wydaje formacie ISO-8601 Wiedziałem YYYY-MM-DD nie zawsze działa w SQL Server - wbrew temu, co Books Online wydaje się nauczać. Zamiast tego użyj YYYYMMDD lub YYYY-MM-DDTHH: MM: SS.
Dzięki, gbn!

+0

To jest ANSI nie jest ISO. ISO byłoby "1998-02-23T14: 23: 05" – gbn

+0

... bez "T" i czasu, rrrr-mm-dd domyślnie ANSI – gbn

+0

Mój system jest w kontrolowanym środowisku, nie będzie szwajcarsko-niemieckiej daty problemy z konwersją. Podoba mi się idea try-catch.Prawdopodobnie usuniemy IF ISDATE() i @Temp, a następnie wychwycę błąd konwersji, jeśli wystąpi SET @ Destination = LEFT (@ Source, 2) + '/' + SUBSTRING (@ Source, 3,2) + '/' + RIGHT (@ Source, 4) –

6

Możesz zagwarantować polecenie data-miesiąc-rok, używając SET DATEFORMAT. Oznacza to, że ISDATE będzie analizować "15 -07-2009" jako 15 lipca 2009

W przeciwnym razie twoje podejście jest wystarczająco dobre, biorąc pod uwagę zewnętrzne ograniczenia ... ale możesz też zmienić kolejność na ANSI/ISO.

Po odpowiedź marc_s': "SET dateformat DMY" działa dla większości ustawień europejskich ...

OK:

SET LANGUAGE british 
SELECT ISDATE('2009-07-15') --this is ansi says marc_s. It gives "zero" 
SELECT ISDATE('2009-07-15T11:22:33') --this really is ANSI and gives true 


SET LANGUAGE german 
SELECT ISDATE('2009-07-15') --false 
SELECT ISDATE('2009-07-15T11:22:33') --true 
+0

ustalono - dla większości - ale dlaczego nie zastosować formatu ISO-8601, który działa dla WSZYSTKICH ustawień SET DATEFORMAT? Po prostu zagraj w sejfie ..... –

+0

ISO-8601 działa dla wszystkich ustawień, ale nie jest to ISO: to ANSI, który podałeś http://stackoverflow.com/questions/1135746/sql-server-convert-string-to- datetime – gbn

+0

MS Books Online wydaje się nie zgadzać: http://msdn.microsoft.com/en-us/library/ms190977%28SQL.90%29.aspx –

Powiązane problemy