测试sqlite表中是否存在值的最佳方法是什么?

时间:2011-06-21 05:55:33

标签: php sqlite pdo

这里的第一个问题,如果我做了一些愚蠢的事情,请不要打扰我!

我正在创建一个包含注册等的登录系统。在注册时我需要测试3件事情,看看他们是否已经在使用。

我的初始测试代码如下所示:

$IDq = $userdbc->query("SELECT * FROM users WHERE userID = '$uID'");
$IDq->setFetchMode(PDO::FETCH_ASSOC);
$IDf = $IDq->fetch();
if($IDf['userID']){
    echo '<p>ID exists</p>';
}
else{
    echo '<p>ID does not exist?</p>';
}

我将需要测试可能重复的电子邮件和显示名称..我确定必须有更好的方法来解决这个问题吗?

或者我真的要重复这个过程3次以测试每个项目吗?

这是我第一次使用数据库解决方案的真正冒险..非常感谢任何有用的输入 - 提前感谢!

编辑:我确实需要单独测试每个值,以便我可以使用适当的错误消息重建注册表单,说明确切需要更改的内容。对不起,我应该更具体。


编辑:解决方案 - 谢谢Shakti Singh,以及其他所有人的帮助。

该函数(使用带有命名占位符的预准备语句):

function item_exists($dbc, $col, $val){
    $query = $dbc->prepare("SELECT * FROM users WHERE $col = :val");
    $query->execute(array(':val' => $val));
    $fetch = $query->fetch();
    if($fetch[$col]){
        return true;
    }
    else{
        return false;
    }
}

我如何在我的注册验证功能中使用它:

$userdbc = new PDO('sqlite:db/users.s3');

if(item_exists($userdbc, 'userID', $_POST['id'])){
    $valid = false;
    array_push($sub['e'], 'User ID is not available.');
}
if(item_exists($userdbc, 'userEmail', $_POST['email'])){
    $valid = false;
    array_push($sub['e'], 'Email Address is already in use.');
}
if(item_exists($userdbc, 'userName', $_POST['name'])){
    $valid = false;
    array_push($sub['e'], 'Display Name already taken.');
}
$userdbc = null;

编辑:其他:

因为我只测试了一个项目,所以我替换了item_exists()函数:

$query->execute(array(':val' => $val));

有:

$query->bindParam(':val', $val);
$query->execute();

..只是因为执行一个数组对我来说似乎有些愚蠢,因为它只有一个键/值..

不知道实际差异可能是什么,但嘿,这是另一种选择。

编辑:附加 - 附加:

所有更改的功能:

function item_exists($dbc, $col, $val, $rn){
    // updated the prepare statement as per James Anderson's suggestion.
    $query = $dbc->prepare("SELECT COUNT($col) AS dupli FROM users WHERE $col = :val");
    $query->bindParam(':val', $val);
    $query->execute();
    $fetch = $query->fetch();
    // $fetch['dupli'] contains the number of matches found.
    // $fetch[0] should also work, but not tested.
    if($rn){ // if $rn = true, return the number of finds
        return $fetch['dupli'];
    }
    else{ // else we are just testing for a match so..
        if($fetch['dupli'] > 0){ // if we have one
            return true;
        }
        else{
            return false;
        }
    }
}

我觉得我应该加上这个以防万一其他人像我一样挣扎,总是很高兴有工作的例子 - 也有评论^ _~

我很确定这将是我的最后一次编辑,但是......永远不会知道。

4 个答案:

答案 0 :(得分:2)

不要重复此过程3次以测试每个项目。

只需创建一个通用方法或函数,将为要检查的每个项调用该函数,并根据数据库值返回true或false。

function item_exists($item_value,$item_type)
{
   $IDq = $userdbc->query("SELECT * FROM users WHERE $item_type= '$item_value'");
   $IDq->setFetchMode(PDO::FETCH_ASSOC);
   $IDf = $IDq->fetch();
   if($IDf[$item_type])
   {
     return true;
   } 
   else
   {
     return false;
   }
}

并像这样调用函数

if (item_exists($userID, 'userID') === true)
{
     echo 'user_id exists';
}

if (item_exists($emailID, 'email') === true)
{
     echo 'email exists';
}

此方法可让您知道重复的内容。这样您就可以向最终用户显示消息。

答案 1 :(得分:1)

它们是三个不同的测试,为什么不是三个SQL?

您可以而且应该将“select *”更改为“select count(*) as idcount”,因为只有索引访问才能满足整个查询。

如果您真的想在一个SQL中执行此操作,那么:

    Select sum(DUP_USER) as du, sum(DUP_NAME) as dn, Sum(DUP_EMAIL) as de 
from (
    Select Case when userId = '$Uid' then 1 Else 0 End AS DUP_USER
           Case when userName = '$uname' then 1 Else 0 End AS DUP_NAME
           Case when userEmail = '$uEmail' then 1 Else 0 End as DUP_EMAIL
    From users
     WHERE userID= '$uID' 
        OR userName = '$uName' 
        OR userEmail = '$uEmail' )

但老实说,三个单独的SQL更具可读性。

答案 2 :(得分:0)

只需在WHERE子句中添加条件(如

)三次,而不是这样做
WHERE userID= '$uID' OR userName = '$uName' OR userEmail = '$uEmail'

所以当这样做时,如果任何一个条件满足,那么你会得到一行,然后你就会知道存在重复的条目

修改

有关OR的进一步阅读 - 请在主题或优化

下查看The SQLite Query Planner

答案 3 :(得分:0)

您始终可以使用OR语句:

$IDq = $userdbc->query("SELECT * FROM users WHERE userID = '$uID' OR email='$email' OR displayName='$displayName'");
$IDq->setFetchMode(PDO::FETCH_ASSOC);
$IDf = $IDq->fetch();

echo ($IDf['userID'] == $uID) ? '<p>ID exists</p>' : '<p>ID does not exist?</p>';
echo ($IDf['email'] == $email) ? '<p>Email exists</p>' : '<p>Email does not exist?</p>';
echo ($IDf['displayName'] == $displayName) ? '<p>DisplayName exists</p>' : '<p>DisplayName does not exist?</p>';

我希望您在将这些值发送到数据库之前逃避这些值,并且在您的帖子中错过了该部分。否则你会接受SQL注入