使用空变量复制mysql行

时间:2014-04-23 20:44:56

标签: php mysql sql

我有一张包含很多列的表格。我有一个函数将我的记录复制到一个新行,并带有更新的自动递增ID。

该函数完美地工作,但是在我的一些INT列上,有时我将NULL作为默认值。当记录重复时,它会将我的NULL位置转换为0。

我假设它是因为我正在做'" . value . "'

有没有人可以帮我弄清楚如何将NULL值插入" . NULL . "并将其他值保持为'" . value . "'

编辑我在区分空值和空值时遇到问题。我尝试过empty()和is_null()以及没有值的varchar和一个带有NULL值的INT并不显示差异

注意我知道我使用的是过时的mysql扩展程序。目前,我只是想正确处理我的空变量。

function duplicateRow($table, $id_field, $id_value)
{
    // copy content of the record you wish to clone 
    $entity = mysql_fetch_array(mysql_query("SELECT * FROM {$table} WHERE {$id_field}={$id_value}"), MYSQL_ASSOC) or die("Could not select original record"); 

    // set the auto-incremented id's value to blank. If you forget this step, nothing will work because we can't have two records with the same id 
    $entity[$id_field] = ""; 

    // insert cloned copy of the original record 
    mysql_query("INSERT INTO {$table} (".implode(", ",array_keys($entity)).") VALUES ('".implode("', '",array_values($entity))."')") or die(mysql_error()); 

    //returns the new id
    return mysql_insert_id(); 
}

3 个答案:

答案 0 :(得分:1)

您不需要将数据提取到PHP中然后再将其发送回MySQL:INSERT ... SELECT是一个单独的SQL命令,可以使整个shebang本地发生在数据库中。

但是,您需要从操作中排除$id_field,因此您无法使用*通配符,但必须明确列出列名称。这增加了一些复杂性,特别是以安全,防注射的方式执行操作:

function duplicateRow($table, $id_field, $id_value)
{
    // prevent SQL injection
    $enc_map = array(
      'utf8'   => 'UTF-8',
      'latin1' => 'Windows-1252' // etc.
    );
    mb_regex_encoding($enc_map[mysql_client_encoding()]);
    $table_safe    = '`'.mb_ereg_replace('`', '``', $table   ).'`';
    $id_field_safe = '`'.mb_ereg_replace('`', '``', $id_field).'`';
    $id_value_safe = mysql_real_escape_string($id_value);

    // fetch column names
    $fields = array();
    $qry = mysql_query("SHOW COLUMNS FROM $table_safe");
    while ($row = mysql_fetch_assoc($qry))
      if ($row['field'] != $id_field)
        $fields[] = '`'.mb_ereg_replace('`', '``', $row['field']).'`';

    $fields_safe = implode(',', $fields);

    // duplicate the record
    mysql_query("
      INSERT INTO $table_safe
        ($fields_safe)
      SELECT $fields_safe
      FROM   $table_safe
      WHERE  $id_field_safe = '$id_value_safe'
    ");

    //returns the new id
    return mysql_insert_id(); 
}

请注意,古老的ext / mysql扩展已被弃用,并且多年来一直不鼓励在新代码中使用它。您应该认真考虑切换到MySQLiPDO

答案 1 :(得分:0)

你的MySQL版本是什么?某些版本的MySQL(5.5及更早版本,如果我没有记错的话)将空值转换为空字符串字段和0转换为int字段。

您必须强制空值或更新到MySQL 5.6

答案 2 :(得分:0)

我最后制作了一个foreach语句,检查我的值是否为null并稍微更改了查询。这可能不是最好的,正确的或实用的方法,但它有效。如果有人有任何建议,他们将100%赞赏!

我保持我的功能大致相同的原因是我需要将它用于多个大表。所以我不确切知道这些领域是什么。

function duplicateRow($table, $id_field, $id_value)
{
    // copy content of the record you wish to clone 
    $entity = mysql_fetch_array(mysql_query("SELECT * FROM {$table} WHERE {$id_field}={$id_value} AND snapshot=0"), MYSQL_ASSOC) or die("Could not select original record"); 

    foreach ($entity as &$value) { if(is_null($value) == true) { $value = "NULL"; } else { $value = "'$value'"; } }

    // set the auto-incremented id's value to blank. If you forget this step, nothing will work because we can't have two records with the same id 
    $entity[$id_field] = "'"; 

    // insert cloned copy of the original record 
    $query = "INSERT INTO {$table} (".implode(", ",array_keys($entity)).") VALUES ('".implode(", ",array_values($entity)).")";
    mysql_query($query) or die(mysql_error());

    //returns the new id
    return mysql_insert_id(); 
}