我正在将文本文件解析为使用php处理文件数据的空sqlite数据库。我使用以下命令建立数据库连接:
try {
$db = new PDO('sqlite:temp.db');
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch(PDOException $e) {
echo 'Connection failed: ' . $e->getMessage();
die($error);
}
由于用户文件数据很大,没有排序,并且有多个内部外键依赖项,因此我在外键上使用deferable INITIALLY DEFERRED将数据作为单个事务插入。只要我的原始输入数据是正确的,这就可以很好地工作。当发生用户输入错误时,我将获得整个事务的单一通用异常(当然,随后会回滚)。用户错误通常(但不完全)表现为未定义的外键引用。
有没有人建议一种获取更多信息的方法,例如,在事务中导致异常的单个插入语句,或者丢失的特定外键,这将有助于跟踪用户输入错误?
由于用户输入数据没有顺序,并且该数据的结构很复杂,因此在提交之前验证它将非常复杂,如果可能的话,我希望避免手动编写该方面的代码。
// $queries is a query by query array of your insert data
// we'll assume any sub-arrays are initialized appropriately on demand
$primary_keys = array();
$foreign_keys = array();
foreach ($queries as $idx => $data) {
// build your query appropriately
// if this is an insert to a table with a primary key
// that will be referenced by a foreign key:
$primary_keys[$table_inserting_to][$idx] = $data['primary_key']; // the primary key value we're inserting
// elseif this is an insert to a table with a foreign key
// that references a primary key that could fail:
$foreign_keys[$table_inserting_to][$idx] = $data['foreign_key']; // the foreign key value we're inserting
// run your query
}
// commit your transaction
// whoops, we failed
// build the associations we need to check
$links = array('table_with_foreign_key' => 'table_with_primary_key', 'table_with_foreign_key_2' => 'table_with_primary_key_2');
$errors = array();
foreach ($links as $foreign => $primary) {
$failed_keys = array_diff($foreign_keys[$foreign], $primary_keys[$primary]);
foreach ($failed_keys as $key) {
$errors[] = "Foreign key check $foreign to $primary, $key could not be found on query idx ".array_search($key, $foreign_keys[$foreign]);
}
}
…如果您需要考虑数据库中已经存在的主键,您总是可以查询它们以初始化$primary_keys
数组。
这个答案是基于您正在使用准备好的语句的假设
如果不是这样,你应该做必要的调整。
。收集数组
中的参数$params = array(':name' => 'foo', ':cat' => 'bar', ':val' => 'baz', [...]);
B。在调用execute($params)
之前,执行以下操作,在文件中注册您正在使用的参数:
file_put_contents('file.log', implode(';', $params) . "'r'n"); //or "'n" on linux, "'r" on mac
C。call execute($params)
D。如果查询成功,则GOTO A,否则,死亡。
使用这个简单的算法,您将有一个日志文件(名为file.log
),其中包含已成功插入的所有参数以及错误的参数(在最后一行)。
可能的改进:
这个算法效率不高,因为你打开和关闭文件多次。如果您关心效率,请遵循以下说明:
X。定义$log = array();
。收集数组
中的参数$params = array(':name' => 'foo', ':cat' => 'bar', ':val' => 'baz', [...]);
B。在调用execute($params)
之前,执行以下操作来存储您正在使用的参数:
$log[] = implode(';', $params) . "'r'n"; //or "'n" on linux, "'r" on mac
C。call execute($params)
D。如果查询成功,则GOTO A,否则,file_put_contents('file.log', implode("'r'n", $log));
.
将上述建议与错误引发的PDO异常结合起来。它的堆栈对于调试总是非常有用的。
要使用pdo启用例外,请在连接后使用此命令:
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);