Первой проблемой является сохранение даты в столбце строки. Почему вы не используете DATE
или DATETIME
? Если вы делаете это, чтобы сохранить свой формат d/m/y, STOP делает это. Формат - это ответственность уровня представления и не должен влиять на хранение. Кроме того, почему вы используете NVARCHAR
? Какие символы вы ожидаете в своих литературе даты, которые потребуют Unicode?
Далее следует, что у вас нет правильной проверки, и плохие данные попали в вашу колонку. Вы можете определить это плохие данные следующим образом:
SET DATEFORMAT DMY;
SELECT * FROM dbo.table
WHERE ISDATE(postdate) = 0;
Теперь исправить эти данные, либо обновить его, когда вы знаете, что это такое, или установки этих строк NULL
, пока запрос не возвращает 0 строк.
Обратите внимание, что вы можете иметь данные, такие как 11/13/2013, которые, очевидно, не в D/M/Y fomrat, и если это так, вы могли бы также иметь данные, которые кажется действительным, но сделал пользователь, который вступил 06/09/2013 означает 9 июня или 6 сентября? Как вы можете быть уверены?
Самый безопасный способ предотвратить эту проблему, не повторялись завтра, вероятно, будет добавить новый столбец, над переместить данные, удалить старую колонку, и остановка с использованием строки на всех слоях.
ALTER TABLE dbo.table
ADD d DATE;
UPDATE dbo.table
SET d = CONVERT(DATETIME, postdate, 103);
ALTER TABLE dbo.table
DROP COLUMN postdate;
EXEC sp_rename N'dbo.table.d', N'postdate', N'COLUMN';
Вы можете быть в состоянии сделать это инлайн без всего этого свопинга следующим образом:
SET DATEFORMAT DMY; -- the key you missed in your attempt I think
ALTER TABLE dbo.table ALTER COLUMN postdate DATE;
Если вы не можете исправить саму колонку, то, по крайней мере, рассмотреть вопрос о добавлении проверочного ограничения и некоторые проверки вокруг этого столбца, чтобы плохие данные не возвращались туда завтра. Например:
ALTER TABLE dbo.table
ADD CONSTRAINT prevent_bad_dates
CHECK (CONVERT(DATE, postdate, 103) >= '19000101');
Ваша проверка еще до введения, если вы берете параметр VARCHAR в вашей хранимой процедуры, которая выполняет вставку:
ALTER PROCEDURE dbo.whatever
@postdate NVARCHAR(10), -- assuming here
@other_params...
AS
BEGIN
SET NOCOUNT ON;
SET DATEFORMAT DMY;
IF ISDATE(@postdate) = 0
BEGIN
RAISERROR('Incorrect format for date: %s.', 11, 1, @postdate);
RETURN;
END
... perform insert...
END
Этот еще не поможет вам понять, является ли пользователь, который ввел 06/09/2013
, означал 9 или 6 сентября. Поэтому я призываю вас принять эту бесплатную входную информацию от ваших пользователей и заставить их использовать элемент управления календарем или сборщик дат или что-то в этом роде , вы можете полностью контролировать формат. Если вам нужно отправить строковые литералы на SQL Server, самый безопасный формат будет YYYYMMDD
. Также вы должны знать о потенциальных проблемах с использованием BETWEEN
вместо открытого диапазона. Пожалуйста, прочитайте следующие сообщения:
http://sqlblog.com/blogs/aaron_bertrand/archive/2009/10/16/bad-habits-to-kick-mishandling-date-range-queries.aspx
http://sqlblog.com/blogs/aaron_bertrand/archive/2011/10/19/what-do-between-and-the-devil-have-in-common.aspx
Это не проблема Java. Это чисто SQL. Java только генерирует исключение – MaxI