【问题标题】:Read stored procedure select results into pandas dataframe将存储过程选择结果读入熊​​猫数据框
【发布时间】:2014-11-25 18:47:50
【问题描述】:

给定:

CREATE PROCEDURE my_procedure
    @Param INT
AS
    SELECT Col1, Col2
    FROM Table
    WHERE Col2 = @Param

我希望能够将其用作:

import pandas as pd
import pyodbc

query = 'EXEC my_procedure @Param = {0}'.format(my_param)
conn = pyodbc.connect(my_connection_string)

df = pd.read_sql(query, conn)

但这会引发错误:

ValueError: Reading a table with read_sql is not supported for a DBAPI2 connection. Use an SQLAlchemy engine or specify an sql query

SQLAlchemy 也不起作用:

import sqlalchemy
engine = sqlalchemy.create_engine(my_connection_string)
df = pd.read_sql(query, engine)

投掷:

ValueError: Could not init table 'my_procedure'

其实我可以直接使用pyodbc执行语句:

cursor = conn.cursor()
cursor.execute(query)
results = cursor.fetchall()
df = pd.DataFrame.from_records(results)

有没有办法将这些过程结果直接发送到 DataFrame?

【问题讨论】:

  • 你用的是什么版本的熊猫?您可以尝试使用pd.read_sql_query 而不是read_sql 吗? (read_sql 中有一个关于执行存储过程的错误)

标签: sql-server stored-procedures pandas sqlalchemy pyodbc


【解决方案1】:

请改用 read_sql_query()

看起来@joris (+1) 已经在问题正下方的评论中有这个,但我没有看到它,因为它不在答案部分。

使用 SQLA 引擎——除了 SQLAlchemy,Pandas 只支持 SQLite。然后使用 read_sql_query() 代替 read_sql()。后者尝试自动检测您传递的是表名还是完整的查询,但使用“EXEC”关键字似乎效果不佳。使用 read_sql_query() 会跳过自动检测并允许您明确指出您正在使用查询(还有一个 read_sql_table())。

import pandas as pd
import sqlalchemy

query = 'EXEC my_procedure @Param = {0}'.format(my_param)
engine = sqlalchemy.create_engine(my_connection_string)
df = pd.read_sql_query(query, engine)

【讨论】:

    【解决方案2】:

    https://code.google.com/p/pyodbc/wiki/StoredProcedures

    我不是 python 专家,但 SQL Server 有时会返回语句执行的计数。例如,一次更新会告诉您更新了多少行。

    只需使用 'SET NO COUNT;'在您的批处理调用的前面。这将删除插入、更新和删除的计数。

    确保您使用的是正确的本机客户端模块。

    看看这个堆栈溢出示例。

    它有一个即席 SQL 和调用存储过程的例子。

    Calling a stored procedure python

    祝你好运

    【讨论】:

    • SET NOCOUNT ON 不幸的是在这种情况下没有帮助。
    • 在我的存储过程开始时添加 SET NOCOUNT ON 有效。谢谢。另外,我尝试在查询的开头添加“SET NOCOUNT ON;”,效果也很好。
    【解决方案3】:

    添加SET NOCOUNT ON 感谢@CRAFTY DBA 后,这对我有用

    sql_query = """SET NOCOUNT ON; EXEC db_name.dbo.StoreProc '{0}';""".format(input)
    
    df = pandas.read_sql_query(sql_query , conn)
    

    【讨论】:

    • 我也必须这样做。为了使我的查询正常工作,我必须在存储过程的变量周围使用单引号创建带有三引号的字符串。看起来像这样"""EXEC sProcedure 'variable1', 'variable2'"""
    【解决方案4】:

    使用 ODBC 语法调用存储过程(使用参数而不是字符串格式)适用于使用 pandas 0.14.1 和 pyodbc 3.0.7 加载数据帧。以下示例使用AdventureWorks2008R2 sample database

    首先确认使用pyodbc调用存储过程的预期结果:

    import pandas as pd
    import pyodbc
    connection = pyodbc.connect(driver='{SQL Server Native Client 11.0}', server='ServerInstance', database='AdventureWorks2008R2', trusted_connection='yes')
    sql = "{call dbo.uspGetEmployeeManagers(?)}"
    params = (3,)
    cursor = connection.cursor()
    rows = cursor.execute(sql, params).fetchall()
    print(rows)
    

    应该返回:

    [(0, 3, 'Roberto', 'Tamburello', '/1/1/', 'Terri', 'Duffy'), (1, 2, 'Terri', 'Duffy',
    '/1/', 'Ken', 'Sánchez')]
    

    现在使用 pandas 将结果加载到数据框中:

    df = pd.read_sql(sql=sql, con=connection, params=params)
    print(df)
    

    应该返回:

       RecursionLevel  BusinessEntityID FirstName    LastName OrganizationNode  \
    0               0                 3   Roberto  Tamburello            /1/1/
    1               1                 2     Terri       Duffy              /1/
    
      ManagerFirstName ManagerLastName
    0            Terri           Duffy
    1              Ken         Sánchez
    

    编辑

    由于您无法更新到 pandas 0.14.1,请使用 pandas.DataFrame.from_records 从 pyodbc 加载结果:

    # get column names from pyodbc results
    columns = [column[0] for column in cursor.description]
    df = pd.DataFrame.from_records(rows, columns=columns)
    

    【讨论】:

    • 这在 pandas 0.14.0 中不起作用。我目前无法升级到 0.14.1 进行测试,但感谢您的提示。
    • @joeb1415 更新了如何在不使用read_sql的情况下填充数据帧
    • 次要,你可能想from_records(rows, columns=columns, coerce_float=True) 这样你就不会得到字符串数字列,oracle/sql 经常出现这种情况
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-06
    • 2017-06-22
    • 1970-01-01
    • 2018-03-20
    • 1970-01-01
    • 2013-11-09
    • 2019-05-07
    相关资源
    最近更新 更多