【问题标题】:How to use Executemany in my situation?如何在我的情况下使用 Executemany?
【发布时间】:2011-08-21 14:28:36
【问题描述】:

如何获得这些 SQL 语句序列?去工作?我以前只处理过单个select 语句,而cursor.execute 工作得很好。我现在不知道在这种情况下该怎么办。我得到的错误是format requires a mapping

args =  {
        "timepattern" : timepattern,
        "datestart_int" : datestart_int,
        "dateend_int" : dateend_int
        }
sql = ( "CREATE TEMPORARY TABLE cohort_users (user_id INTEGER);                                "
            "INSERT INTO cohort_users (user_id)                                                    "
            "SELECT id FROM users WHERE registered_at BETWEEN %(datestart_int)s AND %(dateend_int)s;                        "
            "SELECT 1, FROM_UNIXTIME(%(dateend_int)s, %(timepattern)s)                                                    "
            "UNION ALL                                                                            "
            "SELECT (COUNT(DISTINCT x.user_id)/(SELECT COUNT(1) FROM cohort_users)),             "
            "        FROM_UNIXTIME((%(dateend_int)s + (7 * 24 * 60 * 60)), %(timepattern)s)                                "
            "FROM cohort_users z INNER JOIN actions x ON x.user_id = z.id                        "
            "WHERE x.did_at BETWEEN (%(datestart_int)s + (7 * 24 * 60 * 60)) AND (%(dateend_int)s + (7 * 24 * 60 * 60))        "
            "DROP TABLE cohort_users;                                                            "
            )

cursor.executemany(sql,args)

【问题讨论】:

    标签: python mysql mysql-python executemany


    【解决方案1】:

    假设您的数据库软件支持 %(name)s 形式的参数占位符。

    我们还假设它在一个“操作”中支持多个语句。注意:第三条语句(SELECT ... UNION ALL SELECT ...)末尾缺少分号。

    在这种情况下,您需要做的就是使用 cursor.execute(sql, args) ... executemany() 与一系列 args 一起使用(例如,执行多个 INSERT)。

    为了便于移植和调试,最好一次执行四个语句。

    使用三引号(以及结构化缩进而不是宽缩进)将使您的 SQL 更易于阅读:

    sql = """
    CREATE TEMPORARY TABLE cohort_users (user_id INTEGER);   
    
    INSERT INTO cohort_users (user_id)
        SELECT id
            FROM users
            WHERE registered_at BETWEEN %(datestart_int)s AND %(dateend_int)s
        ;
    
    SELECT  1, FROM_UNIXTIME(%(dateend_int)s, %(timepattern)s)
    UNION ALL
    SELECT  (COUNT(DISTINCT x.user_id)/(SELECT COUNT(1) FROM cohort_users)), 
            FROM_UNIXTIME((%(dateend_int)s + (7 * 24 * 60 * 60)), (timepattern)s)
        FROM cohort_users z
        INNER JOIN actions x ON x.user_id = z.id
        WHERE x.did_at BETWEEN (%(datestart_int)s + (7 * 24 * 60 * 60))
        AND (%(dateend_int)s + (7 * 24 * 60 * 60))
        ;
    
    DROP TABLE cohort_users;
    """
    

    【讨论】:

    • 我遇到了这个问题,我认为可能会记录在这里:bugs.mysql.com/bug.php?id=10327。完整的 SQL 包含更多引用 cohort_users 表的联合。
    • @Nai:这与您提出的问题无关。根据您提供的链接,多次提及临时表的错误消息是ERROR 1137: Can't reopen table: <table_name>。你说你收到的消息是format requires a mapping。看起来您已经解决了 NEXT 问题。在决定哪个(如果有)答案适合 THIS 问题时,请忽略下一个问题。
    • @Nai:我不是 mysql 专家……我唯一能想到的就是将那个大的 SELECT 分解为多个 SELECT 并在 Python 中执行您自己的“UNION ALL”。顺便说一句,你有z.id,它应该是z.user_id
    • 啊谢谢好地方:P。我发现的解决方法是这样做:CREATE TABLE cohort_users ENGINE = MeMORYFYI。
    【解决方案2】:

    executemany() 用于在多个参数上执行相同的单个语句。

    你想要的是另一种方式:只需在每个语句上调用 execute()。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-03-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-30
      • 1970-01-01
      相关资源
      最近更新 更多