Python / pyodb c не получает raiserror или throw от SQL Server try / catch блок? - PullRequest
0 голосов
/ 04 февраля 2020

Я ожидаю, что python / pyodb c обработает рейзеррор или бросок из блока t sql (SQL Server). Вместо этого он, похоже, возвращает список нулевой длины без информации о столбце. Это проблема с драйверами или мне чего-то не хватает? MRE ниже ...

import pyodbc
import pandas.io.sql as pd
from pandas import DataFrame
from tabulate import tabulate
import sys 
import os

server   = "XXX.XXX.XXX.XXX"
database = "XXXXXXXXXXXX"
username = "XXXXXXXXXXXX"
password = "XXXXXXXXXXXX"

try:
    cnxn = pyodbc.connect('DRIVER={ODBC Driver 17 for SQL Server};MARS_Connection=Yes;SERVER='+server+';DATABASE='+database+';UID='+username+';PWD='+password)
    # autocommit defaults to false on pyodbc but we add it here for absence of doubt.
    cnxn.autocommit = False
    cursor = cnxn.cursor()

    #query_str = open(sys.argv[1],"r").read()
    #query_str = "set nocount on; create table #test (col1 int, col2 varchar(10)); insert into #test (col1, col2) values (999, 'hello'); select * from #test"
    query_str = """ 
    set nocount on;
    begin try
        --create table #test (col1 int, col2 varchar(10));
        --insert into #test (col1, col2) values (999, 'hello');
        --select * from #test;
        select 1/ 0 ;
    end try
    begin catch
        raiserror('Hello from the db', 16, 1);
        --throw;
    end catch
    """

    #print (query_str)

    try:
        retval = cursor.execute(query_str)
        if cursor.description is not None:
            columns = [column[0] for column in cursor.description]
            rt = retval.fetchall()
            detupled_rt = map(list, rt) 
            df = pd.DataFrame(detupled_rt)
            table = df.values.tolist()
            print(tabulate(table, columns, tablefmt="github"))
        else:
            print("Completed with no result set")

    except pyodbc.ProgrammingError as pex:
        print("Programming error")
        raise pex 

except pyodbc.Error as ex: 
    #sqlstate = ex.args[1]
    print ("Program error")
    raise ex

finally:
    cnxn.commit()
    cursor.close()
    cnxn.close()

Это работает так, как я ожидаю, если уберу блоки try / catch из запроса sql, например ...

query_str = """ 
    set nocount on;
    select 1/ 0 ;
"""

Ожидается вывод ...

Program error
Traceback (most recent call last):
  File "t_try.py", line 56, in <module>
    raise ex
  File "t_try.py", line 38, in <module>
    retval = cursor.execute(query_str)
pyodbc.DataError: ('22012', '[22012] [Microsoft][ODBC Driver 17 for SQL Server][SQL Server]Divide by zero error encountered. (8134) (SQLExecDirectW)')
...