从MS SQL Server数据库创建DataFrame时出现Pandas错误:' ODBC SQL类型-151尚不支持

时间:2017-08-18 05:47:02

标签: python sql-server pandas

我尝试从MS SQL Server 2016中的表创建DataFrame,我使用了示例数据库AdventureWorks2012,这里是代码:

import pyodbc 
cnxn = pyodbc.connect("Driver={ODBC Driver 13 for SQL Server};"
                      "Server=localhost;"
                      "Database=AdventureWorks2012;"
                      "Trusted_Connection=yes;")


cursor = cnxn.cursor()
cursor.execute('SELECT * FROM HumanResources.Employee')

df = pandas.read_sql(sql, cnxn)
cursor.close()
cnxn.close()

但是我收到了错误:

----> 1 df = pandas.read_sql(sql,cnxn)

ProgrammingError :(' ODBC SQL类型-151尚不支持.column-index = 3 type = -151',' HY106')

3 个答案:

答案 0 :(得分:1)

所以我只是创建我的答案,因为我现在知道你的问题的完整背景。此问题与新的MS SQL Server 2016的ODBC驱动程序兼容性问题有关。您提到您可以将字段缩小为数据类型为 hierarchyid 的字段。根据提供的文档here,您可以将其转换为nvarchar(4000)字符串表示形式。因此,您的解决方案将是您编写查询的方式。

您的代码目前为:

cursor.execute('SELECT * FROM HumanResources.Employee')

我会将其修改为:

cursor.execute("""
SELECT CAST(theHierarchyIdField AS NVARCHAR(4000)) AS myConvertedField
    ,additionalField
    ,...
FROM HumanResources.Employee
""")

我可以理解,显式编写查询中要提取的所有字段会很烦人,但它是在SQL端进行转换的唯一方法,然后将其作为可识别的数据类型。

另一个解决方案是重新设计您的表架构并将hierarchyid类型更改为nvarchar(4000),但我不知道您是否有权更改表格,因此我可以我只是提出上述解决方案。

此外,如果您计划使用pandas来提取数据,那么只需将sql变量设置为查询字符串read_sql

sql = """
SELECT CAST(theHierarchyIdField AS NVARCHAR(4000)) AS myConvertedField
    ,additionalField
    ,...
FROM HumanResources.Employee
"""

df = pandas.read_sql(sql, cnxn)

答案 1 :(得分:1)

如果您不使用ODBC类型为-151(TSQL hierarchid)的列,则只需在连接上添加一个数据类型处理程序即可将其转换为字符串:

    def HandleHierarchyId(v):
      return str(v)

    conn = pyodbc.connect(connection_string)
    conn.add_output_converter(-151, HandleHierarchyId)

您还可以使用here中列出的任何其他方法来转换此类型。

答案 2 :(得分:0)

来自documentation ... for

pandas.read_sql(sql, con, 
                index_col=None, coerce_float=True, params=None,
                parse_dates=None, columns=None, chunksize=None)

sql : string SQL query or SQLAlchemy Selectable (select or text object)
to be executed, or database table name.

换句话说,参数应该是SQL查询或其他一些机制来选择你想要的行和列。

在您的代码中,您没有将变量sql定义为查询,但您在此行中使用它:

df = pandas.read_sql(sql, cnxn)

我的建议是pandas混淆并提供您描述的错误。

试试这个,看看你是否更接近目标:

sql = cursor.execute('SELECT * FROM HumanResources.Employee')
df = pandas.read_sql(sql, cnxn)