如何使用Python / SQLAlchemy和MSSQL在一个SQL中执行多个插入/更新查询?

时间:2016-01-19 03:52:35

标签: python sql-server exception sqlalchemy pyodbc

我是python和SQLAlchemy的新手,我试图了解如何使用Python / SQLAlchemy在一个SQL中执行多个插入/更新查询:

要求 在一个SQL中执行多个插入/更新:

DECLARE @age INT = 160
INSERT INTO TEST_TABLE VALUES ('QZ_TEST', @age + 1)
INSERT INTO TEST_TABLE VALUES ('QZ_TEST', 'not a number')
INSERT INTO ANOTHER_TABLE VALUES ('QZ_TEST', @age + 2)

了解此查询看起来很丑,但我们确实有很多类似的查询。 (我们使用的是大约20年的遗留数据库)

Python代码

def OdbcEngineSA(driver, conn_str):
    def connect():
        return pyodbc.connect(conn_str, autocommit=True, timeout=120)
    return sqlalchemy.create_engine(driver + '://', creator=connect)

def get_db_connection():
    return OdbcEngineSA('mssql', 'DSN=mssql;Server=server,15001;database=DEV;UID=user_abc;PWD=pw_')

def main():
    db_connection = get_db_connection()
    sql = """
    DECLARE @age INT = 160
    INSERT INTO TEST_TABLE VALUES ('QZ_TEST', @age + 1)
    INSERT INTO TEST_TABLE VALUES ('QZ_TEST', 'not a number')
    INSERT INTO ANOTHER_TABLE VALUES ('QZ_TEST', @age + 2)
    """
    try:
        db_connection.execute(sql)
        db_connection.commit()
        logger.info('db updated')   
    except Exception as e:
        logger.error('Exception captured as expected: %s', e)
        db_connection.rollback()

请注意

INSERT INTO TEST_TABLE VALUES ('QZ_TEST', 'not a number')
如果我使用SQL客户端运行此单个查询,

将触发错误: [S0001] [245]转换varchar值时转换失败,而不是数字'数据类型int。

我期待Python捕获的异常,然而, Python代码运行时没有任何异常。即使我用

替换了SQL,Python也没有捕获任何异常
BEGIN TRY
        DECLARE @age INT = 160
        INSERT INTO TEST_TABLE VALUES ('QZ_TEST', @age + 1)
        INSERT INTO TEST_TABLE VALUES ('QZ_TEST', 'not a number')
        INSERT INTO ANOTHER_TABLE VALUES ('QZ_TEST', @age + 2)
END TRY
    BEGIN CATCH
        DECLARE @ErrorMessage NVARCHAR(4000)
        DECLARE @ErrorSeverity INT
        DECLARE @ErrorState INT

        SELECT 
            @ErrorMessage = ERROR_MESSAGE(),
            @ErrorSeverity = ERROR_SEVERITY(),
            @ErrorState = ERROR_STATE()

        RAISERROR (@ErrorMessage,
                   @ErrorSeverity, -- Level 16
                   @ErrorState
                   )
    END CATCH

我的问题

  • 我使用正确的方法执行查询吗?
  • 如果我的代码很好,我怎样才能从中捕获实际的SQL异常 蟒?

1 个答案:

答案 0 :(得分:0)

execute命令可能在准备语句时遇到问题,因为它实际上是多个语句。对于您要做的事情,我相信您可能需要查看executemany

https://github.com/mkleehammer/pyodbc/wiki/Cursor#executemanysql-paras

它采用不同的形式,并将INSERT值绑定为列表中的元组。

祝你好运!