pymysql 关于带参的正则查询问题

2021-12-15 11:24:07 +08:00
 gossip
有个商品表,我打算通过品名查询,但考虑下这种商品名很乱,势必要用正则来取:
+----+---------------------------------------+
| id | name |
+----+---------------------------------------+
| 1 | r510vc 15.6 英寸笔记本 |
| 2 | y400n 14.0 英寸笔记本电脑 |
| 3 | g150th 15.6 英寸游戏本 |
| 4 | x550cc 15.6 英寸笔记本 |
| 5 | x240 超级本 |
| 6 | u330p 13.3 英寸超级本 |
| 7 | svp13226scb 触控超级本 |
| 8 | ipad mini 7.9 英寸平板电脑 |
| 9 | ipad air 9.7 英寸平板电脑 |
| 10 | ipad mini 配备 retina 显示屏 |
| 11 | ideacentre c340 20 英寸一体电脑 |
| 12 | vostro 3800-r1206 台式电脑 |
| 13 | imac me086ch/a 21.5 英寸一体电脑 |
| 14 | at7-7414lp 台式电脑 linux ) |
| 15 | z220sff f4f06pa 工作站 |
| 16 | poweredge ii 服务器 |
| 17 | mac pro 专业级台式电脑 |
| 18 | hmz-t3w 头戴显示设备 |
| 19 | 商务双肩背包 |
| 20 | x3250 m4 机架式服务器 |
| 21 | 商务双肩背包 |
+----+---------------------------------------+

比如输入电脑,就显示含有电脑关键字的。于是我写了个查询的类,下面定义一个依据名称查询的方法:

def search_by_name(self):
goods_name = input('请输入您要查询的商品名:')
# sql_command = 'select * from goods where name regexp ".*%s.*"' % goods_name
# self.execute_sql_command(sql_command)
#self.cursor.execute('select * from goods where name regexp ".*%s.*"',[goods_name,])
sql = 'select * from goods where name=%s'
paras = (goods_name,)
self.cursor.execute(sql,paras)
for item in self.cursor.fetchall():
print(item)

1.被注释掉的 self.cursor.execute('select * from goods where name regexp ".*%s.*"',[goods_name,])一句是我想达到的目标,但是发现不成功

于是我猜想可能是正则语句太复杂了?上面有一重引号,导致解析时候发生了错误
2.为了验证呢,于是写了
sql = 'select * from goods where name=%s'
paras = (goods_name,)
self.cursor.execute(sql,paras)

这三行没问题,没有用正则,只是普通参数化查询,是可以成功的。
3.另外非参数化的构造 sql 语句再执行的方法,也能把这个正则查询跑出来,但是会有 sql 注入问题(也就是上面被注释掉的前两行的方法)

因为是 python 初学者,这个问题应该在前端做规则限制吧。但是还是想知道应该怎么写这种带参的正则查询呢?
2181 次点击
所在节点    Python
7 条回复
ErenJaeger
2021-12-15 13:59:15 +08:00
MySQL 正则还真没用过,可以用模糊查询 like
peonone
2021-12-15 15:41:25 +08:00
试试
self.cursor.execute('select * from goods where name regexp %s',[f".*{goods_name}.*",])
gossip
2021-12-15 15:55:26 +08:00
@peonone 正解了,想问下大佬,这个问题出在哪了呀,为啥里面有双引号就不行呢?
另外您的写法从哪里看到的,我谷歌了一上午没找到好的方法
dayeye2006199
2021-12-16 03:44:20 +08:00
您这自己拼 SQL ,眼看着要被注入攻击的感觉;用 prepared statement 把
peonone
2021-12-16 11:26:47 +08:00
@gossip 在 SQL 字符串里%s 需要是一个完整的参数值代位符,".*%s.*"这样是不行的。
我也没找到相关的文档,从我的经验来的:)


@dayeye2006199 只有被注释的前两行是拼 SQL 的方式,LZ 想解决的问题就是在使用 prepared statement 了。
但还是要注意会把用户输入的内容当作正则来处理,比如用户输入".*",会匹配任意字符
gossip
2021-12-16 12:09:22 +08:00
@peonone 感谢啦,您说得没错,觉得这个问题这么解决还不是办法。不过也是没接触过前端,写了个增删改查 sql 的小程序练练手,只有后端的 python 代码。本来想用查询先都把结果干出来,然后 python 对结果进行正则的,后来想了下,觉得这样效率不高,还是放在数据库端了在查询的时候做了匹配。

不知道真的生产环境下该怎么处理这种问题呢?
peonone
2021-12-16 14:53:13 +08:00
真实环境下这种场景不会使用正则去查询数据库的,效率太低,需要扫描整个表,对每行的商品名做正则匹配,IO 和 CPU 消耗都很高,一种解决办法是使用检索引擎,比如 ElasticSearch ,MySQL 也有全文检索功能 https://dev.mysql.com/doc/refman/8.0/en/fulltext-search.html ,可以用来实现个简单原型试试。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/822324

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX