我想将一个表(包括其索引和触发器)从一个数据库复制到另一个数据库。这并不像我希望的那么简单。这是一个用于演示的最小工作示例 (MWE)。首先,我的 MariaDB 版本:
$ mysql --version
mysql Ver 15.1 Distrib 10.0.29-MariaDB, for debian-linux-gnu (x86_64) using readline 5.2
Run Code Online (Sandbox Code Playgroud)
接下来是第一个表:
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;
Run Code Online (Sandbox Code Playgroud)
最后三行给出:
+-------+-------------+------+-----+---------+----------------+
| 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)
Run Code Online (Sandbox Code Playgroud)
到现在为止还挺好。现在,复制tb1到另一个数据库(在同一台服务器上):
CREATE DATABASE db2;
USE db2;
CREATE TABLE db2.tb1 AS SELECT * FROM db1.tb1;
DESCRIBE tb1;
SHOW TRIGGERS;
SHOW INDEX FROM tb1;
Run Code Online (Sandbox Code Playgroud)
我曾希望这最后三行会给出与它们相同的输出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)
Run Code Online (Sandbox Code Playgroud)
换句话说,CREATE TABLE db2.tb1 AS SELECT * FROM db1.tb1;:
我的问题:什么是简洁的等效项CREATE TABLE db2.tb1 AS SELECT * FROM db1.tb1;,可以复制所有丢失的项目?
CREATE TABLE newTable LIKE oldTable
Run Code Online (Sandbox Code Playgroud)
应该包括索引和设置,但不包括数据和触发器。
之后,您需要复制数据:
INSERT INTO newTable SELECT * FROM oldTable
Run Code Online (Sandbox Code Playgroud)
触发器不是表的直接一部分,而是脚本管理的一部分。
您可以在 中找到触发器information_schema.triggers。在那里您可以查询为您的表设置的每个触发器。但我强烈建议不要手动处理该表。
相反,您可以阅读那里的定义并使用SHOW CREATE TRIGGERand创建一个新触发器CREATE TRIGGER。这涉及动态 sql 或能够操作 sql 的客户端(这应该适用于每个客户端)。
如果有一个客户端连接到源数据库和目标数据库,您可以执行以下操作:
SELECT `TRIGGER_NAME` FROM information_schema.triggers WHERE `TRIGGER_SCHEMA` = database() AND `EVENT_OBJECT_TABLE` = oldTableName
Run Code Online (Sandbox Code Playgroud)
正如您在评论中所述,您也可以使用
SHOW TRIGGERS WHERE `Table` = "oldTable"
Run Code Online (Sandbox Code Playgroud)
而不是读取触发器表。作为旁注,这些反引号Table很重要,因为它Table是一个保留字,在这里以类似于列名的方式使用。
使用触发器名称,对于每个触发器,您可以使用
SHOW CREATE TRIGGER triggerNameFromQueryAbove
Run Code Online (Sandbox Code Playgroud)
这为您提供了可用于在新数据库中创建触发器的 create 语句。但请注意:可能包含数据库名称和定义者,新数据库中可能不存在这些信息,因此您必须手动删除该信息。
有关“触发器”表的更多信息,请阅读 mysql 手册(也应适用于 mariadb):https ://dev.mysql.com/doc/refman/5.7/en/triggers-table.html