【问题标题】:PHP/MYSQL - Inserting multiple rows using mysql_insert_id?PHP/MYSQL - 使用 mysql_insert_id 插入多行?
【发布时间】:2011-09-08 22:20:34
【问题描述】:

背景:

我正在将客户的基本信息从客户表单上传到数据库。当客户点击“完成”时,输入的信息,例如 (NameCityCountry 等) 将存储在 client_info 表。

作为替代方案,客户端也可以将图像上传到服务器。然后将这些图像的信息(image_pathimage_name)存储在另一个名为 client_images 的单独表中,该表具有 外键client_info 相关联。

client_info 表:

CREATE TABLE IF NOT EXISTS `client_info` (
  `client_id` int(11) NOT NULL AUTO_INCREMENT,
  `client_name` varchar(100) NOT NULL,
  `client_city` varchar(100) NOT NULL,
  `client_country` varchar(10) NOT NULL,
  PRIMARY KEY (`client_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=10446 ;

client_images 表:

CREATE TABLE IF NOT EXISTS `client_images` (
  `image_id` int(11) NOT NULL AUTO_INCREMENT,
  `image_path` varchar(100) NOT NULL,
  `image_name` varchar(100) NOT NULL,
  `client_id` int(11) NOT NULL,
  PRIMARY KEY (`image_id`),
  KEY `client_id` (`client_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=415;

问题:

我已成功将一行上传到 client_images 表。添加多于一行会导致以下错误

Cannot add or update a child row: a foreign key constraint fails (`db`.`client_images`, CONSTRAINT `client_images_ibfk_1` FOREIGN KEY (`client_id`) REFERENCES `client_info` (`client_id`) ON DELETE CASCADE ON UPDATE CASCADE) : 1452

但是,当我通过控制台添加多行和已经存在的 client_id 对其进行测试时,它运行良好。

例子:

mysql> INSERT INTO client_images (image_path, image_name, client_id) VALUES ('pathname1', 'name1', 10241);
Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO client_images (image_path, image_name, client_id) VALUES ('pathname2', 'name2', 10241);
Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO client_images (image_path, image_name, client_id) VALUES ('pathname3', 'name3', 10241);
Query OK, 1 row affected (0.00 sec)

我需要指出,我是这样排列的:

文件:(create_article.php)

insert_client_info($client_name, $client_city, $client_country);    

include('uploads.php');

?>

<?php mysql_close($connection); ?>

uploads.php 内我有一个 foreach 循环,用于计算要上传的文件数量,在循环结束时我目前有一个函数 insert_images($image_path, $image_name);

功能(插入图像):

function insert_images($directory_path, $image_name) {  

    global $connection;
    $client_id=mysql_insert_id();

    $query = "INSERT INTO client_images (
        image_path, image_name, client_id
    ) VALUES (
        '{$directory_path}', '{$image_name}', '{$client_id}'
    )";
$result = mysql_query($query, $connection);

if ($result) {
    // Success!
    echo "<p></p>";
    echo "Successfully uploaded the file.";
    echo "<p></p>";

} else {
    // Display error message.
    echo "<p>" . mysql_error() ." : ".mysql_errno(). "</p>";
}
return $result;
}

阅读其他类似问题我知道致命弱点可能是 mysql_insert_id() 并且不知何故它使用了与 foreach 循环中的第一个不同的另一个连接,因此导致得到前面提到的 MYSQL 错误。

谢谢 / EDZ

【问题讨论】:

    标签: php mysql


    【解决方案1】:

    这部分:

    $query = "INSERT INTO client_images (
            image_path, image_name, client_id
        ) VALUES (
            '{$directory_path}', '{$image_name}', '{$client_id}'
        )";
    

    应该是:

    $query = "INSERT INTO client_images (
            image_path, image_name, client_id
        ) VALUES (
            '$directory_path', '$image_name', $client_id
        )";
    

    您必须使用mysql_real_escape_string() 转义变量以防止sql injection

    $client_id 也是数字,所以不需要引用 '$client_id'

    【讨论】:

    • 是的,我知道这一点,这只是一个例子。不过还是谢谢。
    【解决方案2】:

    添加多于一行会导致以下错误:

    最后一个插入 id 是由当前 MySQL 会话中最近的 INSERT 生成的,它生成了一个自动递增的 id。

    当您插入第一个图像时,最新的 INSERT 是用于 client_info 的那个。

    但是一旦到了第二张图片,最新的INSERT就是第一张图片的,所以mysql_insert_id()返回的值是不同的。同样,每个后续 INSERT 都会更改 mysql_insert_id() 返回的值。

    您应该在foreach 循环开始插入图像之前设置变量$client_id,然后将该变量传递给对insert_images() 的每次调用。在 uploads.php 中:

    $client_id=mysql_insert_id();
    foreach (...) {
        insert_images($client_id, ...);
    }
    

    将 $client_id 作为 insert_images() 函数的参数传递,而不是在函数中设置 $client_id。

    function insert_images($client_id, $directory_path, $image_name) {  
        ...
    }
    

    P.S.:@tttony 提醒您注意 SQL 注入时,他的观点很好。

    另请参阅我的演示文稿SQL Injection Myths and Fallacies,或我的书中关于 SQL 注入的章节SQL Antipatterns: Avoiding the Pitfalls of Database Programming

    【讨论】:

      猜你喜欢
      • 2014-02-25
      • 2012-01-04
      • 2010-12-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多