mysql:复制包含外键的表结构

mysql:复制包含外键的表结构,mysql,Mysql,我知道如何使用像创建旧表那样创建新表来复制表,但这也不能复制外键约束。我还可以对来自show create table old_table的结果执行字符串操作(使用正则表达式替换表名和外键约束名),但这似乎很容易出错。是否有更好的方法来复制表的结构,包括外键?您可能可以编写一个过程,在创建表之后,根据以下信息准备ALTER table…语句: SELECT * FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE TABLE_NAME LIKE '&l

我知道如何使用
像创建旧表那样创建新表来复制表,但这也不能复制外键约束。我还可以对来自
show create table old_table
的结果执行字符串操作(使用正则表达式替换表名和外键约束名),但这似乎很容易出错。是否有更好的方法来复制表的结构,包括外键?

您可能可以编写一个过程,在
创建表之后,根据以下信息准备
ALTER table…
语句:

SELECT * 
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE 
WHERE TABLE_NAME LIKE '<table_name>' 
AND TABLE_SCHEMA = '<db_name>'
AND REFERENCED_TABLE_NAME IS NOT NULL;
选择*
来自信息\u SCHEMA.KEY\u列\u用法
其中表名称类似于“”
和表_SCHEMA=''
且引用的_表_名称不为空;

如果只需编写一点脚本就可以了,您可以利用
SHOW CREATE TABLE
这样的几行代码(PHP,但该概念适用于任何语言):

//获取create语句
$retrieve=“SHOW CREATE TABLE”;
$create=
//隔离“创建表”索引
$create=$create['create Table'];
//到处用新表名替换旧表名
$create=preg_replace(“/”$newname.“/”,$oldname,$create);
//您可能需要重命名外键以防止名称重复使用错误。
//看http://stackoverflow.com/questions/12623651/
$create=preg_replace(“/FK_/”,“FK_TEMP_”,$create);
//创建新表

不是很优雅,但到目前为止还可以用。我是在一个测试环境中做这件事的,所以我把它放在我的
setUp()
方法中

Wrikken的回答启发了我。让我扩展一下

嗯,事情更复杂。请参阅:。它说,
临时
表和其他东西也会有问题。Wrikken提到的解决方案是一个很好的方法,但是,您需要至少再进行一次查找,以获取有关
UPDATE
DELETE
规则的信息:

SELECT * 
FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
WHERE TABLE_NAME LIKE '<table_name>' 
AND CONSTRAINT_SCHEMA = '<db_name>';
选择*
来自信息\u模式。参考\u约束
其中表名称类似于“”
和约束_模式=“”;
因此,获得一个简化任务的工具可能是一个好主意。我个人使用Adminer()。它附带了一个导出整个数据库的选项(包括所有表、触发器、外键等等)。一旦导出它(在SQL语法中),就可以轻松地更改DB名称并将其重新导入。我在项目的bugs部分写到了这一点(见票证380)

也许你已经有了你最喜欢的数据库管理器,而不想要另一个。然后,您可以按照以下步骤操作:

  • 使用
    mysqldump
    ->转储数据库,您将获得
    file.sql
  • 创建一个新的数据库
  • 在新数据库中执行
    file.sql

  • Adminer
    mysqldump
    都有一个选项,可以只选择特定的表,这样就不必导出整个数据库。如果您只需要结构而不需要数据,请为
    mysqldump
    使用一个选项
    -d
    ,或者在
    Adminer

    中单击该选项。如果您有phpMyAdmin,则可以只导出表的结构,然后在.sql文件中将旧表名更改为新表名并将其导入回


    这是一种相当快速的方法

    如果您只想清理表,可以将所有相关数据复制到复制表中。而不是截断并复制回来。结果是,您保留了FK

    CREATE TABLE IF NOT EXISTS t_copy LIKE t_origin;
    
    INSERT INTO t_copy 
    SELECT  t_origin.*      
    FROM t_origin;
    
    
    SET FOREIGN_KEY_CHECKS = 0;
    
    TRUNCATE t_origin;
    
    INSERT INTO t_origin
    SELECT t_copy.* 
    FROM t_copy;
    
    DROP TABLE t_copy;
    
    SET FOREIGN_KEY_CHECKS = 1; 
    

    我创建了一个bash脚本,将一个表复制到另一个数据库中,通过向其中添加“_1”来修改键和约束:

    mysqldump -h ${host_ip} -u root -p${some_password} ${some_database} ${some_table}  > some_filename
    sed -i -r -e 's@KEY `([a-zA-Z0-9_]*)`@KEY `\1_1`@g' -e 's@CONSTRAINT `([a-zA-Z0-9_]*)`@CONSTRAINT `\1_1`@g' some_filename
    mysql -h ${host_ip} -u root -p${some_password} ${some_new_database} < some_filename
    
    mysqldump-h${host\u ip}-u root-p${some\u password}${some\u database}${some\u table}>some\u文件名
    sed-i-r-e's@KEY`([a-zA-Z0-9\]*)`@KEY`\1\`1`@g'-e's@CONSTRAINT`([a-zA-Z0-9\]*)`@CONSTRAINT`\1\'1`@g'某些文件名
    mysql-h${host\u ip}-u root-p${some\u password}${some\u new\u database}

    这也适用于新的数据库实例,但不需要使用“sed”命令。只有当源数据库和目标数据库位于同一实例中时,才需要执行此操作。

    您是否曾经尝试过这样做?我现在正试图弄明白这一点,但无法真正让它工作。令人遗憾的是,创建表类创建了95%的输出表。。。我,如果这对任何人都有用的话。我把几个相关的问题粘在一起,就像这个问题中提到的那样。如果你处理的是脚本操作,这是最好的方法。令人遗憾的是,创建TABLE-LIKE完成了95%。我,如果这对任何人都有用的话。我把几个相关的问题粘在一起,就像这个问题中提到的那样。这实际上是一个很好的替代解决方案。我不明白那些反对票+从我这里得到1。
    mysqldump -h ${host_ip} -u root -p${some_password} ${some_database} ${some_table}  > some_filename
    sed -i -r -e 's@KEY `([a-zA-Z0-9_]*)`@KEY `\1_1`@g' -e 's@CONSTRAINT `([a-zA-Z0-9_]*)`@CONSTRAINT `\1_1`@g' some_filename
    mysql -h ${host_ip} -u root -p${some_password} ${some_new_database} < some_filename