0

次のようなことを行うと、MySQL は常にエラーをスローします。

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

フィールド a と c が「newtable」に存在しない場合。もちろん、これが正当な誤りであることは理解しています。私が知りたいのは、これを処理するための case ステートメントのようなものを構築する方法があるかということです。クエリは動的テーブルに基づいて動的に作成されるため、どのフィールドが存在するかを事前に知る方法はありません。

あなたの賢いアイデアは何ですか?

上記のように、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 に答える