从一个MariaDB数据库到另一个数据库的克隆表,包括默认值,索引和触发器?

时间:2017-03-05 23:23:58

标签: mysql sql database mariadb

我想将一个表(包括其索引和触发器)从一个数据库复制到另一个数据库。这并不像我希望的那么简单。这是一个minimal working example (MWE)来演示。首先,我的MariaDB版本:

$ mysql --version
mysql  Ver 15.1 Distrib 10.0.29-MariaDB, for debian-linux-gnu (x86_64) using readline 5.2

接下来,第一个表:

CREATE DATABASE db1;
USE db1;
CREATE TABLE tb1 (id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    word VARCHAR(50) NOT NULL);
INSERT INTO tb1 (word) VALUES ('foo');
DELETE FROM tb1 WHERE word='foo';
DELIMITER $$
CREATE TRIGGER before_word_insert BEFORE INSERT ON tb1 FOR EACH ROW
    BEGIN
        SET NEW.word=TRIM(NEW.word);
        IF NOT (NEW.word REGEXP '^[[:alpha:]]+$') THEN
            SIGNAL SQLSTATE '12345' SET MESSAGE_TEXT = 'Invalid word';
        END IF;
    END$$
DELIMITER ;
INSERT INTO tb1 (word) VALUES ('foo');
DESCRIBE tb1;
SHOW TRIGGERS;
SHOW INDEX FROM tb1;

最后三行给出:

+-------+-------------+------+-----+---------+----------------+
| Field | Type        | Null | Key | Default | Extra          |
+-------+-------------+------+-----+---------+----------------+
| id    | int(11)     | NO   | PRI | NULL    | auto_increment |
| word  | varchar(50) | NO   |     | NULL    |                |
+-------+-------------+------+-----+---------+----------------+
2 rows in set (0.00 sec)

+--------------------+--------+-------+----------------------------------------------------------------------------------------------------------------------------------------------------------+--------+---------+----------+----------------+----------------------+----------------------+--------------------+
| Trigger            | Event  | Table | Statement                                                                                                                                                | Timing | Created | sql_mode | Definer        | character_set_client | collation_connection | Database Collation |
+--------------------+--------+-------+----------------------------------------------------------------------------------------------------------------------------------------------------------+--------+---------+----------+----------------+----------------------+----------------------+--------------------+
| before_word_insert | INSERT | tb1   | BEGIN SET NEW.word=TRIM(NEW.word); IF NOT (NEW.word REGEXP '^[[:alpha:]]+$') THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Invalid word'; END IF; END | BEFORE | NULL    |          | root@localhost | utf8                 | utf8_general_ci      | latin1_swedish_ci  |
+--------------------+--------+-------+----------------------------------------------------------------------------------------------------------------------------------------------------------+--------+---------+----------+----------------+----------------------+----------------------+--------------------+
1 row in set (0.04 sec)

+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| tb1   |          0 | PRIMARY  |            1 | id          | A         |           3 |     NULL | NULL   |      | BTREE      |         |               |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
1 row in set (0.00 sec)

到目前为止,这么好。现在,将tb1复制到另一个数据库(在同一台服务器上):

CREATE DATABASE db2;
USE db2;
CREATE TABLE db2.tb1 AS SELECT * FROM db1.tb1;
DESCRIBE tb1;
SHOW TRIGGERS;
SHOW INDEX FROM tb1;

我原本希望最后三行可以提供与db1相同的输出,但他们不会:

+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int(11)     | NO   |     | 0       |       |
| word  | varchar(50) | NO   |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

Empty set (0.00 sec)

Empty set (0.00 sec)

换句话说,CREATE TABLE db2.tb1 AS SELECT * FROM db1.tb1;

  • 复制了表格内容;
  • 复制了列类型;
  • 没有复制" Key"属性;
  • 未复制"默认"属性;
  • 没有复制" Extra"属性;
  • 未复制触发器;和
  • 未复制索引。

我的问题复制所有缺失的项目的CREATE TABLE db2.tb1 AS SELECT * FROM db1.tb1;简洁等同于什么?

2 个答案:

答案 0 :(得分:2)

CREATE TABLE newTable LIKE oldTable

应包括索引和设置,但不包括数据和触发器。

之后,您需要复制数据:

INSERT INTO newTable SELECT * FROM oldTable

触发器不是表的直接部分,而是脚本管理的一部分。

您可以在information_schema.triggers中找到触发器。在那里,您可以查询表的每个触发器集。但我强烈建议不要手动使用该表

相反,您可以阅读其中的定义,并使用SHOW CREATE TRIGGERCREATE TRIGGER创建新的触发器。这涉及动态sql或能够操作sql的客户端(应该适用于每个客户端)。

如果客户端连接到源数据库和目标数据库,您可以执行以下操作:

SELECT `TRIGGER_NAME` FROM information_schema.triggers WHERE `TRIGGER_SCHEMA` = database() AND `EVENT_OBJECT_TABLE` = oldTableName

正如您在评论中所述,您也可以使用

SHOW TRIGGERS WHERE `Table` = "oldTable"

而不是读取触发器表。作为旁注,Table周围的这些反引号非常重要,因为Table是一个保留字,在这里以类似名称的方式使用。

使用触发器名称,为每个触发器施放

SHOW CREATE TRIGGER triggerNameFromQueryAbove

这为您提供了可用于在新数据库中创建触发器的create语句。但要小心:可能包含数据库名称和定义者,这可能不存在于新数据库中,因此您必须手动删除该信息。

有关"触发器"的更多信息。表,阅读mysql手册(也应该适用于mariadb):https://dev.mysql.com/doc/refman/5.7/en/triggers-table.html

答案 1 :(得分:0)

我正在看这个问题,因为我有同样的问题。我有点沮丧,如果真的没有更简洁的命令来做到这一点。我想指出一个(也许是显而易见的)程序也可以工作。您可以将数据库转储到一个文件(例如“dumpdb1.sql”),如果您使用 mysqldump 进行备份,这已经很方便了。然后,您当然可以仅复制 dumpdb1.sql 中的相关文本,以创建 tb1,设置其约束和索引,并添加其触发器和数据,将此摘录放入文件“buildtb1.sql”中。最后,只需在 db2 上运行后一个文件,您就会在那里获得 tb1 的完美完整副本。

此外,我在 MariaDB 文档中看到:Tutorialspoint MariaDB Table Cloning 他们指出了 SHOW CREATE TABLE 语句在这方面的用处。它将提供一个 CREATE TABLE 语句,您可以在此过程中复制和使用。如果您不想使用它,我只是提到这是 mysqldump 方法的替代方法。当然 SHOW CREATE TABLE 不会描述触发器,因此您仍然需要执行 SHOW TRIGGERS 过程来捕获和重现这些。