[MSSQL2005] Jak pobrać aktualny format daty?

0

Cześć, w swojej aplikacji często przekazuję do SQL różne daty w postaci stringa.
Oczywście na niektórych komputerach nie działa - no na serwerze jest inny format daty.

W związku z tym chcę pobrać format daty, jaki jest na serwerze, a potem przygotować stringa z datą w aplikacji właśnie w tym formacie, żeby nie było problemu.
Tylko, że nigdzie nie mogę znaleźć, jak pobrać aktualny format daty z serwera :|

Ktoś wie? A może ktoś ma inny pomysł na rozwiązanie mojego problemu oprócz zastosowania czasu w UTC? :)

0

Wystarczy castować na tym datetime i masz problem z głowy:

SELECT CAST('01-01-01' AS DATETIME);
SELECT CAST('2001-01-01' AS DATETIME);
SELECT CAST('01-01-2001' AS DATETIME);
SELECT CAST('01/01/01' AS DATETIME);
0

Adam niestety nie zawsze sam cast wystarczy - zależnie od ustawień dateformat funkcja castująca zadziała tak albo inaczej (np. pomyli miesiące z dniami).

Juhas, bieżący dateformat znajdziesz zapytaniem:

select date_format from sys.dm_exec_sessions where session_id = @@spid
0
tjj napisał(a)

Juhas, bieżący dateformat znajdziesz zapytaniem:

select date_format from sys.dm_exec_sessions where session_id = @@spid

Coś jest nie tak, bo zwraca mi mdy, podczas, gdy mam ymd

[dopisane]
Hmmm, wyświetlają mi się daty w formacie ymd, natomiast zainsertować mogę zarówno ymd, jak i mdy

[dopisane2]
Myślałem, że to nie będzie miało znaczenia, ale ma.
Powyższe zapytanie, jak już mówiłem zwraca mi mdy. Inserty mogę robić z datami w formacie mdy i ymd, natomiast select mi zwraca daty w formacie ymd. Co więcej, jeśli chcę użyć jakiegoś filtru, to w warunku muszę podać datę w formacie ymd, bo inaczej filtr nie działa. O co tu chodzi?

0

@tjj - no fakt ;)

@Juhas - proponuję przekazywać datę do MSSQL-a w taki sposób

DATEADD(MONTH,((@YEAR-1900)*12)+@MONTH-1,@DAY-1)
0
AdamPL napisał(a)

@tjj - no fakt ;)

@Juhas - proponuję przekazywać datę do MSSQL-a w taki sposób

DATEADD(MONTH,((@YEAR-1900)*12)+@MONTH-1,@DAY-1)

Właśnie tak robię, tzn. zrobiłem sobie taką funkcję.
Natomiast w kilku miejscach w kodzie, żeby zrobić jeden select, okazuje się, że muszę wykonać najpierw 4 inne :P
Dlatego cały czas myślę nad alternatywnym rozwiązaniem.

0

Juhas,

przekazuj datę normalnie np. '2010-03-15', z tym, że wcześnie ustaw sesji właściwy dateformat - powinno być OK. Jeżeli łączysz się z serwerem bazodanowym z aplikacji .netowej jeszcze lepszym rozwiązaniem jest stosowanie parametrów sqlowych (wtedy problem nigdy nie występuje).

Hmmm, wyświetlają mi się daty w formacie ymd, natomiast zainsertować mogę zarówno ymd, jak i mdy

To dlatego, że dateformat decyduje o tym, jak interpretować przekazywany ciąg znaków, a nie jak wyświetlać - wyświetana data zawsze będzie w formacie ODBC canonical. Jeśli chcesz wyświetlać datę w inny sposób użyj funkcji FORMAT.

0
tjj napisał(a)

Juhas,
przekazuj datę normalnie np. '2010-03-15', z tym, że wcześnie ustaw sesji właściwy dateformat - powinno być OK.

A mógłbyś powiedzieć, jak to zrobić? Bo z tego, co wiem SET DATEFORMAT ustawia format dla całego serwera. Łączę się ze zwykłej aplikacji Win32.

Moim celem jest uniezależnienie się od formatu dat. Aktualnie posługuję się tym, co wyżej, ale to długo trwa. W ostateczności będę chyba musiał przejść na czas w postaci liczby(UTC to się nazywa?), ale chcę uniknąć tego jak ognia :)

To dlatego, że dateformat decyduje o tym, jak interpretować przekazywany ciąg znaków, a nie jak wyświetlać - wyświetana data zawsze będzie w formacie ODBC canonical. Jeśli chcesz wyświetlać datę w inny sposób użyj funkcji FORMAT.

Tu mi się widzi takie rozwiązanie. Ustawić FORMAT daty, inserty dawać wg tego, co zwraca mi Twoje zapytanie. I tak samo przekazywać datę w selectach.

Teraz które z tych rozwiązań będzie najlepsze

0

SET DATEFORMAT przesłania sposób interpretowania daty tylko na poziomie sesji.

0
AdamPL napisał(a)

SET DATEFORMAT przesłania sposób interpretowania daty tylko na poziomie sesji.

OK rozumiem. Niemniej jednak nadal nie wiem, co zrobić z selectami.
Bo załóżmy, że mam format daty: dmy. Ale select zwraca mi ymd(konkretnie: 2010-01-31).
I jeśli ja teraz zrobię:

SELECT * FROM tabela WHERE data>'31-01-2010'

to zobaczę głupoty albo nic.

(Nie mogę i nie chcę użyć casta ani żadnego converta, bo z tego, co wyczytałem jest problem przy porównywaniu dat. Dodatkowo rodzi to tyle zmian, że człowiek może umrzeć). Najchętniej to chcę przekazać do zapytania odpowiednio sformatowaną datę.

0

@Juhas

Nie do końca jest tak jak myślisz - SET DATEFORMAT ustawia format dla połączenia (co zresztą widać przy próbie jego sprawdzenia - select date_format from sys.dm_exec_sessions where session_id = @@spid - zwraca dla każdej sesji osobny format).

Żeby móc przesyłać w insertach, update'ach itd. daty w formacie '2010-03-15' ustaw domyślny język użytkownika, po którym się łączysz na English (jeżeli jest ustawiony Polish i przesyłasz w tym formacie to dostaniesz out-of-range; możesz też, w przypadku kiedy język jest Polish i np. nie masz możliwości jego zmiany używać formatu d/m/yyyy - wtedy też powinno zadziałać).

Generalnie przypuszczam, że możesz mieć trzy problemy:

  1. w różnych fragmentach kodu wysyłasz daty w różnym formacie (np. '2010.11.03', '2010-11-03', '03-11-2010', etc.) - trzeba ujednolicić
  2. łączysz się do bazy po różnych użytkownikach, którzy mają różne ustawienia Default Language - j.w.
  3. tak jak napisałem wyżej - masz ustawione Polish a próbujesz przepchnąć yyyy-mm-dd

W razie problemów zajrzyj tu:
http://blogs.lessthandot.com/index.php/DataMgmt/DataDesign/setting-a-standard-dateformat-for-sql-se

Tu mi się widzi takie rozwiązanie. Ustawić FORMAT daty, inserty dawać wg tego, co zwraca mi Twoje zapytanie. I tak samo przekazywać datę w selectach.

Nie bardzo rozumiem co masz na myśli - ustaw poprawnie Default Language wtedy będziesz mógł zawsze stosować jeden format daty.
W przypadku zaciągania danych z bazy (czyli select) powinieneś pobierać ją tak, jak jest (czyli jako zmienną datetime, a formatować do odpowiedniego tekstu na poziomie aplikacji klienckiej)

0
tjj napisał(a)

Generalnie przypuszczam, że możesz mieć trzy problemy:

  1. w różnych fragmentach kodu wysyłasz daty w różnym formacie (np. '2010.11.03', '2010-11-03', '03-11-2010', etc.) - trzeba ujednolicić

Problem jest taki, że u mnie działa ;)
Ale u niektórych klientów program wywala właśnie out of range. Dlatego trzeba uniezależnić się od formatu daty, jaki jest na serwerze.

Czyli radzisz ustawić język na us_english i operować datami w formacie: yyyy-mm-dd, tak?
Zobaczymy, czy to pomoże, mam nadzieję, że tak.

0

Tak myślę, że to powinno załatwić sprawę.

W ogóle to podtrzymuję to, co pisałem wcześniej - w zapytaniach (obiekty SqlCommand, OleDbCommand, etc.) używaj parametrów, np.:

using (SqlConnection conn = new SqlConnection(_conn))
{
    conn.Open();
    SqlCommand cmd = new SqlCommand("exec getCalendarEvents @date", conn);
    cmd.Parameters.Add(new SqlParameter("date", DateTime.Today));
    SqlDataReader dr = cmd.ExecuteReader();
    
    //.....

    conn.Close();
}

W tym kodzie provider sam zadba o właściwe przekazanie obiektu DateTime.

0

@Juhas

Bo załóżmy, że mam format daty: dmy. Ale select zwraca mi ymd(konkretnie: 2010-01-31).
I jeśli ja teraz zrobię:

SELECT * FROM tabela WHERE data>'31-01-2010'

A nie możesz trzymać czasu w bazie w formacie uniksowym? Wystarczy na to zwykły Integer, no i tak jest chyba najbardziej uniwersalnie.

0

Panowie nie modyfikujcie postów, bo zwariować można :/
Żeby zapytanie
SELECT * FROM tabela WHERE data>'31-01-2010'
działało zmień Default Language usera na English i przestaw kolejność:
SELECT * FROM tabela WHERE data>'2010-01-31'
albo zastosuj parametry...

0
GhostDog napisał(a)

A nie możesz trzymać czasu w bazie w formacie uniksowym?

Myślałem o tym jako ostateczność. To się wiąże ze zmianą całej bazy i dodatkowymi problemami(np. trzaby było napisać funkcje konwertujące to na coś czytelnego dla człowieka).

Na razie zostaję przy ustawianiu języka i przekazywaniu w odpowiednim formacie. Po mojemu to wystarczyło.

1 użytkowników online, w tym zalogowanych: 0, gości: 1