【问题标题】:MySQL update or insert based on fetchall results in Python基于 Python 中 fetchall 结果的 MySQL 更新或插入
【发布时间】:2021-05-12 20:09:18
【问题描述】:

我需要通过本地 python 脚本在我的 wordpress 中设置一些用户元数据。因此我不能使用 WP update_user_meta ——它必须手动完成。

import mysql.connector as mysql
cnx = mysql.connect(host=HOST, database=DATABASE, user=USER, password=PASSWORD)
cursor = cnx.cursor()
get_meta = ("SELECT * FROM `ff_usermeta` WHERE `user_id`= 1 AND (`meta_key`='nickname' OR `meta_key`='info' OR `meta_key`='bg' OR `meta_key`='avatar' OR `meta_key`='profile_updated')")
cursor.execute(get_meta)
meta = cursor.fetchall()
#some processing of the result
cursor.execute(q, (...))
cnx.commit()
cursor.close()
cnx.close()

现在我需要检查结果是否包含每个键的元数据。 如果此用户的密钥已存在,则需要为此元运行 UPDATE。 如果该用户仍然没有此键的元数据,则必须插入新行。

if(there's no 'nickname' in meta_key on either of 5 or less rows):
   q = ("INSERT INTO `ff_usermeta` ...")
else: 
   q = ("UPDATE `ff_usermeta` ...")

...还有 4 次这样的?.. 似乎是一个循环的好地方,但我真的不喜欢让它成为 5x 队列的想法,特别是因为将来可能会有更多的字段。

我正在考虑在 fetchall 结果中搜索 meta_key 中的匹配项,如果找到,则将所需数据添加到一个数组中,如果没有,则添加到另一个数组中。然后在最后只运行一次更新和一次插入,假设两者都不为空。如果我用 semi-php 风格写的话,大概是这样的:

if(in_array("nickname", meta))
    for_update .= "`nickname`='"+data[0]+"', "
else:
    fields .= "`nickname`, "
    vals .= "'"+data[0]+"', "
if(in_array("bg", meta)):
    for_update .= "`bg`='"+data[1]+"', "
else:
    fields .= "`bg`, "
    vals .= "'"+data[1]+"', "
    
if(for_update):
    update = ("UPDATE `ff_usermeta` SET "+for_update+" WHERE 1")
if(fields):
    insert = ("INSERT INTO `ff_usermeta`("+fields+") VALUES ("+vals+")")

但绝对不知道如何将它正确地翻译成 python。我不得不用谷歌搜索“为什么不能将一个字符串添加到另一个字符串”之类的东西。有什么建议吗?或者也许有更好的方法?谢谢!

【问题讨论】:

  • 我们不知道你的结果集是什么样子的,写 SELECT * 也是一种不好的形式,要么你需要返回很多信息并花费时间,要么你真的需要所有信息,但是它仍然是糟糕的形式
  • user_meta 中只有 4 个字段:umeta_id、user_id、meta_key、meta_value。我认为如果我用 * 选择它们或通过命名它们中的每一个来选择它们并不重要,但我想我知道的 4 个中的一个并不需要太多。但这就像要解析的数字少了 1 个,而且每分钟不会超过 1 个用户。
  • 你有 LIMIT 1,所以你只得到 1 个元值,最好也发布表格和数据,因为你需要一个更复杂的查询
  • 限制为 5 个,而不是 1 个 - 或者您的意思是使其成为 5 个单独的选择请求,每个请求 1 行?我想那样做,但这不会在 mysql 上造成不必要的负载吗?
  • 我看错了,您的查询不需要限制,因为当所有元键都存在时,它只会得到 5 行。

标签: python php mysql wordpress


【解决方案1】:

它不完整,你不能用那种方式更新你的行。

但是有了这个你就可以开始查询了

如果 user_id 存在,第一个选择正好是 1 行。

user_id 似乎不是正确的选择,但要得到你能做的就足够了。

如果查询没有条目,它将插入一些您从任何地方获得的数据

插入时的更新是错误的,因为您必须插入 5 个新的 orws 或更新最多 5 行,但这更适合您编程

import mysql.connector as mysql
HOST = "localhost"
DATABASE = ""
USER = "root"
PASSWORD = "mypassword"
cnx = mysql.connect(host=HOST, database=DATABASE, user=USER, password=PASSWORD)

cnx = mysql.connect(host=HOST, database=DATABASE, user=USER, password=PASSWORD)
cursor = cnx.cursor()
user_id = 1
get_meta = ("""SELECT  umeta_id, user_id , MAX(IF( `meta_key`='nickname', meta_value,'')) AS 'nickname' , MAX(IF( `meta_key`='info', meta_value,'')) AS 'info' , MAX(IF( `meta_key`='bg', meta_value,'')) AS 'bg' , MAX(IF( `meta_key`='avatar', meta_value,''NULL'')) AS 'avatar' , MAX(IF (`meta_key`='profile_updated', meta_value,'')) AS 'profile_updated' FROM `ff_usermeta`  WHERE `user_id`= %s GROUP BY umeta_id, user_id:""")
result = cursor.execute(get_meta,(user_id,))
if result > 0:
    data = cursor.fetchone()
    for_update = "";
    #some processing of the result
    if not data["nickname"]:
        for_update += "`nickname`='"+data["nickname"]+"', "
        if not data["bg"]:
            for_update += "`bg`='"+data["bg"]+"', "
        query = ("UPDATE `ff_usermeta` SET "+for_update+" WHERE user_id = " + user_id)
else:
    #here are no data to be gathered as there is no user_id present add new user
    nickname = ""
    bg= ""
    info = ""
    avatar = ""
    profile_updated = ""
    fields= ""
    vals = ""
    fields += "`nickname`,`info`, `bg`,`avatar`,`profile_updated`"
    vals += "'"+nickname+"', "+"'"+info+"', "+"'"+bg+"', "+"'"+avatar+"', "+"'"+profile_updatedfo+"'"
    query = ("INSERT INTO `ff_usermeta`("+fields+") VALUES ("+vals+")")
cursor.execute(query)
cnx.commit()
cursor.close()
cnx.close()

【讨论】:

  • 嘿,非常感谢!我不知道 mysql 会允许在其内部处理所有这些,我不是很流利地知道这一点,但我想我可以从那里处理它。真的很有帮助!
【解决方案2】:

我已尽力调整上述建议,但不知道如何使其发挥作用。最终我采用了另一种方式,它似乎以某种方式工作,所以我会发布完整的代码,以防有人发现它有用。

它的作用:使用验证请求检查表中的队列,然后解析页面(单独的函数)并相应地更新用户配置文件。

import mysql.connector as mysql
import time
from datetime import datetime
cnx = mysql.connect(host=HOST, database=DATABASE, user=USER, password=PASSWORD)
while True: #endless loop as a temporary scheduler
    cursor = cnx.cursor()
    #getting first request in the queue - 0: id, 1: url, 2: parse, 3: status, 4: user, 5: user_page, 6: req_date, 7: action
    cursor.execute("SELECT * FROM `ff_qq` WHERE status = 0 LIMIT 1")
    row = cursor.fetchone()
    if row:
        status = 1 #processed
        if row[7] == "verify":
            get_user = ("SELECT * FROM `ff_users` WHERE ID = %s LIMIT 1")
            cursor.execute(get_user, (row[4],))
            user = cursor.fetchone() #0 - ID, 5 - user_url, 8 - user_status, 9 - display_name
            #separate function that returns data to insert into mysql
            udata = verify(row) #0 - nickname, 1 - fb_av, 2 - fb_bg, 3 - fb_info, 4 - owner
            ustat = row[1].split("/authors/")
            if udata['owned'] or user[8] == ustat[1]:
                update_user = ("UPDATE `ff_users` SET user_status = %s, display_name = %s, user_url = %s WHERE ID = %s LIMIT 1")
                cursor.execute(update_user, (ustat[1], udata['nickname'], row[1], user[0]))
                status = 2 #success
                get = ("SELECT `meta_value` FROM `ff_usermeta` WHERE `user_id`= %s AND `meta_key`='ff_capabilities' LIMIT 1")
                cursor.execute(get, (row[4],))
                rights = cursor.fetchone()
                if rights == 'a:1:{s:10:"subscriber";b:1;}':
                    promote = ("UPDATE `ff_usermeta` SET `meta_value` = 'a:1:{s:6:\"author\";b:1;}' "
                                       "WHERE `user_id` = %s AND `meta_key`='ff_capabilities' LIMIT 1")
                    cursor.execute(promote, (row[0],))
                #list of meta_key values in same order as returned data
                ff = ['nickname', 'fb_av', 'fb_bg', 'fb_info']
                for x in range(0,3): #goes through each one of the above list
                    if udata[ff[x]]: #yes this actually works, who would've thought?..
                        #current meta_key added directly into the string
                        get = ("SELECT `meta_value` FROM `ff_usermeta` WHERE `user_id`= %s AND `meta_key`='" + ff[x] + "' LIMIT 1")
                        cursor.execute(get, (row[4],))
                        meta = cursor.fetchone()
                        if(meta): #update if it exists, otherwise insert new row
                            qq = ("UPDATE `ff_usermeta` SET `meta_value` = %s "
                                       "WHERE `user_id` = %s AND `meta_key`='" + ff[x] + "' LIMIT 1")
                        else:
                            qq = ("INSERT INTO `ff_usermeta`(`meta_value`, `meta_key`, `user_id`) "
                                   "VALUES ('%s','" + ff[x] + "','%s'")
                        cursor.execute(qq, (udata[ff[x]], row[0])) #same execute works for both
            else:
                status = 3 #verification failed
        #update queue to reflect its status
        update = ("UPDATE `ff_qq` SET status = %s WHERE id = %s LIMIT 1")
        cursor.execute(update, (status, row[0]))
        cnx.commit()
        cursor.close()
    now = datetime.now()
    print(now.strftime("%d.%m.%Y %H:%M:%S"))
    time.sleep(180) #sleep until it's time to re-check the queue
cnx.close()

【讨论】:

    猜你喜欢
    • 2017-01-20
    • 1970-01-01
    • 2013-03-06
    • 1970-01-01
    • 1970-01-01
    • 2017-08-15
    • 1970-01-01
    • 2011-05-11
    相关资源
    最近更新 更多