2013-03-26 6 views
0

У меня есть база данных, где столбец даты сохраняется как тип nvarchar, а формат даты - dd/mm/yyyy (англ.). Я пытаюсь сделать запрос выбора для поиска данных, помещенных между двумя датами.Преобразование String to Date и сравнение дат

Этот запрос:

SELECT * FROM table 
    WHERE CONVERT(datetime,postdate,103) BETWEEN ? AND ? 

Я преобразовал мое поле в дату, но всякий раз, когда я пытаюсь работает мой запрос, я получаю сообщение об ошибке

java.lang.Exception: com.microsoft.sqlserver .jdbc.SQLServerException:
преобразование типа данных NVARCHAR к типу DateTime данных привело к значению вне-диапазона

Когда я запустить IsDate запрос:

SELECT * FROM table WHERE ISDATE(postdate)=0 

Строка с датой 18/02/2013 показана. Если я не ошибаюсь, это означает, что рассматривается как месяц.

Как я могу в принципе преобразовать свое поле в действительную дату и сравнить даты?

ответ

-1

при получении даты из базы данных вы получаете дату в формате java.sql.date!

Вам необходимо его преобразовать в java.util.date!

это можно сделать, используя следующий код

java.util.Date utilDate = new java.util.Date(SQLDate.getTime()); 

попробовать и это будет сделано !!

+1

Это не проблема Java. Это чисто SQL. Java только генерирует исключение – MaxI

3

Первой проблемой является сохранение даты в столбце строки. Почему вы не используете 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

Смежные вопросы