2011-07-30 11 views
20

Chcę zaoferować użytkownikowi możliwość wprowadzenia niekompletnych dat (na przykład tylko rok 2005 lub styczeń 1998), ale także uzupełnić daty z roku, miesiąca, dnia. Czy mogę to zrobić za pomocą pojedynczego pola daty w DB?Przechowuj niepełną datę w polu daty MySQL

Próbowałem UPDATE tableA SET mydate = '2001-00-00' i wydaje się, że działa (bez błędów), ale nie jestem pewien, czy to jest poprawne. Wewnętrznie zakładam, że używany jest znacznik czasu, więc w jaki sposób MySQL może reprezentować te 0?

+0

Co otrzymujesz, gdy zapytasz 'SELECT mydate FROM tableA'? – phlogratos

+0

Prawidłowa wartość, tj. 2001-00-00. Martwię się tylko, że nie używam jakiegoś standardowego zachowania, które opiera się na jakiejś sztuczce, która może kiedyś się zepsuć lub nie działać w pewnych okolicznościach. –

Odpowiedz

22

Jest mała uwaga w documentation for the DATE_FORMAT() o MySQL pozwala niekompletne terminach:

zakresy miesiąc i dzień specyfikatorami zacząć od zera ze względu na faktu, że MySQL pozwala na przechowywanie niekompletnych terminach takich jak ' 2014-00-00 ".

Jak podkreślił @wonk0, MySQL zestawy nieprawidłowe daty, aby 0000-00-00 00:00:00 gdy ALLOW_INVALID_DATES nie jest ustawiony. Jednak nawet jeśli ALLOW_INVALID_DATES nie jest ustawiony, wstawienie prawidłowego roku z ustawionym miesiącem i dniem nie wydaje się powodować takiego zachowania - przynajmniej nie w moim testowaniu (MySQL 5.1.54-1ubuntu4). Użyłem tej funkcji przedtem bez żadnego problemu, ale do tej pory nie mogłem znaleźć bardziej szczegółowej dokumentacji opisującej to zachowanie w całości.

Porównywanie dat/godzin również działa zgodnie z oczekiwaniami: na przykład 2011-01-00 > 2011-00-00 i 2011-00-01 > 2011-00-00 wykonaj, jak można się spodziewać.

UPDATE

Zobacz this answer (przez innego Mike) do podobnego pytania. Wskazuje to na wyciągu z The Definitive Guide do MySQL 5:

W starszych wersjach MySQL, datę i typy danych DateTime nie tylko ograniczoną ilość typu kontroli. Wartości między 0 a 12 dla miesięcy, a 0 i 31 dla dni były ogólnie dozwolone. Jednak jest to odpowiedzialność programu klienta za podanie prawidłowych danych. (Dla przykład 0 to wartości dopuszczalnej przez miesiąc lub dzień, w celu zapewniają możliwość przechowywania niekompletnych lub brak danych).

Począwszy MySQL 5.0.2, jest bardziej dokładna walidacji, tak , że tylko prawidłowe dane mogą być przechowywane. Nadal dozwolone są miesiące i wartości dni 0, a także data 0000-00-00.

+1

Czy założenie, że znacznik czasu jest używany do przechowywania daty, jest zatem niepoprawne? Ponieważ nie widzę sposobu, w jaki można reprezentować 2011-00-00 jako znacznik czasu. –

+1

@Omar Kohl: Tak, myślę, że to założenie jest nieprawidłowe. "TIMESTAMP" ma mniejszy zasięg niż "DATETIME". 'DATETIME' używa 8 bajtów, podczas gdy' TIMESTAMP' używa 4 bajty. Zobacz [Wymagania dotyczące pamięci typu danych] (http://dev.mysql.com/doc/refman/5.5/en/storage-requirements.html#id918335) – Mike

+1

Doskonała odpowiedź, najlepsza, którą odkryłem, szukając daleko i szeroko. –

2

Cóż, jeśli użyłeś pola daty, powinieneś oczekiwać tych 0. Jednym ze sposobów pozbycia się ich jest raczej skorzystanie z selekcji varchar. Jednak lepiej jest użyć pola daty, ponieważ to jest tam przechowywane.

Jeśli masz, aby użytkownicy mogli wejść niepełną datę to musi być varchar iw tym przypadku można formatować wejście ze skryptu i przechowywać w tej kolumnie

+0

To byłaby moja ostatnia deska ratunku. Oczywiście o rzeczy w formacie daty jest zawsze ładniejsza do zamawiania itp. –

+1

tak więc zamiast pozwalać użytkownikom na sformatowanie daty, radzę po prostu pozwolić sql, aby sformatować bieżący 'datetimestamp' tam – DaMainBoss

+0

+1 bardzo dobry punkt. Dats, co bym zrobił –

1

Przechowywanie części terminach zależy na Tryb sql działa w MySQL. Przeczytaj http://dev.mysql.com/doc/refman/5.1/en/server-sql-mode.html, w szczególności o błędnych datach w http://dev.mysql.com/doc/refman/5.1/en/server-sql-mode.html#sqlmode_allow_invalid_dates.

+1

"ALLOW_INVALID_DATES: Nie wykonuj pełnej kontroli dat. Sprawdź tylko, czy miesiąc mieści się w przedziale od 1 do 12, a dzień mieści się w przedziale od 1 do 31." W tym przypadku nie ma zastosowania, ponieważ ani miesiąc, ani dzień nie znajdują się w tym przedziale ... (00 oba) –

+0

'Sprawdź tylko, czy miesiąc mieści się w przedziale od 1 do 12, a dzień mieści się w przedziale od 1 do 31 "Dlaczego pozwala na miesiąc lub dzień 0? – phlogratos

Powiązane problemy