【问题标题】:executemany with pyodbc, stored procedures and SQL Server使用 pyodbc、存储过程和 SQL Server 执行
【发布时间】:2020-07-16 15:57:35
【问题描述】:

我很高兴知道诊断此错误的最简单方法是什么,因为通过 pyodbc 显示正在执行的 SQL 似乎并不容易。

我的存储过程如下所示:

ALTER PROCEDURE [dbo].[s_populate_Test_sp]  
    @TestDateTime DATETIME, 
    @TestInt INT, 
    @TestMoney MONEY, 
    @TestVarChar500 VARCHAR(500), 
    @TestFloat FLOAT
AS
    SET NOCOUNT ON

    INSERT INTO [dbo].[tbl_Test_sp2] (test_datetime, test_int, test_money, test_varchar500, test_float)
    VALUES (@TestDateTime, @TestInt, @TestMoney, @TestVarChar500, @TestFloat)

我可以使用原始文本(下面的注释代码)成功执行此存储过程,但我在执行多方面遇到困难:

import os 
import pyodbc
import datetime
        
def test_sp():
    # Constants
    dir_path = os.path.dirname(os.path.realpath(__file__))
    
    # Connect
    server = 'xxx'
    db2 = 'xxx'
    conn_str = 'DRIVER={SQL Server};SERVER=' + server + \
                           ';DATABASE=' + db2 + ';Trusted_Connection=yes'
    conn=pyodbc.connect(conn_str, autocommit=False)
    cursor = conn.cursor()
    cursor.fast_executemany = True
    
    for row in range(10000):
        # sql = '''EXEC [dbo].[s_populate_Test_sp] @TestDateTime = '2020-01-01 13:00',
        #             @TestInt = 999,
        #             @TestMoney = '£12.34',
        #             @TestVarChar500 = 'Hello My Name is Jon',
        #             @TestFloat = 1.234567
        #             '''
        # cursor.execute(sql)
        

        sql = '''exec s_populate_Test_sp (@TestDateTime = ?, @TestInt = ?, @TestMoney = ?, @TestVarChar500 = ?, @TestFloat = ?)'''
        values = ['2020-01-01 13:00', 999, '£12.34', 'Hello My Name is Jon', 1.234567]
        cursor.executemany(sql, [values])
        
    conn.commit()

if __name__ == '__main__':
    test_sp()

不幸的是,这会产生一个相当神秘的错误消息:

ProgrammingError: ('42000', "[42000] [Microsoft][ODBC SQL Server Driver][SQL Server]'@TestDateTime' 附近的语法不正确。(102) (SQLExecute); [42000] [Microsoft][ODBC SQL Server 驱动程序][SQL Server]无法准备语句。(8180)")

我找不到在 SQL 执行之前显示它的方法,所以目前有点试错。

非常感谢

【问题讨论】:

  • 您注意到有效代码和无效代码之间的区别了吗?我愿意。 @TestDateTime(@TestDateTime.
  • 谢谢。一旦我删除括号。我得到:DataError: ('22018', '[22018] [Microsoft][ODBC SQL Server Driver]Invalid character value for cast specification (0) (SQLExecute)') 我想那可能是英镑符号,所以我删除了它。仍然得到错误。将进一步调查。
  • 建议使用标准且明确的日期时间格式,yyyymmdd hh:mm:ssyyyy-mm-ddThh:mm:ss。还可以检查tbl_Test_sp2 是否有触发器。
  • 解决了谢谢 - 如果我使用 datetime.datetime 对象并删除 £ 符号它工作正常

标签: python sql-server stored-procedures pyodbc


【解决方案1】:

根据 cmets,答案是删除括号、£ 符号并使用 datetime.datetime 对象:

sql = '''exec s_populate_Test_sp @TestDateTime = ?, @TestInt = ?, @TestMoney = ?, @TestVarChar500 = ?, @TestFloat = ?'''
values = [datetime.datetime.now(), 999, 12.34, 'Hello My Name is Jon', 1.234567]

速度如此之慢令人沮丧。在我公司的 VPN 上,它每分钟可以记录 400 条记录,而在靠近服务器的虚拟机上,它每分钟可以记录 9,000 条记录。我怀疑这是 pyodbc 和 SQL Server 的限制之一,对于更大的数据集,我将不得不执行 bcp 或类似的操作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-11-07
    • 2017-01-18
    • 2020-11-12
    • 2016-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多