避免提交给sql的空白和重复条目

时间:2011-12-12 09:01:34

标签: php mysql database logic

我正在努力解决这段代码的逻辑问题。我认为使用后退按钮时会出现空白条目。这是针对残疾学习者的问卷调查系统,每页只询问一个问题,并为每个问题单独提交结果。有一个单独的表格用于确定调查是否已完全完成(我使用GET跟踪唯一ID),结果仅来自完全完成的结果。

我尝试使用UPDATE响应/注释,其中存在quesitonID和唯一ID,但这似乎会产生更多问题。为了清晰起见并允许一些思想自由,我将代码削减到最低限度。非常感谢。

编辑:'响应'是一个单选按钮条目,'评论'是文本输入。 'UniqueID','surveyID','QID'& 'type'在URL中确定并使用GET捕获。

mysql_query("

INSERT INTO answers (uniqueID, surveyID, QID, type, response, comment) 
SELECT '$U', '$S','$Q', '$t', '$response', '$comments' 

") 
or die(mysql_error());  


if (isset($_GET['start']))   {

mysql_query("

INSERT INTO complete (uniqueID, surveyID) 
VALUES('$U', '$S') 

") 
or die(mysql_error()); 

}     

if (isset($_GET['finished']))   { 

mysql_query("

UPDATE complete 
SET timestamp = NOW() 
WHERE uniqueID='$U' 

") 
or die(mysql_error()); 

}

2 个答案:

答案 0 :(得分:1)

如果您在插入重复值或空值时询问如何让mysql抱怨,答案是:

  • UNIQUE约束(uniqueID,surveyID,QID)以避免重复
  • 用于避免空值的NOT NULL约束

阅读有关约束的内容,请进入MySQL docs

但是如果提供的值存在且格式正确,我也会检查PHP。没有提到SELECT '$U', '$S','$Q', '$t', '$response', '$comments'编写查询的方式非常危险,因为允许不同类型的代码注入。

答案 1 :(得分:1)

您的代码不会进行任何验证,只有die才会出现错误 这在生产代码中不起作用。

就验证而言,您有两个选择:

A - 检查php中的输入并禁止任何非法值 B - 使用SQL约束并监视输出。
或两者的结合。

选项 B 的问题在于,您只需从MySQL获得一个错误,您必须在php中处理该错误。
出于这个原因,我会选择A.

第一步:逃避输入
最好的方法是使用PDO 如果你使用mysql_ lib,你必须在每个输入上使用mysql_real_escape_string来逃避它并引用你的$vars;像这样:

$a = mysql_real_escape_string($_GET['param1']);
examplequery = "SELECT * FROM table1 WHERE field1 = '$a' ";

对于整数值,您可以将变量强制转换为整数,然后将其注入而不带引号。

$a = intval($_GET['param1']);
$b = intval($_GET['param2']);
if $a > $b { list($a,$b) = array($b,$a); }  //Exchange the two vars if needed.
examplequery = "SELECT * FROM table1 WHERE field1 BETWEEN $a AND $b";

验证您的数据
这里你有两个选项,你可以将验证硬编码到php中,或者使用SQL来检查输入 我喜欢第二种方法,因为它允许您将所有信息放入有效输入到数据库中。

使用验证表验证您的数据
  一种选择是创建一个像这样的表:

table Checks (
  fieldname varchar(50) not null,
  tablename varchar(50) not null,
  fieldtype enum('int','varchar','enum','decimal'.....) not null,
  min_value double default -1000000;
  max_value double default 1000000;
  validation_query varchar(1000) default null, 
  primary key (tablename, fieldname)) ENGINE = InnoDB;

现在你可以像这样检查一个参数(使用PDO):

$stmt = $dbh->prepare("SELECT fieldtype, min_value, max_value, validation_query
                       FROM checks WHERE fieldname = ? AND tablename = ?");
$stmt->execute(array('field1', 'table1'));
$result = $stmt->fetch(PDO::FETCH_ASSOC);
switch ($result['type']) {
  case 'int':
    $allOK = isnumeric($inputvalue_to_check); 
    $allOK = $allOK AND ($intval($inputvalue_to_check) >= $result['min_value']
                     AND $intval($inputvalue_to_check) <= $result['max_value']);
    if is_null($result['validation_query']) {
      $sql = $result['validation_query'];
      $check = $dbh-?prepare($sql);
      $check_result = $check->execute(array($inputvalue_to_check));
      $check_result->fetch(PDO::FETCH_ASSOC);
      if is_null($check_result['result']) { //value is not OK}
    break;
  case .......

在php验证
如果您知道自己的数据并且无法更改,则可以使用ifswitch语句进行验证。
这段代码看起来很像上面的代码,除了它不从数据库获取数据,逻辑是硬编码而是存储在php数据结构中。