我有一个数据库,其中date列保存为nvarchar类型,日期格式为dd/mm/yyyy
(英国)。我正在尝试执行选择查询以搜索在两个日期之间发布的数据。
查询是:
SELECT * FROM table
WHERE CONVERT(datetime,postdate,103) BETWEEN ? AND ?
我已将我的字段转换为日期时间,但每当我尝试运行查询时,我都会收到错误
java.lang.Exception:com.microsoft.sqlserver.jdbc.SQLServerException:
将nvarchar数据类型转换为日期时间数据类型会导致超出范围的值
当我运行isDate查询时:
SELECT * FROM table WHERE ISDATE(postdate)=0
显示日期为18/02/2013
的行。如果我没有错,这意味着 18 被视为一个月。
我如何基本上将我的字段转换为有效日期并比较日期?
答案 0 :(得分:3)
第一个问题是您将日期存储在字符串列中。你为什么不使用DATE
或DATETIME
?如果您这样做是为了保留您的d / m / y格式,请停止这样做。格式是表示层的责任,不应影响存储。另外,你为什么要使用NVARCHAR
?您期望在需要Unicode的日期文字中使用哪种符号?
接下来是您没有进行适当的验证,并且您的列中的错误数据已经结束。您可以按如下方式识别此错误数据:
SET DATEFORMAT DMY;
SELECT * FROM dbo.table
WHERE ISDATE(postdate) = 0;
现在,通过在知道数据时更新数据或将这些行设置为NULL
来修复该数据,直到查询返回0行。
请注意,您可能拥有类似于11/13/2013的数据,这显然不在D / M / Y fomrat中,如果是这种情况,您也可能拥有似乎<的数据/ strong>有效,但输入06/09/2013的用户是指6月9日还是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
的用户是指6月9日还是9月6日。因此,我强烈建议您从用户手中取出写意的临时条目并强制他们使用日历控件或日期选择器等,这样您可以完全控制格式。如果需要将字符串文字发送到SQL Server,最安全的格式将是YYYYMMDD
。此外,您应该了解使用BETWEEN
而不是开放式范围的潜在问题。请阅读以下帖子:
答案 1 :(得分:-1)
当您从数据库中检索日期时,您将以java.sql.date格式获取日期!
您现在需要将其转换为java.util.date!
可以使用以下代码
完成java.util.Date utilDate = new java.util.Date(SQLDate.getTime());
试试吧,它会完成!!