【问题标题】:How can I 'SELECT INTO' with unknown columns?如何使用未知列“选择进入”?
【发布时间】:2011-05-14 04:48:16
【问题描述】:

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

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

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

你有什么精明的想法?

注意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);
}

【问题讨论】:

  • 69% 相当不错,我看不出问题吗?
  • 灰色几乎看不到,绿色更好

标签: sql mysql insert mysql-error-1054


【解决方案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;

【讨论】:

  • 我不认为这对我有用,因为“newtable”是动态创建的。新表的字段名称来自动态(可变)ajax POST 服务。
  • 我更新了我的帖子以包含一个可行的解决方案。谢谢你的想法。我确实认为您的解决方案会起作用,尽管在我的情况下,这只是一种错觉。
猜你喜欢
  • 2015-11-12
  • 2013-06-24
  • 2023-03-12
  • 1970-01-01
  • 2023-04-08
  • 1970-01-01
  • 1970-01-01
  • 2015-10-09
  • 2018-12-18
相关资源
最近更新 更多