You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何提交疫苗登记表单时出现SQLSTATE[23000]完整性约束违反错误?

疫苗登记系统表单提交问题分析与解决

问题描述

开发疫苗登记系统时,提交表单出现SQLSTATE[23000]: Integrity Constraint Violation错误,涉及$boost1brand至$boost2date2字段。给这些字段添加?? ""处理后不再报错,但MySQL中无插入记录。


相关代码及表结构

PHP插入代码

<?php
    if(isset($_POST['create'])) {
        $firstname = $_POST['firstname'];
        $middlename = $_POST['middlename'];
        $lastname = $_POST['lastname'];
        $houseno = $_POST['houseno'];
        $stsubd = $_POST['stsubd'];
        $brgy = $_POST['brgy'];
        $citymun = $_POST['citymun'];
        $bday = $_POST['bday'];
        $celno = $_POST['celno'];
        $telno = $_POST['telno'];
        $vaccbrand1 = $_POST['vaccbrand1'];
        $date1st = $_POST['date1st'];
        $vaccbrand2 = $_POST['vaccbrand2'];
        $date2nd = $_POST['date2nd'];
        $question1 = $_POST['question1'];
        $boost1brand = $_POST['boost1brand'];
        $date1once = $_POST['date1once'];
        $boost2brand1 = $_POST['boost2brand1'];
        $boost2date1 = $_POST['boost2date1'];
        $boost2brand2 = $_POST['boost2brand2'];
        $boost2date2 = $_POST['boost2date2'];

        $sql = "INSERT INTO users (firstname, middlename, lastname, houseno, stsubd, brgy, citymun, bday, celno, telno, vaccbrand1, date1st, vaccbrand2, date2nd, question1, boost1brand, date1once, boost2brand1, boost2date1, boost2brand2, boost2date2) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
        $stminsert = $db->prepare($sql);
        $result = $stminsert->execute([$firstname, $middlename, $lastname, $houseno, $stsubd, $brgy, $citymun, $bday, $celno, $telno, $vaccbrand1, $date1st, $vaccbrand2, $date2nd, $question1, $boost1brand, $date1once, $boost2brand1, $boost2date1, $boost2brand2, $boost2date2]);
        if($result) {
            echo "Successfully saved.";
        } else {
            echo "There were error while saving the data.";
        }
    }
?>

HTML表单代码

<p>Are you boostered?</p>
 <label for="once">Once</label> <input value="once" type="radio" id="boostone" name="question1" onclick="displayForm2(this)"><br>
 <label for="twice">Twice</label> <input value="twice" type="radio" id="boosttwo" name="question1" onclick="displayForm2(this)"><br>
 <label for="noboost">No</label> <input value="noboost" type="radio" id="boostno" name="question1" onclick="displayForm2(this)"><br>
     <div style="visibility:hidden; position:relative" id="onceboostContainer">
    <form id="onceboost">
     <div class="form-group">
     <label class="col-md-5 control-label">Brand of Vaccine</label>
      <div class="col-md-3 selectContainer">
      <div class="input-group">
     <span class="input-group-addon"><i class="glyphicon glyphicon-list"></i></span>
      <select name="boost1brand" id="booster1brand" class="form-control selectpicker">
        <option value="nullvac">Select Brand...</option>
        <option value="COVONAX">COVOVAX (Novavax formulation)</option>
        <option value="Comirnaty">Pfizer/BioNTech Comirnaty</option>
        <option value="Spikevax">Moderna Spikevax</option>
        <option value="SputnikLight">Gamaleya Sputnik Light</option>
        <option value="SputnikV">Gamaleya Sputnik V</option>
        <option value="Jcovden">Janssen (Johnson & Johnson) Jcovden</option>
        <option value="Vaxzevria">Oxford/AstraZeneca Vaxzevria</option>
        <option value="Covaxin">Bharat Biotech Covaxin</option>
        <option value="Covilo">Sinopharm (Beijing) Covilo</option>
        <option value="Inactivated">Sinopharm (Wuhan) Inactivated (Vero Cells)</option>
        <option value="CoronaVac">Sinovac CoronaVac</option>
        <option value="nonevac">None</option>
      </select>
    </div>
  </div>
  </div>
     <div class="form-group">
    <label class="col-md-5 control-label">Date of booster</label>  
    <div class="col-md-2 inputGroupContainer">
    <div class="input-group">
    <span class="input-group-addon"><i class="glyphicon glyphicon-th"></i></span>
    <input  name="date1once" id="date1stonce" class="form-control"  type="date" required>
      </div>
    </div>
  </div>
     <input type="submit" name="create" value="Register with one booster">
 </form></div>

MySQL表结构

CREATE TABLE `users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `firstname` varchar(50) NOT NULL,
  `middlename` varchar(50) NOT NULL,
  `lastname` varchar(50) NOT NULL,
  `houseno` varchar(50) NOT NULL,
  `stsubd` varchar(50) NOT NULL,
  `brgy` varchar(50) NOT NULL,
  `citymun` varchar(50) NOT NULL,
  `bday` varchar(50) NOT NULL,
  `celno` varchar(50) NOT NULL,
  `telno` varchar(50) NOT NULL,
  `vaccbrand1` varchar(50) NOT NULL,
  `date1st` varchar(50) NOT NULL,
  `vaccbrand2` varchar(50) NOT NULL,
  `date2nd` varchar(50) NOT NULL,
  `question1` varchar(50) NOT NULL,
  `boost1brand` varchar(50) NOT NULL,
  `date1once` varchar(50) NOT NULL,
  `boost2brand1` varchar(50) NOT NULL,
  `boost2date1` varchar(50) NOT NULL,
  `boost2brand2` varchar(50) NOT NULL,
  `boost2date2` varchar(50) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

问题分析

  1. 初始约束错误原因:MySQL表中boost1brand到boost2date2所有字段都设置为NOT NULL,但用户选择不同booster选项时,部分字段不会随表单提交(比如选"once"时,boost2brand1等字段不存在于POST数据中),直接取值会导致变量为null,违反非空约束。
  2. 添加?? ""后无插入记录的原因:
    • HTML存在嵌套表单:主表单内嵌套了<form id="onceboost">,提交时只会提交嵌套表单内的字段,主表单的必填字段(如firstname、vaccbrand1等)未被提交,导致这些字段值为null,仍然违反表的非空约束,execute()返回false但未输出具体错误。
    • 原HTML中<label for="noboost>存在语法错误(缺少闭合引号),可能导致表单交互异常。

解决方案

1. 修复HTML嵌套表单问题

去掉嵌套的<form id="onceboost">标签,所有表单控件放在同一个主表单内,确保提交时所有字段都能被POST到后端,同时修正语法错误:

<p>Are you boostered?</p>
<label for="once">Once</label> <input value="once" type="radio" id="boostone" name="question1" onclick="displayForm2(this)"><br>
<label for="twice">Twice</label> <input value="twice" type="radio" id="boosttwo" name="question1" onclick="displayForm2(this)"><br>
<label for="noboost">No</label> <input value="noboost" type="radio" id="boostno" name="question1" onclick="displayForm2(this)"><br>
<div style="visibility:hidden; position:relative" id="onceboostContainer">
  <div class="form-group">
    <label class="col-md-5 control-label">Brand of Vaccine</label>
    <div class="col-md-3 selectContainer">
      <div class="input-group">
        <span class="input-group-addon"><i class="glyphicon glyphicon-list"></i></span>
        <select name="boost1brand" id="booster1brand" class="form-control selectpicker">
          <option value="nullvac">Select Brand...</option>
          <!-- 其他选项保留 -->
        </select>
      </div>
    </div>
  </div>
  <div class="form-group">
    <label class="col-md-5 control-label">Date of booster</label>  
    <div class="col-md-2 inputGroupContainer">
      <div class="input-group">
        <span class="input-group-addon"><i class="glyphicon glyphicon-th"></i></span>
        <input name="date1once" id="date1stonce" class="form-control" type="date" required>
      </div>
    </div>
  </div>
  <input type="submit" name="create" value="Register with one booster">
</div>

2. 完善PHP后端字段取值与错误调试

对所有可能未提交的字段进行空值处理,同时添加错误信息输出,方便排查问题:

<?php
if(isset($_POST['create'])) {
    // 主字段取值,确保非空
    $firstname = $_POST['firstname'] ?? '';
    $middlename = $_POST['middlename'] ?? '';
    $lastname = $_POST['lastname'] ?? '';
    $houseno = $_POST['houseno'] ?? '';
    $stsubd = $_POST['stsubd'] ?? '';
    $brgy = $_POST['brgy'] ?? '';
    $citymun = $_POST['citymun'] ?? '';
    $bday = $_POST['bday'] ?? '';
    $celno = $_POST['celno'] ?? '';
    $telno = $_POST['telno'] ?? '';
    $vaccbrand1 = $_POST['vaccbrand1'] ?? '';
    $date1st = $_POST['date1st'] ?? '';
    $vaccbrand2 = $_POST['vaccbrand2'] ?? '';
    $date2nd = $_POST['date2nd'] ?? '';
    $question1 = $_POST['question1'] ?? '';
    
    // Booster相关字段取值,未提交时设为空字符串
    $boost1brand = $_POST['boost1brand'] ?? '';
    $date1once = $_POST['date1once'] ?? '';
    $boost2brand1 = $_POST['boost2brand1'] ?? '';
    $boost2date1 = $_POST['boost2date1'] ?? '';
    $boost2brand2 = $_POST['boost2brand2'] ?? '';
    $boost2date2 = $_POST['boost2date2'] ?? '';

    $sql = "INSERT INTO users (firstname, middlename, lastname, houseno, stsubd, brgy, citymun, bday, celno, telno, vaccbrand1, date1st, vaccbrand2, date2nd, question1, boost1brand, date1once, boost2brand1, boost2date1, boost2brand2, boost2date2) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
    $stminsert = $db->prepare($sql);
    $result = $stminsert->execute([$firstname, $middlename, $lastname, $houseno, $stsubd, $brgy, $citymun, $bday, $celno, $telno, $vaccbrand1, $date1st, $vaccbrand2, $date2nd, $question1, $boost1brand, $date1once, $boost2brand1, $boost2date1, $boost2brand2, $boost2date2]);
    
    if($result) {
        echo "Successfully saved.";
    } else {
        // 输出具体错误信息用于调试
        $errorInfo = $stminsert->errorInfo();
        echo "Error: " . $errorInfo[2];
    }
}
?>

3. 优化数据库表结构(可选)

如果booster字段确实允许为空,建议将这些字段的NOT NULL改为NULL,更符合业务逻辑:

ALTER TABLE users 
MODIFY COLUMN boost1brand varchar(50) NULL,
MODIFY COLUMN date1once varchar(50) NULL,
MODIFY COLUMN boost2brand1 varchar(50) NULL,
MODIFY COLUMN boost2date1 varchar(50) NULL,
MODIFY COLUMN boost2brand2 varchar(50) NULL,
MODIFY COLUMN boost2date2 varchar(50) NULL;

内容的提问来源于stack exchange,提问作者AthensRR18

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 20:05:47