Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/233.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 在这个PDO查询中,用一个新列更改我的表有什么错?_Php_Mysql_Sql_Pdo_Alter - Fatal编程技术网

Php 在这个PDO查询中,用一个新列更改我的表有什么错?

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)) {

我正在尝试向一个表中添加一个新列,其中设置日期作为列头,tinyint1作为数据类型

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您是对的,但至少在理论上,有一个正则表达式保护它。这种想法与此有更多的关系,如果他们决定在某个时候删除正则表达式呢?当然,他们还是会有麻烦的,但不会像他们一开始就没有任何东西那样糟糕。