Python实现Mysql查询字段缺失处理

文摘   科技   2024-05-10 19:11   广东  

ISEE小语


《羊皮卷》中有一句话:“人真的忙起来,根本没有太多复杂情绪;人太闲,才会把鸡毛蒜皮当回事。”



本次分享是由于小栈在实际中,在查询多个数据库中的users_msg表时,有的库中有en_name,有的库中没有这个字段,在实现过程中出现

1054 - Unknown column 'en_name' in 'field list'

由于固执己见,踩了坑,这里来记录一个简单的例子



环境:

Python
3.9.16
三方库

mysql-connector-python==8.1.0

PyMySQL==1.1.0




安装:

pip install mysql-connector-python==8.1.0pip install PyMySQL==1.1.0


前提准备


小栈本地环境的Mysql的版本是5.7.32

有的users_msg表中有字段id,name,age,score


有的表字段是id,name,en_name,age,score



基本查询

接下来查询id为8,en_name的值

SELECT en_name FROM users_msg WHERE id=8;

(左右滑动查看完整代码)

两个结果,

第一个库没有en_name字段的表,结果:

提示【Unknown column 'en_name' in 'field list'】


第二个库的存在en_name字段的表,结果:


固执己见的小栈认为可以直接一个sql搞定,开始网上查阅资料


网上方式

方式一:使用COALESCE函数的机制来实现

这里的意思是通过COALESCE函数会检查en_name的值,如果en_name是NULL,它就返回default_name;否则,返回en_name的实际值。

SELECT     COALESCE(en_name, 'default_name') AS en_nameFROM     users_msg WHERE     id = 8;

(左右滑动查看完整代码)

很遗憾,这个方式不可以,看一下结果:

但这个方式适合在当前表中已经存在的字段,如果这个字段的值为NULL,使用这个方式,它就返回default_name;否则,返回en_name的实际值。


方式二:使用IFNULL函数

这里的意思是通过IFNULL函数用于将NULL值替换为指定的默认值。

SELECT     IFNULL(en_name, 'default_name') AS en_nameFROM     users_msg WHERE     id = 8;

(左右滑动查看完整代码)

很遗憾,这个方式仍不可以

实际使用效果,与以上COALESCE函数的方式类似


方式三:使用IF语句结合EXISTS条件

这里的意思是通过查询users_msg表中是否存在en_name字段,如果不存在则返回默认值,否则返回en_name的实际值。

SELECT    CASE        WHEN EXISTS (            SELECT 1            FROM information_schema.`COLUMNS`            WHERE table_name='users_msg' AND COLUMN_name = 'en_name'        ) THEN en_name        ELSE 0    END AS en_name_existsFROM    users_msgWHERE    id = 8;

(左右滑动查看完整代码)

很遗憾,这个方式也不可以

这个方式看逻辑实现很清晰,感觉没有什么问题,但仍会提示【1054 - Unknown column 'en_name' in 'field list'】

原因是由于不能直接使用CASE WHEN EXISTS来处理字段不存在的情况


小栈总结

上三种处理方式,均未能解决,是因为查询本身需要知道字段是否存在才能执行。

如果尝试在查询中使用不存在的字段,MySQL会抛出一个【1054 - Unknown column 'en_name' in 'field list'】的错误,指出该字段是未知的。

这个基本常识性的问题,让好奇心盖过去了。

结果就是,一个sql处理,小栈没搞定


小栈方式

接下来,在实现逻辑里面处理

首先,先查en_name字段是否存在

exists_sql = "SELECT 1 FROM information_schema.`COLUMNS` WHERE TABLE_SCHEMA = 'self_test' AND table_name='users_msg' AND COLUMN_name = 'en_name' LIMIT 1;"cursor.execute(exists_sql)is_exists = cursor.fetchone()print(is_exists)

(左右滑动查看完整代码)

以上执行的结果:

如果'en_name'存在,输出:(1,)

如果'en_name'不存在,输出:None


然后,根据输出的结果进行判断,再进行查询

if is_exists:    # 如果存在,则返回en_name的实际值    _sql = "SELECT en_name FROM users_msg WHERE id = 8;"else:    # 如果不存在,则返回赋给en_name的默认值    _sql = "SELECT 'default_name' AS en_name FROM users_msg WHERE id = 8;"cursor.execute(_sql)result = cursor.fetchone()print(result)


主要代码

如果没有前期固执己见的纠结,其实会很简单

# -*- coding: utf-8 -*-
import mysql.connector
# 连接MySqldb_config = { 'host': '127.0.0.1', 'user': 'root', 'password': '123456', 'port': 3306, 'database': 'self_test'}cnx = mysql.connector.connect(**db_config)cursor = cnx.cursor()
exists_sql = "SELECT 1 FROM information_schema.`COLUMNS` WHERE TABLE_SCHEMA = 'self_test' AND table_name='users_msg' AND COLUMN_name = 'en_name' LIMIT 1;"cursor.execute(exists_sql)is_exists = cursor.fetchone()print(is_exists)
if is_exists: # 如果存在,则返回en_name的实际值 _sql = "SELECT en_name FROM users_msg WHERE id = 8;"else: # 如果不存在,则返回赋给en_name的默认值 _sql = "SELECT 'default_name' AS en_name FROM users_msg WHERE id = 8;"cursor.execute(_sql)result = cursor.fetchone()print(result)
# 结束

(左右滑动查看完整代码)


总结

栈记录,只为个过程。

结果实现上可能会有更好的方式,也可能一个sql能搞定,但小栈放弃了

如果哪位朋友有更好的方式,希望给小栈留个言,小栈还是想“固执己见”

上面提到的数据库,在以往的文章中分享过,小栈直接拿过来使用的

Python实现MySql数据库导出表结构和数据功能-实例

ISEE小栈,公众号:ISEE小栈Python实现MySql数据库导出表结构和数据功能-实例


【Mysql】合集中有几篇实例,有兴趣的同学可以看看,挺有意思。




有兴趣的朋友点个“”和“在看”,谢谢支持~!


     

文章就分享到这儿,喜欢就点个吧!



推荐阅读  点击标题可跳转


ISEE小栈
没有花里胡哨,简单才是王道。
 最新文章