不区分大小写的多列postgres搜索


case insensitive postgres search with multiple columns

我想在PHP中创建一个联系人表单搜索。

示例条目:

名称:粉红色

电话:555-888-1234

我想在输入框中搜索姓名和电话,并返回LIKE匹配结果,不区分大小写。

例子:

在姓名中搜索'p'而不包含电话号码,并返回结果

在电话号码字段中搜索'5',没有名字,得到结果。

搜索"x"在name字段中,没有得到结果,目前我得到了结果。

$query = "SELECT * FROM contacts WHERE name ~* '.*$name.*' OR phone ~* '.*$phone.*'";

想象一下(但不要实际运行它!)如果在name字段中放入以下内容会发生什么:

');DROP TABLE contacts;--

欢迎学习SQL注入。Bye Bye contacts表,除非您使用的用户不是表的所有者——但即使这样,DELETE FROM contacts;也可能工作。


猜一下,发生的事情是,如果phonename是空白的,则将其替换为空字符串。所以给定.*$phone.*,产生一个像.*.*的正则表达式,当然是匹配任何。因为有一个OR子句,您的测试与空白电话和名称= x测试

name ~* '.*x.*' OR phone ~* '.*.*'

当然对于name中的任何值都是正确的。

您应该能够通过查看实际运行的查询来判断这一点。打开postgresql.conf中的log_statement=all,使用PostgreSQL查询日志


你需要做的是:

  • 动态构建查询。如果过滤器中没有phone的条目,则完全去掉OR phone ~* ...子句。

  • 使用查询参数将您的值正确地注入到查询中。即使您是通过在客户端进行连接或使用如下方式来连接值,也可以这样做:

    WHERE name ~* '.*'||$1||'.*'
    

    其中$1是查询参数占位符。我不记得PHP是否使用?之类的;

  • 在将值作为参数发送之前,转义正则表达式元字符。否则,用(搜索phone将产生语法错误,因为无效的regexp。