我正在try 执行一个存储过程,并使用PYTHON的SQLALCHEMY模块访问它的输出.

我找到了this post个,但不能让它运行得没有错误.

SQL Stored Procedure

USE [TestDatabase]
GO

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[testPython]
    @numOne int,
    @numTwo int,
    @numSum int OUTPUT

AS
BEGIN
    LINENO 0
    SET NOCOUNT ON;

    SET @numSum = @numOne + @numTwo
END
GO

Python个个

import sqlalchemy as db
engine = db.create_engine(f"mssql+pyodbc://{username}:{password}@{dnsname}/{dbname}?driver={driver}")

with engine.connect() as conn:
    outParam = db.sql.outparam("ret_%d" % 0, type_=int)
    result = conn.execute('testPython ?, ?, ? OUTPUT', [1, 2, outParam])
    print(result)

The error it returned

TypeError:‘BindParameter’类型的对象没有len()

上述异常是以下异常的直接原因:

SystemError:<类‘pyodbc.Error’>返回了设置了错误的结果

Edit:多亏了mkleehammer's github,我成功地让它与pyodbc一起工作.如果有人知道,我仍然想知道如何使用SqlalChemy来做到这一点.

pyodbc code

def testsp():
    query = """
    DECLARE @out int;
    EXEC [dbo].[testPython] @numOne = ?, @numTwo = ?, @numSum = @out OUTPUT;
    SELECT @out AS the_output;
    """
    params = (1,2,)

    connection = pyodbc.connect(f'DRIVER={DRIVER_SQL};SERVER={DNSNAME_SQL};DATABASE={DBNAME_SQL};UID={USERNAME_SQL};PWD={PASSWORD_SQL}',auto_commit=True)
    cursor = connection.cursor()
    cursor.execute(query, params)
    rows = cursor.fetchall()
    while rows:
        print(rows)
        if cursor.nextset():
            rows = cursor.fetchall()
        else:
            rows = None
    cursor.close()
    connection.close()

如果存储过程包含INSERT语句,则Edit2:Gord的解决方案不起作用.它返回求和的值,但不执行INSERT语句.我try 将INSERT作为普通命令和字符串中的INSERT,然后使用EXEC(@Query).我还确保授予用户对NumbersTable的SELECT和INSERT权限.

我还try 了上面的pyodbc代码,但没有执行INSERT命令,但返回了正确的总和.

SOLUTION:我发现有this post个人表示需要将自动提交设置为True.这既适用于pyodbc代码,也适用于sqlalChemy代码.

SQL

USE [TestDatabase]
GO

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[testPython]
    @numOne int,
    @numTwo int,
    @numSum int OUTPUT

AS
BEGIN
    LINENO 0

    SET NOCOUNT ON;

    -- DECLARE @query varchar(max)
    -- SET @query = 'INSERT INTO NumbersTable(num1, num2, numSum)
    --              VALUES(' + numOne + ', ' + numTwo ', ' + numSum')'
    -- print(@query)
    -- EXEC(@query)

    SET @numSum = @numOne + @numTwo

    INSERT INTO NumbersTable(num1, num2, numSum)
    VALUES(@numOne, @numTwo, @numSum)

    
END
GO

Python个个

import sqlalchemy as db

engine = db.create_engine(f"mssql+pyodbc://{username}:{password}@{dnsname}/{dbname}?driver={driver}&autocommit=true")

query = """
DECLARE @out int;
EXEC [dbo].[testPython] @numOne = :p1, @numTwo = :p2, @numSum = @out OUTPUT;
SELECT @out AS the_output;
"""
params = dict(p1=1,p2=2)

with engine.connect() as conn:
    result = conn.execute(db.text(query), params).scalar()
    print(result)

这将返回3,但该行不会插入到NumbersTable中.

Executing Stored Procedure in SQL as same user

EXECUTE AS login = 'UserTest'

DECLARE @out int
EXEC [dbo].[testPython] @numOne = 0, @numTwo = 0, @numSum = @out OUTPUT
SELECT @out as the_output

这将输出总和并将该行插入到NumbersTable中.

推荐答案

只需使用与您的Plain-pyodbc解决方案相同的anonymous code block稍作修改的版本:

import sqlalchemy as db

engine = db.create_engine("mssql+pyodbc://scott:tiger^5HHH@mssql_199")

query = """\
SET NOCOUNT ON;
DECLARE @out int;
EXEC [dbo].[testPython] @numOne = :p1, @numTwo = :p2, @numSum = @out OUTPUT;
SELECT @out AS the_output;
"""
params = dict(p1=1, p2=2)

with engine.begin() as conn:
    result = conn.execute(db.text(query), params).scalar()
    print(result)  # 3

Python相关问答推荐

运行回文查找器代码时发生错误:[类型错误:builtin_index_or_system对象不可订阅]

韦尔福德方差与Numpy方差不同

Matlab中是否有Python的f-字符串等效物

Python中的嵌套Ruby哈希

Julia CSV for Python中的等效性Pandas index_col参数

如何使用Python以编程方式判断和检索Angular网站的动态内容?

如何使Matplotlib标题以图形为中心,而图例框则以图形为中心

python中的解释会在后台调用函数吗?

Python列表不会在条件while循环中正确随机化'

什么是合并两个embrame的最佳方法,其中一个有日期范围,另一个有日期没有任何共享列?

Polars将相同的自定义函数应用于组中的多个列,

freq = inject在pandas中做了什么?''它与freq = D有什么不同?''

为用户输入的整数查找根/幂整数对的Python练习

提取数组每行的非零元素

read_csv分隔符正在创建无关的空列

Pythonquests.get(Url)返回Colab中的空内容

随机森林n_估计器的计算

为什么我的scipy.optimize.minimize(method=";newton-cg";)函数停留在局部最大值上?

无法在盐流道中获得柱子

如何将列表从a迭代到z-以抓取数据并将其转换为DataFrame?