将 varchar 转换为缺少时间的日期时间时,按结果排序超出范围

Order by results are out-of-range when converting varchar to datetime with missing time

我在 log-db 中有一个 varchar 行,通常看起来像 17.09.2020 00:00:01 我可以 CAST() 它到 datetime 并按它排序没有问题,例如这个简化的查询:

SELECT CAST(my_date_and_time AS datetime)
FROM my_table
ORDER BY CAST(my_date_and_time AS datetime) DESC

现在的问题是,今晚我在 00:00:00 处得到了一个日志条目,并且日志脚本或数据库从 varchar 字段中截断了时间,所以现在它只包含 17.09.2020 而不是 17.09.2020 00:00:00。 当我尝试将其转换为 datetime 时,会出现超出范围的错误,可能是因为缺少时间部分?

不幸的是,我无法访问日志脚本来更改它。 那么有什么方法可以将其转换为查询中可用的格式吗?

编辑: 下面是 my_date_and_time 行的示例:

|---------------------|
|   my_date_and_time  |
|---------------------|
| 17.09.2020 05:29:53 |
|---------------------|
| 17.09.2020 00:02:11 |
|---------------------|
|      17.09.2020     |  
|---------------------|
| 16.09.2020 23:59:38 |
|---------------------|
| 16.09.2020 23:59:18 |
|---------------------|

EDIT2: 通过进一步测试,我能够进一步缩小错误范围。这不是因为最初假设的时间戳没有时间信息。该问题实际上影响了不合规的记录。

这些数据记录月份前面少了0,年份后面多了一个点 例如16.9.2020. 14:22:23

我差点把编程这个的人的脑袋扯下来..

有没有什么办法可以通过查询得到正确的值呢?

对造成的误解深表歉意,并感谢迄今为止为解决问题做出贡献的所有人

正如我在评论中提到的,您真的应该修复数据类型。

如果您的所有日期 都是 格式 dd.MM.yyyy hh:mm:ss 那么您可以使用 CONVERT 和样式代码来转换它们,而不管设置如何:

SELECT TRY_CONVERT(datetime,Your_varchar,103)
FROM dbo.YourTable;

如果有 return NULL 它们要么具有值 NULL,要么无法转换。

但回到修复您的数据。

首先,让我们在一个新专栏中这样做:

ALTER TABLE dbo.YourTable ADD Actual_date_and_Time datetime NULL

现在我们可以 UPDATE 通过覆盖值来 UPDATE 该值:

UPDATE dbo.YourTable
SET Actual_date_and_Time = TRY_CONVERT(datetime,Varchar_Date_and_time,103);

然后您可以查询实际的 datetime 列。

然后您可以查看您的新数据,看看是否有问题,并进行修改:

SELECT Varchar_Date_and_time
FROM dbo.YourTable
WHERE Varchar_Date_and_time IS NOT NULL
  AND Actual_date_and_Time;

然后,最后,您可以 DROP 旧列并重命名新列(如果需要):

ALTER TABLE dbo.YourTable DROP COLUMN Varchar_Date_and_time;
EXEC sys.sp_rename N'dbo.YourTable.Actual_date_and_Time',N'Varchar_Date_and_time','COLUMN';

让我们试试 convert 函数 (Date and Time Conversions Using SQL Server):

declare @my_date_and_time  varchar(19) = '17.09.2020 00:00:01';

select convert(date, @my_date_and_time, 104)

或尝试将 dateformat 设置为 dmy (day/month/year):

set dateformat dmy

declare @my_date_and_time  varchar(19) = '17.09.2020 00:00:01';

select cast(@my_date_and_time as date)