0

MySQL 在执行以下操作时总是抛出错误:

INSERT INTO `newtable` 
(`a`, `b`, `c`, `d`) 
SELECT 
`a`, `b`, `c` , `d` FROM `oldtable`

当“newtable”中不存在字段 a 和 c 时。当然,我理解这是一个合法的错误。我想知道的是,有什么方法可以构建类似案例声明的东西来处理这个问题。该查询是基于动态表动态构建的,因此我无法预先知道存在哪些字段。

你有什么精明的想法?

请注意,newtable 是如上所述动态定义的:

public function updateTableSchema($table, $fields)
{
    // Drop the temporary table if exists
    $sql = "
        DROP TABLE IF EXISTS `temp_{$table}`
    ";
    if (!$this->db()->query($sql)) return FALSE;

    // Make a backup of the original table and select the old values into it
    $sql = "
        CREATE TABLE `temp_{$table}`
        SELECT * FROM `$table`
    ";
    if (!$this->db()->query($sql)) return FALSE;

    // Drop the old table
    if (!$this->db()->query("DROP TABLE `$table`")) return FALSE;

    // Recreate the table with the new fields
    $sql = "
        CREATE TABLE IF NOT EXISTS `$table`
        (\n";

        $sql .= "`id` int(11) NOT NULL AUTO_INCREMENT,\n";
        foreach ($fields as $field)
        {
            $sql .= html_entity_decode("`$field` varchar(255) NOT NULL,\n");
        }
        $sql .= "PRIMARY KEY (`id`)\n";

     $sql .= "
        ) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1
    ";
    if (!$this->db()->query($sql)) return FALSE;

    CREATE TABLE new_tbl SELECT * FROM orig_tbl;

    // Insert the temporary records into the new table
    $sql = "INSERT INTO `$table` (";
    foreach ($fields as $field)
    {
        $sql .= html_entity_decode("`$field`, ");
    }
    $sql = rtrim($sql, ', ') . ') SELECT ';
    foreach ($fields as $field)
    {
        $sql .= html_entity_decode("`$field`, ");
    }
    $sql = rtrim($sql, ', ') . " FROM `temp_{$table}`"; 
    print $sql;
    if (!$this->db()->query($sql)) return FALSE;

    // Drop the temporary table
    $sql = "DROP TABLE `temp_{$table}`";
    return $this->db()->query($sql);
}

此处的原始表是根据给定表单上存在的表单字段更新的,这些表单字段可以随时添加、删除或重命名。新表也需要按照这些变化进行。

更新: 工作解决方案如下:

public function updateTableSchema($table, $fields)
{
    // Drop the temporary table if exists
    $sql = "
        DROP TABLE IF EXISTS `temp_{$table}`
    ";
    if (!$this->db()->query($sql)) return FALSE;

    // Make a backup of the original table and select the old values into it
    $sql = "
        CREATE TABLE `temp_{$table}`
        SELECT * FROM `$table`
    ";
    if (!$this->db()->query($sql)) return FALSE;

    // Drop the old table
    if (!$this->db()->query("DROP TABLE `$table`")) return FALSE;

    // Recreate the table with the new fields
    $sql = "
        CREATE TABLE IF NOT EXISTS `$table`
        (\n";

        $sql .= "`id` int(11) NOT NULL AUTO_INCREMENT,\n";
        foreach ($fields as $field)
        {
            $sql .= html_entity_decode("`$field` varchar(255) NOT NULL,\n");
        }
        $sql .= "PRIMARY KEY (`id`)\n";

     $sql .= "
        ) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1
    ";
    if (!$this->db()->query($sql)) return FALSE;

    // Insert the temporary records into the new table
    $sql = "INSERT INTO `$table` (";
    foreach ($fields as $field)
    {
        $sql .= html_entity_decode("`$field`, ");
    }
    $sql = rtrim($sql, ', ') . ') SELECT ';
    foreach ($fields as $field)
    {
        $sql .= html_entity_decode("`$field`, ");
    }
    $sql = rtrim($sql, ', ') . " FROM `temp_{$table}`";

    try
    {
        $this->db()->query($sql);
    }
    catch (error $e)
    {
        if (preg_match('/Unknown column/', $e->getMessage()))
        {
            $new_field = utility::getStringBetween($e->getMessage(), "'", "'");
            if (!$new_field) return FALSE;

            $this->db()->query("TRUNCATE TABLE `$table`");
            $key = array_search($new_field, $fields);
            $key--;

            // Check if adding after
            if ($key > 0)
            {
                $sql = "
                    ALTER TABLE `temp_{$table}`
                    ADD `$new_field` VARCHAR( 255 ) NOT NULL AFTER `{$fields[$key]}` 
                ";
                if (!$this->db()->query($sql)) return FALSE;
            }
            // Check if adding before
            else
            {
                $sql = "
                    ALTER TABLE `temp_{$table}`
                    ADD `$new_field` VARCHAR( 255 ) NOT NULL FIRST
                ";
                if (!$this->db()->query($sql)) return FALSE;
            }

            // Insert the temporary records into the new table
            $sql = "INSERT INTO `$table` (";
            foreach ($fields as $field)
            {
                $sql .= html_entity_decode("`$field`, ");
            }
            $sql = rtrim($sql, ', ') . ') SELECT ';
            foreach ($fields as $field)
            {
                $sql .= html_entity_decode("`$field`, ");
            }
            $sql = rtrim($sql, ', ') . " FROM `temp_{$table}`";
            if (!$this->db()->query($sql)) return FALSE;
        }
    }

    // Drop the temporary table
    $sql = "DROP TABLE `temp_{$table}`";
    return $this->db()->query($sql);
}
4

1 回答 1

1

使用创建表...选择这里是一些参考

http://dev.mysql.com/doc/refman/5.0/en/create-table-select.html

http://dev.mysql.com/doc/refman/5.0/en/create-table.html

CREATE TABLE new_tbl SELECT * FROM orig_tbl;
于 2010-11-23T01:08:30.173 回答