使用外键插入PDO失败


PDO insert with foreign key is failing

sqlphppdo非常陌生,我正试图为现有帐户在项目表中执行插入语句,但一直失败。我看不出哪里出了问题。

这是的结构

科目表
id=pk

项目表
id=pk
account_id=fk
项目名称=varchar(100)
pm=varchar(100)
apm=varchar(100)
estrongtart=日期
est_end=日期
contact=varchar(100)
project_status=varchar(100)
comments=文本

所有相关字段都是utf8_unicode_ci排序规则
XAMPP服务器上innodb mySQLdb的限制设置为级联。

php/pdo

<?php
include "$_SERVER[DOCUMENT_ROOT]/core/init.php";
if (empty($_POST) === false) {
    $fk = '';
    $title = $_POST['title'];
    try {
        $query_get_id = $db->prepare("
            SELECT accounts.id
            FROM accounts 
            WHERE accounts.account_name = ?         
        ");
        $query_get_id->bindValue(1, $title, PDO::PARAM_STR);
        $query_get_id->execute();
        $count = $query_get_id->rowCount();
        if ($count > 0) {
            while ($row = $query_get_id->fetch(PDO::FETCH_ASSOC)) {             
                $fk = $row['id'];
            }           
        } 
    } catch(PDOException $e) {
        die($e->getMessage());
    }
    $pn = $_POST['project_name'];
    $ppm = $_POST['project_pm'];
    $papm = $_POST['project_apm'];  
    $pc = $_POST['project_contact'];
    $pes = $_POST['project_est_start'];
    $pee = $_POST['project_est_end'];
    $ps = $_POST['project_status']; 
    $pcom = $_POST['project_comments']; 
    try {
        $query_ip = $db->prepare('INSERT INTO projects (account_id, project_name, pm, apm, est_start, est_end, contact, project_status, comments) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)');
        $query_ip->bindValue(1, $fk, PDO::PARAM_STR);       
        $query_ip->bindValue(2, $pn, PDO::PARAM_STR);
        $query_ip->bindValue(3, $ppm, PDO::PARAM_STR);
        $query_ip->bindValue(4, $papm, PDO::PARAM_STR);
        $query_ip->bindValue(5, $pes, PDO::PARAM_STR);
        $query_ip->bindValue(6, $pee, PDO::PARAM_STR);
        $query_ip->bindValue(7, $pc, PDO::PARAM_STR);
        $query_ip->bindValue(8, $ps, PDO::PARAM_STR);
        $query_ip->bindValue(9, $pcom, PDO::PARAM_STR);         
        $query_ip->execute();
        echo 'Project Created';     
    } catch(PDOException $e) {
        die($e->getMessage());
    }
} else {
    echo 'project creation failed';
}
?>

这并没有带来任何错误,但我有一种感觉,我没有正确设置fk,所以数据库插入失败了。

如果你需要更多的信息,只需询问,即使有所有的代码/信息,我也尽量保持简短和甜蜜。感谢您的帮助。

编辑

我现在在更新我的代码后发现了这个错误

Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (`fsi`.`projects`, CONSTRAINT `projects_ibfk_1` FOREIGN KEY (`id`) REFERENCES `accounts` (`id`) ON DELETE CASCADE ON UPDATE CASCADE)' in C:'xampp'htdocs'include'fill_project.php:50 Stack trace: #0 C:'xampp'htdocs'include'fill_project.php(50): PDOStatement->execute() #1 {main} thrown in C:'xampp'htdocs'include'fill_project.php on line 50

第50行是用代码执行语句的地方

$query_ip->execute();

我太新了,不能完全理解这个错误。我的猜测是,我的第一个怀疑是正确的,我没有正确设置我的fk。我说得对吗?

同样只是一个fyi,我在插入之前回显了我的变量,它们都设置好了,没有一个是空的,如果有人想知道的话。

这并没有向吐出任何错误

这是你的主要问题
而且必须是你最关心的问题
你必须确保,如果发生错误,你将能够看到、阅读和理解它。
如果没有错误消息,你的工作将更像是赌博而不是编程。

一旦你得到了它,你可以修复它,也可以通过谷歌搜索得到更多的解释。错误消息的搜索结果是最相关的。

为了能够看到PDO错误,必须将PDO错误模式设置为异常。异常在很多方面都比常规错误好:它们总是包含堆栈跟踪,可以使用try捕获。。catch或使用专用错误处理程序进行处理。即使未经处理,它们也会作为常规PHP错误提供所有重要信息,遵循站点范围的错误报告设置。

请注意,将此模式设置为连接选项也会让PDO在连接错误时抛出异常,这一点非常重要
因此,这里有一个正确创建PDO连接的示例:

$dsn = "mysql:host=$host;dbname=$db;charset=utf8";
$opt = array(
    PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
    // other options 
);
$pdo = new PDO($dsn, $user, $pass, $opt);

通过这种方式连接,您将始终收到查询执行过程中发生的所有数据库错误的通知。请注意,您必须能够看到PHP的一般错误。在一个实时网站上,你必须查看错误日志,所以,设置必须是

error_reporting(E_ALL);
ini_set('display_errors',0);
ini_set('log_errors',1);

在本地开发服务器上,可以在屏幕上出错:

error_reporting(E_ALL);
ini_set('display_errors',1);

当然,您永远不应该在PDO语句前面使用错误抑制运算符(@)。

此外,由于许多不好的例子告诉您要将每个PDO语句封装到try..catch块中,我必须特别注意:

不要使用try。。catch运算符只是为了回显错误消息Uncaught异常在这方面已经很好了,因为它将以与其他PHP错误相同的方式运行-因此,您可以使用站点范围的设置来定义行为-因此,您将获得没有这些无用代码的错误消息虽然无条件回复的错误消息可能会向潜在的攻击者透露一些敏感信息,但会让诚实的访问者感到困惑

  • 稍后可以添加自定义异常处理程序,但不是必需的。特别是对于新用户,建议使用未处理的异常,因为它们信息丰富、有用且安全
  • 只有当您要处理错误本身时,才使用try..catch,例如回滚事务

这实际上是一个非索引列的情况。您可以看到,我使用的是phpmyadmin,并且没有为"account-id"列编制索引。这是什么意思?这意味着当我将关系设置为"account_id"时,accounts表的"id"字段为fk。实际上,它在我的"projects"表中将其默认为"id",因为这是唯一的索引列。因此,如果你迷路了,这里有一个快速的可视化。

如果您对"phpmyadmin"非常陌生,就像我在要查看的表上单击"structure"一样,然后单击表底部的"relational view"。

你应该看到像这个的东西

Column______Internal relation_______Foreign key constraint (INNODB)
id          <blank dropdown>        <blank drop down>
account_id  <blank dropdown>        no index found!
name        <blank dropdown>        no index found!   

现在,当你想将你的fk设置为另一个表时,你只需下拉中间名为Internalrelation的列,就会看到其他表的pk列表或者我是这么想的!第三列是造成所有差异的原因,如果该列没有索引,则不能将其定义为另一个表的fk。

因此,这样做可以NOT工作。

Column______Internal relation_______Foreign key constraint (INNODB)
id          <blank dropdown>        <blank drop down>
account_id  <db.accounts.id>        no index found!
name        <blank dropdown>        no index found!

你必须首先转到你的表的结构视图,点击你想要的列上的"索引",然后你的屏幕将看起来像这个

Column______Internal relation_______Foreign key constraint (INNODB)
id          <blank dropdown>        <blank drop down>
account_id  <blank dropdown>        <blank drop down>
name        <blank dropdown>        no index found!

然后你可以选择你的fk,它会看起来像这个

Column______Internal relation_______Foreign key constraint (INNODB)
id          <blank dropdown>        <blank drop down>    
account_id  <db.accounts.id>         <`db`.`accounts`.`id`> ON DELETE <CASCADE> ON UPDATE <CASCADE>
name        <blank dropdown>        no index found!

然后你的fk实际上被设置为正确的值。我没有意识到这一点。不管怎样,这就是我解决问题的方法。我希望这对未来的有帮助