父 - 事务下 PHP PDO SQLite 中的子表 - 没有错误,但它不起作用

Posted

技术标签:

【中文标题】父 - 事务下 PHP PDO SQLite 中的子表 - 没有错误,但它不起作用【英文标题】:Parent - child table in PHP PDO SQLite under transaction - No error but it doesn't work 【发布时间】:2022-01-22 03:30:48 【问题描述】:

早上好, 我在下面编写了代码,它在事务下使用 PDO 和 SQLite 在 php 上运行。 莫名其妙地它没有出错,但它甚至没有写第二个表,结果记录的所有字段都为空。 你能告诉我我做错了什么,因为我在 Apache2 日志中找不到任何错误吗? 非常感谢。

我在 SQLite 中创建了两个表:

第一个包含问题数据; 第二个包含每个问题的详细信息

创建数据库的我的 SQL 脚本:

CREATE TABLE "questionari" (
  "pkid_questionario"   INTEGER NOT NULL,
  "dt_registrazione"    TEXT NOT NULL,
  "matricola"   INTEGER NOT NULL,
  "cognome" TEXT NOT NULL,
  "nome"    TEXT NOT NULL,
  "email"   TEXT NOT NULL,
  "pk_localizzazione"   INTEGER NOT NULL,
  "desc_localizzazione" TEXT NOT NULL,
  PRIMARY KEY("pkid_questionario" AUTOINCREMENT)
);

CREATE TABLE "t1" (
  "idQuestionario"  INTEGER,
  "pkidBene"    INTEGER,
  "NumeroEtichetta" INTEGER,
  "DescBene"    TEXT,
  "EsistenzaBene"   TEXT,
  "EsistenzaEtichetta"  TEXT DEFAULT null,
  "txtNote" TEXT DEFAULT null,
  FOREIGN KEY("idQuestionario") REFERENCES "questionari"("pkid_questionario") 
    ON UPDATE CASCADE 
    ON DELETE CASCADE,
  PRIMARY KEY("pkidBene","idQuestionario")
);

我的 PHP 代码是这样的:

define("T1_PkID","t1_PkID_r");
define("T1_Etichetta", "t1_Etichetta_r");
define("T1_Desc", "t1_Desc_r");
define("T1_Bene_YN", "t1_Bene_YN_r");
define("T1_Etichetta_YN", "t1_Etichetta_YN_r");
define("T1_Note", "t1_Note_r");

//[Omissis...]
try
$db = new SQLiteDB();
//$dbh = new PDO("sqlite:./DB/DB_Inventario.db");
$dbh = $db->connect();
  
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$dbh->beginTransaction();
            
$sql  = "INSERT INTO questionari ";
$sql .= "(dt_registrazione, matricola, cognome, nome, email, pk_localizzazione, desc_localizzazione) VALUES ";
$sql .= "(:dt_registrazione, :matricola, :cognome, :nome, :email, :pk_localizzazione, :desc_localizzazione)";
            
$stmt = $dbh->prepare($sql);
$dt_registrazione = date('Y/m/d H:i:s');
            
$stmt->bindParam(":dt_registrazione", $dt_registrazione);
$stmt->bindParam(":matricola", $matricola);
$stmt->bindParam(":cognome", $cognome);
$stmt->bindParam(":nome", $nome);
$stmt->bindParam(":email", $email);
$stmt->bindParam(":pk_localizzazione", $pkLocalizzazione);
$stmt->bindParam(":desc_localizzazione", $DescLocalizzazione);

$stmt->execute();
                
$lastID = $dbh->lastInsertId();

// t1_NumRows is the rows number to write for t1            
for($i=0;$i<$t1_NumRows;$i++)
  $sql  = "INSERT INTO t1 ";
  $sql .= "(idQuestionario, pkidBene, NumeroEtichetta, DescBene, EsistenzaBene, EsistenzaEtichetta, txtNote) VALUES ";
  $sql .= "(:p_idQuestionario, :p_pkidBene, :p_NumeroEtichetta, :p_DescBene, :p_EsistenzaBene, :p_EsistenzaEtichetta, :p_txtNote)";

  $stmt->bindParam(":p_idQuestionario", $lastID, PDO::PARAM_INT);
  $stmt->bindParam(":p_pkidBene", $_POST[T1_PkID.$i], PDO::PARAM_INT);
  $stmt->bindParam(":p_NumeroEtichetta", $_POST[T1_Etichetta.$i], PDO::PARAM_INT);
  $stmt->bindParam(":p_DescBene", $_POST[T1_Desc.$i], PDO::PARAM_STR, 500);
  $stmt->bindParam(":p_EsistenzaBene", $_POST[T1_Bene_YN.$i], PDO::PARAM_STR, 2);
                
  if($_POST[T1_Bene_YN . $i]=="NO")
    $stmt->bindParam(":p_EsistenzaEtichetta", null, PDO::PARAM_STR, 2);
  else
    $stmt->bindParam(":p_EsistenzaEtichetta", $_POST[T1_Etichetta_YN.$i], PDO::PARAM_STR,   2);

if(strlen(trim($_POST[T1_Note.$i]))==0)
  $stmt->bindParam(":p_txtNote", null, PDO::PARAM_STR, 500);
else
  $stmt->bindParam(":p_txtNote", $_POST[T1_Note.$i], PDO::PARAM_STR, 500);
                
$stmt = $dbh->prepare($sql);
$stmt->execute();

//[Omissis...]
$dbh->commit();  

// In case of exception make rollback!

这是记录第一个问题后“t1”上的结果,有两个细节:

【问题讨论】:

我没有看到 $t1_NumRows 定义,所以它永远不会进入循环 $ t1_NumRows 是一个由加载的表单设置的值 $ _POST [] 表示要发布的行数。在我的测试用例中是 2。 尝试一些故障排除。在此过程中添加一些回显或记录行,例如在 for 循环内部。检查循环内的PDO errors 以确保查询没有失败。 【参考方案1】:

好的,我在代码中进行了一些调试,发现必须在参数查询的定义之后立即插入准备语句。 此时我的代码有效:D:D

for($i=0;$i<$t1_NumRows;$i++)
  $sql  = "INSERT INTO t1 ";
  $sql .= "(idQuestionario, pkidBene, NumeroEtichetta, DescBene, EsistenzaBene, EsistenzaEtichetta, txtNote) VALUES ";
  $sql .= "(:p_idQuestionario, :p_pkidBene, :p_NumeroEtichetta, :p_DescBene, :p_EsistenzaBene, :p_EsistenzaEtichetta, :p_txtNote)";
  
  $stmt = $dbh->prepare($sql);

  $stmt->bindParam(":p_idQuestionario", $lastID, PDO::PARAM_INT);
  $stmt->bindParam(":p_pkidBene", $_POST[T1_PkID.$i], PDO::PARAM_INT);
  $stmt->bindParam(":p_NumeroEtichetta", $_POST[T1_Etichetta.$i], PDO::PARAM_INT);
  $stmt->bindParam(":p_DescBene", $_POST[T1_Desc.$i], PDO::PARAM_STR, 500);
  $stmt->bindParam(":p_EsistenzaBene", $_POST[T1_Bene_YN.$i], PDO::PARAM_STR, 2);
                
  if($_POST[T1_Bene_YN . $i]=="NO")
    $stmt->bindValue(":p_EsistenzaEtichetta", null, PDO::PARAM_STR, 2);
  else
    $stmt->bindParam(":p_EsistenzaEtichetta", $_POST[T1_Etichetta_YN.$i], PDO::PARAM_STR,   2);

if(strlen(trim($_POST[T1_Note.$i]))==0)
  $stmt->bindValue(":p_txtNote", null, PDO::PARAM_STR, 500);
else
  $stmt->bindParam(":p_txtNote", $_POST[T1_Note.$i], PDO::PARAM_STR, 500);
                
$stmt->execute();

【讨论】:

以上是关于父 - 事务下 PHP PDO SQLite 中的子表 - 没有错误,但它不起作用的主要内容,如果未能解决你的问题,请参考以下文章

PHP中的PDO操作学习预处理语句及事务

PHP17 PDO

在 PHP 中设置 SQLite3 PDO 驱动程序

PDO / PHP / MySQL 中的性能:事务与直接执行

PHP PDO 事务自动回滚

PDO中的事务处理