类型错误:转换为Unicode时需要字符串或缓冲区,发现NoneType

1 投票
1 回答
3725 浏览
提问于 2025-04-18 11:42

我正在尝试从一个Python脚本创建一个SQL字符串。

这是我的代码:

sql_query = ('insert into ithelpdesk ' 
        '(id,display_id,subject,description,priority,status,requester_name,source,responder_id,due_by,updated_at,frDueBy,ticket_type,created_at)'
        ' values ('
        '"' + str(data['id']) + '",'
        '"' + str(data['display_id']) + '",'
        '"' + data['subject'] + '",'
        '"' + data['description'] + '",'
        '"' + str(data['priority']) + '",'
        '"' + str(data['status']) + '",'
        '"' + data['requester_name'] + '",'
        '"' + str(data['source']) + '",'
        '"' + str(data['responder_id']) + '",'
        '"' + str(data['due_by']) + '",'
        '"' + str(data['updated_at']) + '",'
        '"' + str(data['frDueBy']) + '",'
        '"' + data['ticket_type'] + '",'
        '"' + str(data['created_at']) + '"'
        ')')

当我运行时,出现了这个错误信息:

Traceback (most recent call last):
 File "c:\users\swatson\dropbox\source files\winpython\dash\newTickets.py", line 198, in <module>
main()
 File "c:\users\swatson\dropbox\source files\winpython\dash\newTickets.py", line 159, in main
addNew(n)
File "c:\users\swatson\dropbox\source files\winpython\dash\newTickets.py", line 65, in addNew
'"' + str(data['created_at']) + '"'
TypeError: coercing to Unicode: need string or buffer, NoneType found

现在我确定(通过打印data['created_at']的值)data['created_at']里有一个值,而且这个值和data['updated_at']是一样的,所以我不知道该怎么解决这个问题?

1 个回答

2

你在这里的根本错误是试图把查询语句写成一整串字符串。不要这样做。这样会导致SQL注入漏洞。

应该使用SQL参数来代替:

sql_query = ('insert into ithelpdesk ' 
        '(id,display_id,subject,description,priority,status,requester_name,source,responder_id,due_by,updated_at,frDueBy,ticket_type,created_at)'
        ' values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)',
    (data['id'], data['display_id'], data['subject'], data['description'],
     data['priority'], data['status'], data['requester_name'], data['source'], 
     data['responder_id'], data['due_by'], data['updated_at'], data['frDueBy'],
     data['ticket_type'], data['created_at']))

具体的语法取决于你使用的数据库适配器;有可能你需要用到%s。很多数据库适配器还支持命名参数,这样你就不需要传入15个不同的值了。你只需在查询中指定要从字典中提取的键:

sql_query = ('insert into ithelpdesk ' 
        '(id,display_id,subject,description,priority,status,requester_name,source,responder_id,due_by,updated_at,frDueBy,ticket_type,created_at)'
        ' values (:id, :display_id, :subject, :description, '
        '         :priority, :status, :requester_name, :source '
        '         :responder_id, :due_by, :updated_at, :frDueBy, '
        '         :ticket_type, :created_at)',
    data)

Python的DB API标准支持几种不同的参数样式。对于位置参数,可以使用?%s,而对于命名参数,可以使用:name%(name)ssqlite3使用前者,而MySQLDB使用后者

当你把Unicode数据和字符串数据拼接在一起,并且其中有一个None时,就会抛出异常。比如说,data['ticket_type']可能是None

撰写回答