【问题标题】:How to embed a function within a function in SQLAlchemy UPDATE call如何在 SQLAlchemy UPDATE 调用中的函数中嵌入函数
【发布时间】:2020-07-24 08:44:15
【问题描述】:

在 SQLAlchemy Core 中工作,我正在尝试创建一个 UPDATE 语句,该语句使用同一表中其他列中的值的 MD5 哈希填充列。我事先不知道列名是什么,但我想将每列中的值附加在一起,然后从中创建哈希值。这是我试图生成的 SQL 的 SET 子句的感觉...

SET master_key = MD5(CONCAT(last_name, first_name))

此更新语句可能包含数百万行,因此我希望在数据库中完成工作,而不是将数据集导入 Python,应用新值,然后将其写回数据库。

这是我的 Python 代码...

    stmt = self.tbl.update().where(self.tbl.c.master_key==None).\
        values({'master_key': func.MD5(concat(key_col_names))})
    qry_engine.execute(statement=stmt)

key_col_names 是一个包含列名列表的字符串,以逗号分隔(例如,'last_name, first_name')。

SQLAlchemy 似乎在我有 MD5 函数的地方生成以下内容: MD5('last_name, first_name'),因此,每行的哈希值都是相同的。如何让它实际使用查询中的列名而不是我提供的文字字符串?

我现在正在为 MySQL 编写这篇文章,但如果使用移植到其他数据库的 SQLAlchemy 函数而不是 MySQL 特定的函数来完成它会很棒。

【问题讨论】:

    标签: python sqlalchemy


    【解决方案1】:

    从您的表中查找实际列并将其解压缩为 CONCAT() 的参数:

    key_cols = [self.tbl.c[name.strip()] for name in key_col_names.split(",")]
    stmt = self.tbl.update().where(self.tbl.c.master_key==None).\
            values({'master_key': func.MD5(func.concat(*key_cols))})
    qry_engine.execute(statement=stmt)
    

    如果有问题的列是字符串类型,请在 Python 中使用+ 运算符来生成连接表达式:

    key_cols = [self.tbl.c[name.strip()] for name in key_col_names.split(",")]
    # This is a bit of a hack and effectively the same as using reduce and operator.add.
    # Another option would be to use a good old for-loop to reduce.
    key_col_cat = sum(key_cols)
    stmt = self.tbl.update().where(self.tbl.c.master_key==None).\
            values({'master_key': func.MD5(key_col_cat)})
    qry_engine.execute(statement=stmt)
    

    【讨论】:

    • 完美!如果你有第二个快速相关的问题。 1) 你知道 self.tbl.primary_key.columns 是否总是以相同的顺序返回它的值吗? (如果不是,我应该对 key_cols 进行排序,以便得到一致的结果)。 2)您的答案的顶级版本是否也适用于非字符串列(例如 bool、int、numeric)?我将自己尝试一下,但最好在此处记录以供将来参考。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-09-04
    • 2021-04-23
    • 2016-12-17
    • 2018-03-13
    • 1970-01-01
    • 1970-01-01
    • 2017-09-11
    相关资源
    最近更新 更多