作者MrMarcus (请勿忘记密码)
看板PHP
标题Re: [请益] 复选的限制查询
时间Sun Jul 1 01:58:54 2007
※ 引述《yo0401 (羽无伦)》之铭言:
: 小弟我想做复选的限制查询
: 但是第一次做,不知道有没有更好的写法
: 我的想法是:
: 譬如衣服的颜色 黄、绿、红
: SELECT * FROM 资料表 WHERE 栏位 like XXX $limit;
: $limit="limit $color1 $color2 $color3";
: if (empty($color=红){
: $color1=null;
: }else{
: $color1="color=红 and"
: }
: .
: .
: .
: (没测试过,只是有这个想法,上面的想法还有很多问题还待解决)
: 不知道有没有人有更好的写法,或是有参考的网站(希望是中文)
: 我的目的是要限制查询的条件,而且是复选
这个问题要从两方面来看,一个是如何在php里面取得表单栏位的复选资料,
一个是如何写出SQL query。
在HTML表单里面要做复选通常是使用核取方块(checkbox):
<form action="act.php" method="get">
颜色:
<input type="checkbox" name="color[]" value="黄" />
<input type="checkbox" name="color[]" value="绿" />
<input type="checkbox" name="color[]" value="红" />
<input type="submit">
</form>
注意栏位名称是color[],有了[],php会帮你把这些栏位资料转成阵列,
在act.php里面你可以透过$_GET['color']来取得使用者勾选的颜色。
如果使用者勾选了黄和绿,$_GET['color']会是
array(
0 => '黄',
1 => '绿'
)
如果都没有勾选,$_GET['color']这个变数就不存在(这很重要,是
不存在,而不是一个空的阵列,这两者差异很大)。
在SQL query方面,首先LIMIT这个语法(适用mysql, postgresql)
的使用方式跟你原本设想的并不一样,它是用来限制传回的资料笔数
而不是过滤哪些资料会被传回。如果你使用IN语法的话,若使用者
勾选黄色绿色,那麽:
SELECT ..... WHERE color IN ('黄', '绿')
便会找出color栏位值"等於"黄或者绿的资料。所以问题变成如何组出
以上的SQL。你可以使用:
$query = "SELECT...WHERE color IN ('".implode("','", $_GET['color'])."')";
但是这是假设使用者至少有勾选一项颜色。如果完全没勾选就送出,
如同前面所述,此时$_GET['color']并不存在,因此implode()那里
就会出现错误讯息,指出$_GET['color']不是一个有效的阵列。
(如何处理万一使用者没有勾选任何颜色的状况就不讨论了。
提示:isset())。
但是IN语法只能找出栏位值完全符合的资料,如果要找出栏位值
"包含"黄或者绿的资料,那得改用LIKE搭配万用字元。
SELECT...WHERE color LIKE '%黄%' OR color LIKE '%绿%'
会找出color栏位值"包含"黄或者绿的资料。要组出这个SQL,可以:
$query = "SELECT...WHERE 1 = 0 ";
foreach($_GET['color'] as $color) {
$query .= (" OR color LIKE '%".$color."%' ");
}
这会组出:
SELECT...WHERE 1 = 0 OR color LIKE '%黄%' OR color LIKE '%绿%'
你可能会觉得那个 1 = 0 是做啥的。这算是个撇步,它可以让你在组
出後面的OR...的时候不用考虑现在不是在阵列的第一个元素(是的话
就不能加上OR,不是才能加上OR,否则组出来的字串会有问题)。
mysql本身有最佳化功能,会把1=0这种显然不成立的条件忽略掉。
同样,这里也没有考虑万一使用者没有勾选任何颜色的状况。
--
是说後半段其实比较适合丢去database板。
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 220.132.153.19
1F:→ MrMarcus:如果能确定要比对的字串都出现在栏位值的开头,那就使用 07/01 02:02
2F:→ MrMarcus:LIKE '黄%',这会比 LIKE '%黄%'的查询速度快。 07/01 02:02