'Conversion failed when converting date and/or time from character string.DB-Lib error message 241,

解决Python与SQLServer时间类型不匹配问题
本文介绍了一种在使用pymssql模块连接SQLServer数据库时遇到的时间类型不匹配错误,并提供了两种解决方案:一是调整Python datetime格式以符合数据库要求;二是更改数据库字段类型。

用pymssql 连接SqlServer数据库后,向数据库插入一条包含时间字段的数据时,报错如下:
‘Conversion failed when converting date and/or time from character string.DB-Lib error message 241,

处理过程:
1、直接在数据库里执行insert语句

INSERT INTO [dbo].[ClustedResult]([outputScript],[classId],[startTime],[endTime]) VALUES(0x76A914E67550CD61C6D89DF67F4D5F8E0B4AD30013C65888AC,'493886f0-7387-11e7-ab02-047d7ba2a507','2017-07-28 19:24:14.431000','2017-07-28 19:24:14.431000')

发现也报错,显示字符串与日期转换失败。

2、查看表中各字段的数据类型
结果:[startTime],[endTime]两个字段的数据类型是datetime

网上查找sqlserver 2008表示时间的数据类型有6种。
time、date、smalldatetime、datetime、datetime2、datetimeoffset;

datetime
日期和时间部分,可以表示的日期范围从公元1753年1月1日00:00:00.000 到9999年12月31日23:59:59.997 ,精确到3.33毫秒,它需要8个字节的存储空间。DateTime字段类型对应的时间格式是 yyyy-MM-dd HH:mm:ss.fff ,3个f,精确到1毫秒(ms),示例 2014-12-03 17:06:15.433

smalldatetime
从1900年1月1日到2079年6月6日的日期和时间数据精确到分钟。29.998秒或更低的 smalldatetime值向下舍入为最接近的分钟,29.999秒或更高的smalldatetime值向上舍入为最接近的分钟。需要4字节的存储空间。

date
SQL Server 2008新引进的数据类型。它表示一个日子,不包含时间部分,可以表示的日期范围从公元元年1月1日到9999年12月31日。只需要3个字节的存储空间。

DateTime2
DateTime2字段类型对应的时间格式是 yyyy-MM-dd HH:mm:ss.fffffff ,7个f,精确到0.1微秒(μs),示例 2014-12-03 17:23:19.2880929 。

在读取该数据时不管你的字段是datetime或smalldatetime读出来的格式都一样(如:1900-01-01)。datetime不会显示出他的毫秒,但是在进行时间比较时他要毫秒就会出现,从而让两个时间段不能相等。

如果是SQL Server 2005,那么请你使用smalldatetime吧,数据能节约一半,虽然查询的时候看起来没什么改变;
如果你是SQL Server 2008,那么请你使用date吧,虽然3个字节跟4个字节没有多大的差距,但是从设计上和逻辑清晰度上都有很大的提升。

如果用SQL的日期函数进行赋值,DateTime字段类型要用 GETDATE() ,DateTime2字段类型要用 SYSDATETIME() 。

有非常详细的参考:
http://www.youkuaiyun.com/article/1970-01-01/282777
http://blog.youkuaiyun.com/justdb/article/details/7575021

3、进行了一系列知识恶补后,查看python下时间类型的特点

begin = datetime.datetime.now()
print type(begin)
print str(begin)

#运行结果:
<type 'datetime.datetime'>
2017-07-28 19:24:14.431000

4、找到问题原因,是由于python 和sqlserver的时间类型format不一样导致的。提供两种解决方案:

  • 方案一:将python的datetime格式统一为数据库格式。
    timeStamp = str(datetime.datetime.now())[0:-3]

  • 方案二:修改数据库数据类型为范围更大的datetime2

### 3.1 确保输入字符串格式与目标格式匹配 在将 `nvarchar` 转换为 `datetime` 时,输入字符串的格式必须与 SQL Server 的预期格式兼容。例如,如果日期字符串为 `'20250714004732860'`,该格式为 `YYYYMMDDHHmmssnnn`,SQL Server 通常可以自动识别并转换为 `datetime` 类型: ```sql SELECT CONVERT(datetime, '20250714004732860') AS ConvertedDate; ``` 如果输入格式不标准,如包含非法分隔符或顺序错误,会导致转换失败。此时应使用 `CONVERT` 函数并指定格式代码,例如 `112` 表示 `YYYYMMDD` 格式: ```sql SELECT CONVERT(datetime, LEFT('20250714004732860', 8), 112) AS ConvertedDate; ``` 此方法可确保 SQL Server 按预期格式解析日期字符串,避免格式不匹配导致的错误[^1]。 ### 3.2 使用 `TRY_CONVERT` 或 `TRY_CAST` 避免转换失败 当输入字符串可能包含非法日期格式时,可使用 `TRY_CONVERT` 或 `TRY_CAST` 函数。这些函数在转换失败时返回 `NULL` 而非抛出错误,适用于数据清洗或批量处理场景: ```sql SELECT TRY_CONVERT(datetime, '20250714004732860') AS SafeConvertedDate; ``` 如果字符串 `'20250714004732860'` 中存在非法字符或格式错误,该函数将返回 `NULL`,而不是中断执行。此方法适用于处理不确定格式的输入数据,避免因个别记录格式错误导致整个查询失败[^2]。 ### 3.3 使用 `ISDATE` 函数验证字符串是否为有效日期 在执行转换前,可以使用 `ISDATE` 函数验证字符串是否为合法日期格式: ```sql SELECT * FROM your_table WHERE ISDATE(your_column) = 1; ``` 此查询仅选择可转换为 `datetime` 的记录,确保后续操作不会因非法格式而失败。需要注意的是,`ISDATE` 在某些版本的 SQL Server 中可能对某些格式识别不准确,建议结合 `TRY_CONVERT` 使用以提高可靠性[^3]。 ### 3.4 显式截取并构造标准日期格式 当输入字符串包含额外信息(如时间部分),可先使用字符串函数截取并构造标准日期格式: ```sql SELECT CONVERT(datetime, LEFT('20250714004732860', 8), 112) AS ConvertedDate; ``` 此方法适用于字符串中仅前几位为日期部分的情况,确保 SQL Server 按照标准格式解析。例如,`LEFT('20250714004732860', 8)` 提取 `'20250714'`,然后使用 `112` 格式代码转换为 `2025-07-14`。 ### 3.5 使用动态 SQL 构造带格式的日期查询 在构建动态 SQL 查询时,应确保日期字符串格式与 SQL Server 兼容,避免因格式错误导致执行失败: ```sql DECLARE @dateFrom datetime = '2025-01-01'; DECLARE @dateTo datetime = GETDATE(); DECLARE @sql nvarchar(1000); SET @sql = 'SELECT * FROM your_table WHERE date_column BETWEEN ''' + CONVERT(nvarchar(20), @dateFrom, 120) + ''' AND ''' + CONVERT(nvarchar(20), @dateTo, 120) + ''''; EXEC sp_executesql @sql; ``` 此方法确保日期字符串在拼接时使用标准格式(如 `YYYY-MM-DD HH:MI:SS`),避免因格式不一致导致转换失败[^1]。 ---
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值