当使用pyodbc访问大于511的字符字段时,为什么count()返回0?

时间:2017-02-21 14:04:22

标签: python postgresql sqlite pyodbc

我试图计算数据库字符字段(PostgreSQL,pyodbc,Python 3.4.4,Windows 7)中子字符串的出现次数。但是当字符字段大于511时,count()总是返回零。只有在使用返回的字符串“执行某些操作”之后(例如,在索引0处访问字符串或使用print()查看字符串),count()才会返回预期值。长度为511或更短的字符串没有问题。

此外,(512或更大)字符串的大小似乎也有变化,请参阅下面的示例。

使用pyodbc时,PostgreSQL,SQLite和Oracle似乎会出现此问题。我无法使用psycopg2重现它。

那么,它是pyodbc中的一个错误吗?或者它是某种优化和count()确实有问题吗? (其他函数似乎没问题,例如len()。)

以下Python脚本将使用PostgreSQL,SQLite-ODBC或Oracle重现此问题。 它将创建两个表,插入文本并尝试在返回的数据上使用函数count()。

import pyodbc
import sys

#conn   = pyodbc.connect('driver={SQLite3 ODBC Driver}; server=localhost; database=D:\\test.db;')
#conn   = pyodbc.connect('DSN=test-oracle;uid=xx;pwd=xx')
conn   = pyodbc.connect('DSN=test-postgresql;uid=xx;pwd=xx')
cursor = conn.cursor()
with conn.cursor() as cursor:

    cursor.execute("create table testtable511 (txt char(511) default ' ' primary key not NULL);")
    cursor.execute("insert into testtable511 (txt) values ('"+511*"t"+"');")
    cursor.execute("create table testtable512 (txt char(512) default ' ' primary key not NULL);")
    cursor.execute("insert into testtable512 (txt) values ('"+512*"t"+"');")

    cursor.execute('select * from testtable511')
    data511  = cursor.fetchone()
    print('511')
    print(80*'#')
    # count is 511, size is 560
    print('counting t before "accessing" string of testtable511:     ', data511[0].count('t'))
    print('size of string before "accessing" string of testtable511: ', sys.getsizeof( data511[0] ))
    data511[0][0]
    # count is 511, size is 560
    print('counting t after "accessing" string of testtable511:      ',  data511[0].count('t'))
    print('size of string after "accessing" string of testtable511:  ',  sys.getsizeof( data511[0] ))
    print(80*'#')

    print()

    cursor.execute('select * from testtable512')
    data512 = cursor.fetchone()
    print('512')
    print(80*'#')
    # count is 0, size is 1106
    print('counting t before "accessing" string of testtable512:     ', data512[0].count('t'))
    print('size of string before "accessing" string of testtable512: ', sys.getsizeof( data512[0] ))
    data512[0][0]
    # count is 512, size is 593
    print('counting t after "accessing" string of testtable512:      ', data512[0].count('t'))
    print('size of string after "accessing" string of testtable512:  ', sys.getsizeof( data512[0] ))
    print(80*'#')

    cursor.execute("drop table testtable511;")
    cursor.execute("drop table testtable512;")

conn.close()

更新:问题在于pyodbc 3.0.10。版本4.0.11修复了该问题。

1 个答案:

答案 0 :(得分:2)

问题在pyodbc 4.0.11中得到修复。

所以这似乎是早期pyodbc版本的错误(我使用的是3.0.10)。