使用SqlAlChemy执行原始查询(针对SQL-Server数据库和Pymssql)时,传递无法识别的参数并引发SQL错误

我正在尝试使用SqlAlChemy(将Pymssql作为提供程序)在SQL-Server数据库上执行简单的原始SQL查询。

这是我的第一次尝试(使用execute连接方法并以**kwargs方式传递参数):

provider = DataProvider().engine
q = "select url from Crawler.CrawlSource where source=@source"
query = text(q)
result = provider.connect().execute(query, source ='mysource')

我以教程中所示的任何方式传递参数(作为kwargs传递和作为dict传递),但它们都不起作用,并且当调用execute方法时抛出异常,该异常显示'Must declare the scalar variable' @source好像没有参数传递给execute方法,看起来ORM(或者可能是数据提供程序(本例中为pymssql))不识别传递给execute方法的参数,只传递query(

我猜MSSQL-Server提供程序(Pymssql)可能有问题,因为SQL-Server在SqlAlChemy和Python家族中不是一等公民,但没有直接线索导致此问题。

如上所述,我还尝试了其他方法

这是我的第二次尝试(使用execute连接方法并将参数作为dict传递):

provider = DataProvider().engine
q = "select url from Crawler.CrawlSource where source=@source"
query = text(q)
result = provider.connect().execute(query, {source :'mysource'})

我的第三次尝试(使用Engine对象的execute方法,以**kwargs方式传递参数):

provider = DataProvider().engine
q = "select url from Crawler.CrawlSource where source=@source"
query = text(q)
result = provider.execute(query, source ='mysource')

我的第四次尝试(使用Engine对象的execute方法,参数作为dict传递):

provider = DataProvider().engine
q = "select url from Crawler.CrawlSource where source=@source"
query = text(q)
result = provider.execute(query, {source :'mysource'})

我的第五次尝试(创建Session并使用Session的execute方法,将参数作为dict传递):

provider = DataProvider().engine
session = sessionmaker(bind=provider)()
q = "select url from Crawler.CrawlSource where source=@source"
query = text(q)
result = session.execute(query, {source :'mysource'})

我的第六次尝试(创建Session,使用Session的execute方法,以**kwargs方式传递参数):

provider = DataProvider().engine
session = sessionmaker(bind=provider)()
q = "select url from Crawler.CrawlSource where source=@source"
query = text(q)
result = session.execute(query,  source='mysource')

但正如我前面提到的,上述努力都没有奏效,它们都导致了上面提到的相同异常

如有任何帮助,我们将不胜感激


解决方案

mssql+pymssql方言似乎支持";pyformat";paramstyle。这对我有效:

import sqlalchemy as sa

engine = sa.create_engine("mssql+pymssql://@localhost:49242/myDb")

sql = "SELECT word FROM vocabulary WHERE language = %(lang)s"
params = {'lang': 'Greek'}
with engine.begin() as conn:
    result = conn.execute(sql, params).fetchall()
    print(result)
    # [('γιορτή',), ('ηλεκτρονικός υπολογιστής',)]

如果使用SQLAlChemytext对象,还可以使用名为";的参数样式:

sql = sa.sql.text("SELECT word FROM vocabulary WHERE language = :lang")
params = {'lang': 'Greek'}
with engine.begin() as conn:
    result = conn.execute(sql, params).fetchall()
    print(result)
    # [('γιορτή',), ('ηλεκτρονικός υπολογιστής',)]

text对象允许我们一致使用名为";的参数样式,而不考虑DB-API层支持的本机参数样式(例如,%s用于pymssql,?用于pyodbc)。

相关文章