Php 在这个PDO查询中,用一个新列更改我的表有什么错?
我正在尝试向一个表中添加一个新列,其中设置日期作为列头,tinyint1作为数据类型Php 在这个PDO查询中,用一个新列更改我的表有什么错?,php,mysql,sql,pdo,alter,Php,Mysql,Sql,Pdo,Alter,我正在尝试向一个表中添加一个新列,其中设置日期作为列头,tinyint1作为数据类型 function addAttendance($date) { include('connection.php'); $column_name = strtolower($date); if(!preg_match('/[^A-Za-z0-9.#\\-$]/', $column_name)){ if(!empty($column_name)) {
function addAttendance($date) {
include('connection.php');
$column_name = strtolower($date);
if(!preg_match('/[^A-Za-z0-9.#\\-$]/', $column_name)){
if(!empty($column_name)) {
$st = $db->prepare("DESCRIBE attendance");
$st->execute();
$st = $st->fetchAll(PDO::FETCH_COLUMN);
$compare = $st;
foreach($compare as $key) {
if($key === $column_name) {
die('Project name already exists. Please select a different name.');
}
}
$st = $db->prepare("ALTER TABLE attendance ADD $column_name BOOLEAN");
$st->execute();
} else { die('Project name is empty.');}
} else { die('Project name can only contain letters and numbers.');}
}
PDO::prepare真的不应该这样使用。它的意思是作为准备执行语句的一种方式。更深入地解释。你在找我。以下可能是最重要的摘录: 对于那些想知道为什么在占位符周围添加引号是错误的,以及为什么不能在表或列名中使用占位符的人: 对于预处理语句中的占位符是如何工作的,存在一个常见的误解:它们不是简单地作为转义字符串替换,而是执行结果SQL。相反,要求DBMS准备语句的DBMS会给出一个完整的查询计划,说明它将如何执行该查询,包括它将使用哪些表和索引,无论您如何填写占位符,这些表和索引都是相同的 从my_表中选择名称(其中id=:value)的计划将与替换:value的内容相同,但无法计划看似相似的从:表中选择名称(其中id=:value),因为DBMS不知道实际要从哪个表中选择
应该注意的是,虽然列名只包含字母和数字(当前由preg_匹配强制执行)是安全的,但最好的做法是仍然引用输入,例如使用PDO::quote。我还建议您研究一下,因为正则表达式可能不是最准确的。您还没有描述此代码中不起作用的内容,但我猜$date包含当前日期的一些格式,如“2014-05-28”。正则表达式筛选将允许使用该字符串。然后将其用作列名:
$column_name = strtolower($date);
mysql> ALTER TABLE attendance ADD COLUMN `2014-05-28` BOOLEAN;
Query OK, 0 rows affected (0.11 sec)
当您添加列时,会生成一个算术表达式作为列名,这将导致错误:
mysql> ALTER TABLE attendance ADD COLUMN 2014-05-28 BOOLEAN;
ERROR 1064 (42000): You have an error in your SQL syntax;
check the manual that corresponds to your MySQL server version for the right syntax to use
near '2014-05-28 BOOLEAN' at line 1
如果将列名分隔为后面的记号,则实际上可以将其用作列名:
$column_name = strtolower($date);
mysql> ALTER TABLE attendance ADD COLUMN `2014-05-28` BOOLEAN;
Query OK, 0 rows affected (0.11 sec)
然而,仅仅因为SQL允许这样奇怪的列名,并不意味着这是一个好主意。使用那个专栏充其量也不方便,你可能应该重新考虑这个想法
代码的另一个错误是没有检查prepare或execute中的错误。您可能启用了PDO在出错时抛出异常,但我假设您没有。这意味着,如果prepare和execute发现错误,您应该期望它们返回false
当然,如果$st没有该方法,调用$st->execute是一个致命错误
因此,您应该检查错误:
if (($st = $db->prepare("ALTER TABLE attendance ADD $column_name BOOLEAN")) === false) {
die(print_r($db->errorInfo(), true));
}
if ($st->execute() === false) {
die(print_r($st->errorInfo(), true));
}
PDO::quote不会对列标识符进行正确的引用。@BillKarwin您是对的,但至少在理论上,有一个正则表达式保护它。这种想法与此有更多的关系,如果他们决定在某个时候删除正则表达式呢?当然,他们还是会有麻烦的,但不会像他们一开始就没有任何东西那样糟糕。