简体   繁体   English

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

[英]How to execute multiple insert/update queries in one SQL using Python/SQLAlchemy and MSSQL?

I'm new to python and SQLAlchemy, I'm trying to understand how to execute multiple insert/update queries in one SQL using Python/SQLAlchemy: 我是python和SQLAlchemy的新手,我试图了解如何使用Python / SQLAlchemy在一个SQL中执行多个插入/更新查询:

Requirement Execute multiple insert/update in one 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)

Understand that this query looks ugly, but we do have many similar queries. 知道这个查询看起来很丑,但是我们确实有很多类似的查询。 (we're using a legacy database which is around 20 years old) (我们使用的旧数据库大约已有20年的历史了)

Python Code 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()

Please note that 请注意

INSERT INTO TEST_TABLE VALUES ('QZ_TEST', 'not a number')

will trigger an Error if I ran this single query with my SQL client: [S0001][245] Conversion failed when converting the varchar value 'not a number' to data type int. 如果我使用SQL客户端运行此单个查询,将触发错误:[S0001] [245]将varchar值“非数字”转换为数据类型int时转换失败。

I'm expecting an exception captured by Python, however, the Python code runs without any exception. 我期望Python捕获到一个异常,但是Python代码运行时没有任何异常。 There's no exception captured by Python even though I replaced the SQL with : 即使我将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

My Questions 我的问题

  • Am I using the correct method to execute the Query? 我是否使用正确的方法执行查询?
  • If my code was fine, how can I capture the actual SQL exception from Python? 如果我的代码很好,如何从Python捕获实际的SQL异常?

The execute command may be having issues preparing your statement, since it is in fact, multiple statements. 由于实际上是多个语句,因此execute命令在准备语句时可能会遇到问题。 For what you're trying to do, I believe you may want to take a look at executemany : 对于您要尝试执行的操作,我相信您可能需要看一下executemany

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

It takes a different form and binds your INSERT values as tuples within a list. 它采用不同的形式并将INSERT值绑定为列表中的元组。

Good luck! 祝好运!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM