使用PHP和MYsql。我有2个表,如
table'tag':字段'id'和'tag'('tag'是varchar)
表'entry':有字段'tags'和其他字段('tags'是varchar,它存储许多单词作为标记,每个单词用逗号分隔。然后我用函数'explode'从中提取标签要存储在数组'$ tags'中的字符串。表'entry'中的所有标记都存储在表'tag'中。)
我想要的是从表'tag'中选择所有'标签',它们是具有给定标签(变量$ tag)的表'entry'的相同字符串'标签'中的标签。但不知道,我只是尝试从表'entry'中选择SELECT标签'tags'中的哪个字符串包含指定的标签(变量$ tag)。我的当前代码是
$count=0;
$sql="SELECT tags FROM entry WHERE tag LIKE '%$tag%'";
$result = mysql_query($sql);
while($data=mysql_fetch_array($result)){
if(mysql_num_rows($result)!=0){
$tags1=explode(',',$data['tags']);
for($loop=0; $loop<=count($tags1)-1; $loop++){
if(!in_array($tags1[$loop], $tags2)){
$count+=1;
$tags2[$count]=$tags1[$loop];
}
}
}
}
答案 0 :(得分:2)
超低效,SQL注入攻击倾向于将其作为一个语句执行的方式是:
$sql="SELECT tags FROM entry WHERE 1=1 ";
然后在运行之前将每个标记添加到查询中:
$sql.="AND tag LIKE '" . $tags1[$loop] . "' ";
如果您想匹配任何代码而不是所有代码,请将AND
替换为OR
。
我真的建议对标记进行规范化,并考虑不以这种方式构建SQL查询。
答案 1 :(得分:2)
您解决此问题的困难都源于您将标签列表存储在一个列中。
您确实需要添加一个交集表,以包含标记和条目之间many-to-many relationship的数据。这是设计关系数据库的正确方法,如果您这样做,许多SQL查询将变得更有效。
例如,要获取与标记$tag
匹配的条目中的所有标记:
<?php
$sql = "SELECT t1.tag FROM tag AS t1
INNER JOIN entries_tags AS e1 ON e1.tag = t1.id
INNER JOIN entries_tags AS e2 ON e2.entry = e1.entry
INNER JOIN tag AS t2 ON t2.id = e2.tag
WHERE t2.tag = ?";
$stmt = $pdo->prepare($sql);
$result = $stmt->execute( array($tag) );
$data = $result->fetchAll();
$count = count($data);
我在我的书SQL Antipatterns: Avoiding the Pitfalls of Database Programming中写了一章来详细说明这个设计引起的实际问题。