Python MySQLdb 返回日期和小数。

13

我有一个像这样的 MySQL 查询:

SELECT mydate, countryCode, qtySold from sales order mydate, countryCode

这将返回类似以下值的元组:

((datetime.date(2011, 1, 3), 'PR', Decimal('1')), (datetime.date(2011, 1, 31), 'MX', Decimal('1')))

当我尝试使用循环打印它时,它完美地打印出来:

2011-1-3, PR, 1
2011-1-31, MX, 1

但是当我尝试返回这个值时,它会返回为

datetime.date(2011, 1, 3), 'PR', Decimal('1')

有没有办法获取正常的数据,以便我可以将其传递给UI进行处理? 正常数据是指:

[['2011-1-03', 'PR', 1], ...]

当我执行DATE_FORMAT(mydate, '%Y-%m-%d')时,输出结果为[['2011-1-03', 'PR', Decimal('1')],[...]]然后我添加了CONVERT(qtySold, UNSIGNED),输出结果为[['2011-1-03', 'PR', 1L],[...]]现在日期问题已经解决,是否有任何解决qtySold的方法? - arc
5个回答

32

默认的转换器为 MySQLdb.converters.conversions,其中包含类似于以下条目的字典:

{0: <class 'decimal.Decimal'>,
 1: <type 'int'>,
 2: <type 'int'>,
 3: <type 'long'>,
 4: <type 'float'>,
 5: <type 'float'>,
 7: <function mysql_timestamp_converter at 0x89e4454>,
 8: <type 'long'>,
 9: <type 'int'>,
 10: <function Date_or_None at 0x89e43ac>,
 ...
}

您可以更改转换器并将其传递给connect方法,如下所示:

conv=converters.conversions.copy()
conv[246]=float    # convert decimals to floats
conv[10]=str       # convert dates to strings
connection=MySQLdb.connect(
    host=HOST,user=USER,
    passwd=PASS,db=DB,
    conv=conv
    )

通过检查交互式Python会话中的MySQLdb.converters.conversions并根据默认值做出合理猜测,找到了键10246

连接建立后还可以更改转换器:

connection.converter=conv

顺便问一下,你是如何通过 SQL 查询解决这个问题的?请将其添加为答案。


1
+1,这就解释了为什么我在下游遇到了Decimal实例的问题 :) 我相信你知道,但如果其他人遇到这个问题,常量定义本身可以在FIELD_TYPE中找到,使用from MySQLdb.constants import FIELD_TYPE(常量表示MySQL列类型 - FIELD_TYPE.DECIMAL = 0FIELD_TYPE.TIMESTAMP = 7等)。 - RocketDonkey
2
而且正如我刚刚发现的一样,你可能想使用FIELD_TYPE.NEWDECIMAL(246)而不是FIELD_TYPE.DECIMAL(0)。 - albrnick
如果您正在使用pymysql,那么这段代码适用于您:conv = pymysql.converters.conversions.copy() - jmcgrath207
有没有办法调整转换器以防止Unicode字符串?我被分配了一个任务,将一个工具从一个系统迁移到另一个系统,但似乎一些背景配置不一致。特别是,我得到了很多列标识符作为u'column_name',这破坏了我的JavaScript。是否有一个一站式的编码来进行转换? - Eddie Rowe

6
如果你需要在日期上使用str类型,而在数字上使用int类型,可以参考datetime.date.strftime()int()函数:
>>> datetime.date(2011, 1, 3).strftime("%Y-%m-%d")
'2011-01-03'

>>> int(Decimal(2))
2

如果你想有系统地改变MySQLdb返回不同列类型的值,可以查看MySQLdb.connect()中的conv关键字参数。详见:http://mysql-python.sourceforge.net/MySQLdb.html#mysqldb

1
有什么我可以在查询层面上做的吗?那会非常有帮助。 - arc
你可以通过.connect()conv参数向类型转换表中添加项目:http://mysql-python.sourceforge.net/MySQLdb.html#mysqldb - Amber
请参阅http://mysql-python.sourceforge.net/MySQLdb-1.2.2/public/MySQLdb.converters-module.html#conversions。 - Amber
我第一次做这个。你能否帮我使用conv转换我的查询? - arc
2
如果这是你第一次尝试,何不阅读文档并学习如何自己完成呢?你似乎并没有卡住——我已经很明确地指出了你需要做的事情,并提供了相应的页面来解释如何实现。如果你有具体问题,请提出来,但请不要仅仅向 StackOverflow 用户请求编写代码。 - Amber
这不是我第一次了。我只是想在conv上寻求一些帮助,因为我没有找到太多关于它的实现方面的信息。顺便提一下,我已经通过使用MySQL查询解决了这个问题。 - arc

4
您可以在查询字符串中强制将特定列转换为CHAR,以避免进行转换。
import MySQLdb
import datetime 
conn = MySQLdb.connect(host= "mysql-server",user="weblogadmin", passwd="admin123",db="weblog_db") 
sqlcursor = conn.cursor() 
sqlcursor.execute("SELECT logrole,logserver,logtype,loglevel,CAST(logdatetime AS CHAR),logdetail,logaction,logread FROM logapp_logtable") 
row = sqlcursor.fetchall() 
for data in row:    
    print(str(data)) 
conn.close()

3

MySQLdb试图提供有用的帮助,为您提供SQL数据类型的Python版本。

然而,如果由于某些原因需要字符串,您可以将返回的所有内容转换为字符串。因此,类似于[[str(val) for val in row] for row in results]的语句就可以实现这个目的。


在这里,最底下的那个零票答案是对我有用的。其他答案在语法上是不正确的。这个答案是有效的,特别是使用这个语法:retVal["rows"] = [[str(val) for val in row] for row in dbCursor.fetchall()] - philo vivero
当你需要像int和float等正确的类型时,这并不有用。 - cerd

1

如果你使用pymysql而不是MySQLdb,答案是类似的。首先导入转换器和常量类型。复制使用的通用转换器,并将小数点更改为转换为浮点数。

import pymysql
from pymysql.constants import FIELD_TYPE
from pymysql.converters import conversions

conv = conversions.copy()
conv[FIELD_TYPE.DECIMAL] = float
conv[FIELD_TYPE.NEWDECIMAL] = float

之后,在连接中使用conv字典。
connection = pymysql.connect(host = db_host,     
                                 user = db_user,    
                                 passwd = db_pass,
                                 db = db_db,
                                 charset='utf8mb4',
                                 conv = conv,
                               max_allowed_packet = 33554432,
                                    cursorclass=pymysql.cursors.DictCursor)

现在正在将十进制转换为浮点数。

谢谢,这对我很有帮助。 另外,对于寻找FIELD_TYPE列表的人,请访问以下链接:https://github.com/PyMySQL/PyMySQL/blob/main/pymysql/constants/FIELD_TYPE.py - Vishnu Kumar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接