【问题标题】:Why can I initialize this column with a NULL value, but I can't update it as such?为什么我可以用 NULL 值初始化此列,但我不能这样更新它?
【发布时间】:2015-11-10 15:58:32
【问题描述】:

情况:

我有 2 个表,用

创建
$wpdb->query("
CREATE TABLE projs 
    (
    id MEDIUMINT NOT NULL AUTO_INCREMENT PRIMARY KEY, 
    compname VARCHAR (200), 
    projname VARCHAR (200), 
    imageurl VARCHAR(300), 
    sumsmall VARCHAR (250), 
    sumfull VARCHAR (5000), 
    results VARCHAR (5000), 
    postdate DATETIME DEFAULT CURRENT_TIMESTAMP, 
    caseid MEDIUM INT, 
    FOREIGN KEY (caseid) 
        REFERENCES cases(id) ON DELETE SET NULL
    ) $charset_collate
");

$wpdb->query("
CREATE TABLE cases 
    (
    id MEDIUMINT NOT NULL AUTO_INCREMENT PRIMARY KEY, 
    compname VARCHAR (200), 
    casename VARCHAR (200), 
    imageurl VARCHAR(300), 
    summary VARCHAR (5000), 
    results VARCHAR (5000), 
    postdate DATETIME DEFAULT CURRENT_TIMESTAMP
    ) $charset_collate
");

它们之间的关系是每个项目(projs 表中的一行)可以有一个关联的案例研究(cases 表中的一行);因此,

caseid MEDIUM INT, FOREIGN KEY (caseid) REFERENCES cases(id) ON DELETE SET NULL

cases表的初始化中。

我有一个 PHP 函数来处理从我创建的管理面板发出的 AJAX 调用。用于添加、更新或删除项目。

add_action( 'wp_ajax_proj_update', 'proj_update' );

function proj_update ( )
{
    $id = $_POST['id'];
    $compname = $_POST['compname'];
    $projname = $_POST['projname'];
    $imageurl = $_POST['imageurl'];
    $sumsmall = $_POST['sumsmall'];
    $sumfull = $_POST['sumfull'];
    $results = $_POST['results'];
    $caseid = (!isset($_POST['caseid']) || strcmp($_POST['caseid'],'none')) ? $_POST['caseid'] : "null";

    $thisAction = $_POST['thisAction'];

    $message = "";

    switch ($thisAction)
    {
        case 'add':
        {
            global $wpdb;
            $message .= $wpdb->query("INSERT INTO projs (compname,projname,imageurl,sumsmall,sumfull,results,caseid) VALUES (" . implode(",", array("'$compname'", "'$projname'", "'$imageurl'", "'$sumsmall'", "'$sumfull'", "'$results'", "$caseid")) . ")") 
                        ? 'Successfully added project ' . $projname . ' to the database.'
                        : 'Error occurred when trying to add project to database: ' . $wpdb->last_error;
            break;
        }
        case 'delete':
        {
            global $wpdb; 
            $message .= $wpdb->query("DELETE FROM projs WHERE id=" . $id)
                      ? 'Successfully deleted project from the database.'
                      : 'Error occurred when trying to delete project from database: ' . $wpdb->last_error;
            break;
        }
        case 'update':
        {
            global $wpdb;
            $message .= $wpdb->query("UPDATE projs SET compname='$compname',projname='$projname',imageurl='$imageurl',sumsmall='$sumsmall',sumfull='$sumfull',results='$results',caseid='$caseid' WHERE id=$id")
                        ? 'Successfully updated project.'
                        : 'Error occurred when trying to update project in database: ' . $wpdb->last_error;
            break;
        }
        default:
        {
            $message .= 'Didn\'t recognize action.'; 
            break;
        }
    }
    die($message);    
}

我已经测试了函数的add 部分并且没有遇到任何故障,但是每当我尝试将updatecaseid 设置为null 时都会遇到错误。当我尝试这样做时,上面的脚本生成的错误语句是

尝试更新数据库中的项目时发生错误: 无法添加或更新子行:外键约束失败 ('my_database_name'.'projs',CONSTRAINT 'projs_ibfk_1' 外键 ('caseid') REFERENCES 'cases' ('id') ON DELETE SET NULL

问题:

知道我在这里做错了什么吗?

【问题讨论】:

  • null 回到 PK null 不起作用,因为父表中的 PK 不能为 null ?那种东西?还是“null”不存在?
  • null is not 'null' ... null is not "null".... 实际上,nullnull,但 null 为 null,如 select null is null; 中产生 1
  • @MediocreWebDev 应该害怕这段代码......你永远不应该使用字符串连接或变量插值来制作查询。采用。准备好了。声明。没有任何借口。您的代码中存在安全漏洞,利用这些漏洞非常容易。例如,将一行的“compname”设置为 pwn3d' -- 的更新几乎肯定会将它们中的 all 设置为相同的值,“pwn3d”...

标签: php mysql sql ajax database-design


【解决方案1】:

你正在做:

INSERT ... VALUES (..., "$caseid")

这意味着您的查询实际上正在运行

INSERT ... VALUES (..., "null")

这不是 SQL 空值。这是一个包含字符n、`u 等的字符串...

如果你想插入一个实际的 SQL 空值,你必须在别处引用值:

$caseid = (isset stuff) ? "'" . $_POST['caseid'] . "'" : "null";
                          ^^^^^------------------^^^^^-- add quotes here

$message .= $wpdb->query([..snip..], $caseid)) . ")") 
                                    ^-------^---no quotes here

【讨论】:

  • 您需要转义 $_POST 值——以处理引号并避免 SQL 注入。
【解决方案2】:

您的查询中的问题是您将字符串“null”分配给项目的caseid

你应该这样做:

$caseid = (!isset($_POST['caseid']) || strcmp($_POST['caseid'],'none')) ? "'" . $_POST['caseid'] . "'" : "null";

然后,在您的查询中:

case 'update':
        {
            global $wpdb;
            $message .= $wpdb->query("UPDATE projs SET compname='$compname',projname='$projname',imageurl='$imageurl',sumsmall='$sumsmall',sumfull='$sumfull',results='$results',caseid=$caseid WHERE id=$id")
                        ? 'Successfully updated project.'
                        : 'Error occurred when trying to update project in database: ' . $wpdb->last_error;
            break;
        }

注意caseid 不再用单引号括起来,因为我在定义它时添加了这些单引号。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-02-09
    • 1970-01-01
    • 1970-01-01
    • 2022-06-10
    • 1970-01-01
    • 1970-01-01
    • 2012-05-17
    • 2016-05-16
    相关资源
    最近更新 更多