0

我有一个数据库,其中日期列保存为 nvarchar 类型,日期格式为dd/mm/yyyy(英国)。我正在尝试执行选择查询来搜索两个日期之间发布的数据。

查询是:

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。如果我没记错的话,这意味着18被视为一个月。

如何基本上将我的字段转换为有效日期并比较日期?

4

2 回答 2

3

第一个问题是您将日期存储在字符串列中。你为什么不使用DATEor 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 格式中,如果是这种情况,您也可能拥有看似有效但输入 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而不是开放式范围的潜在问题。请阅读以下帖子:

于 2013-03-26T11:09:07.660 回答
-1

当您从数据库中检索日期时,您将获得 java.sql.date 格式的日期!

您现在需要将其转换为 java.util.date!

可以使用以下代码来完成

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

试试吧,它会完成的!

于 2013-03-26T11:07:59.730 回答