mysql删除外键并重建

本文介绍了如何使用MySQL的information_schema查询外键信息,创建存储过程来删除所有外键、备份并导入外键数据,以及添加外键到表中。特别提到了处理跨库外键和复合主键的情况。
-- 使用information_schema查询外键信息:
SELECT 
    CONSTRAINT_NAME, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME,  REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME
FROM
    information_schema.KEY_COLUMN_USAGE
WHERE
    REFERENCED_TABLE_SCHEMA = '数据库名称';

-- 是否有跨库外键
SELECT 
    CONSTRAINT_NAME, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME,  REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME
FROM
    information_schema.KEY_COLUMN_USAGE
WHERE
    REFERENCED_TABLE_SCHEMA IS NOT NULL;
    AND REFERENCED_TABLE_SCHEMA != TABLE_SCHEMA;

-- 将外键导入指定文件
SELECT 
    CONSTRAINT_NAME, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME,  REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME
FROM
    information_schema.KEY_COLUMN_USAGE
WHERE
    REFERENCED_TABLE_SCHEMA IS NOT NULL
    into OUTFILE 'D:/tmp/test.txt';

   
-- 存储过程删除外键
-- 在MySQL中,可以使用以下存储过程来删除所有外键约束:
DELIMITER $$

CREATE PROCEDURE DeleteAllForeignKeys()
BEGIN
    DECLARE done INT DEFAULT FALSE;
    DECLARE fk_name VARCHAR(255);
    DECLARE cur_fk CURSOR FOR 
        SELECT CONCAT('ALTER TABLE ', table_name, ' DROP FOREIGN KEY ', constraint_name) 
        FROM information_schema.key_column_usage 
        WHERE constraint_schema = DATABASE() AND constraint_name LIKE 'fk_%';

    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

    OPEN cur_fk;

    read_loop: LOOP
        FETCH cur_fk INTO fk_name;
        IF done THEN 
            LEAVE read_loop;
        END IF;
        SET @stmt = fk_name;
        PREPARE stmt FROM @stmt;
        EXECUTE stmt;
        DEALLOCATE PREPARE stmt;
    END LOOP;

    CLOSE cur_s;
END$$

DELIMITER ;

--使用该存储过程前,请确保您已经备份了数据库,并且了解这将移除所有外键约束,操作无法撤销。执行存储过程的命令是:
CALL DeleteAllForeignKeys();
--注意:此存储过程假设外键名以'fk_'开头。如果您的外键命名规则不同,请相应地调整查询。
-- 删除存储过程
DROP PROCEDURE IF EXISTS DeleteAllForeignKeys();


-- 通过临时表导入备份数据
CREATE TABLE temp_ref_info (
	CONSTRAINT_NAME VARCHAR(64), 
	TABLE_SCHEMA VARCHAR(64), 
	TABLE_NAME VARCHAR(64), 
	COLUMN_NAME VARCHAR(64), 
	REFERENCED_TABLE_NAME VARCHAR(64), 
	REFERENCED_COLUMN_NAME VARCHAR(64)
);

-- 将文件数据导入临时表
LOAD DATA INFILE 'D:/tmp/test.txt'
INTO TABLE temp_ref_info
FIELDS TERMINATED BY ' '
LINES TERMINATED BY '
'
(CONSTRAINT_NAME, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME,  REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME);


--通过存储过程添加外键
DROP PROCEDURE IF EXISTS add_ref;
DELIMITER $$
CREATE PROCEDURE add_ref()
BEGIN
DECLARE const_name VARCHAR(64);
DECLARE db_name VARCHAR(64);
DECLARE tbl_name VARCHAR(64);
DECLARE col_name VARCHAR(64);
DECLARE col_name VARCHAR(64);
DECLARE ref_col_name VARCHAR(64);

DECLARE done INT DEFAULT 0;

DECLARE add_ref_key CURSOR FOR SELECT CONSTRAINT_NAME, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME,  REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME FROM temp_ref_info;

DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;
OPEN add_ref_key;

tables_loop: LOOP

FETCH add_ref_key INTO const_name, db_name, tbl_name, col_name, col_name, ref_col_name;

IF done THEN 
LEAVE tables_loop;
END IF;
SET @add_ref_ddl := CONCAT('ALTER TABLE ', db_name, '.', tbl_name, ' ADD CONSTRAINT ', const_name, ' FOREIGN KEY (', col_name, ' ) REFERENCES ', db_name, '.', ref_tbl_name, '(', ref_col_name, ')');
PREPARE stmt FROM @add_ref_ddl;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END LOOP;
CLOSE add_ref_key;
END$$
DELIMITER;

call add_ref()

-- 删除存储过程
DROP PROCEDURE IF EXISTS add_ref;

-- 上面存储过程不能处理复合主键的场景,得排查有复合主键的表单独操作



<think>好的,用户问的是如何在MySQL中创建约束,需要示例语法。首先,我得回忆一下MySQL的相关知识。根据之前看到的引用资料,约束可以通过在创建表时添加,或者在已有表上修改添加。还有表级约束和列级约束的区别,但MySQL好像主要用表级的方式,因为约束需要指定名称和关联的表。 记得引用3中提到,创建表时可以使用CONSTRAINT关字加上约束名,然后定义。比如在创建从表的时候,用FOREIGN KEY子句指向父表的字段。同时,父表的字段必须是唯一约束或者主,这一点很重要,不然会创建失败。 另,用户可能需要知道的注意事项,比如存储引擎必须是InnoDB,因为MyISAM不支持。还有字符集和排序规则要一致,否则可能出错。这些细节虽然用户没问,但应该包含在回答里,避免他们踩坑。 还要考虑添加到已存在的表的情况,这时候需要用ALTER TABLE语句,添加约束。语法类似创建时的,但需要指定修改表结构。同时,可能需要处理现有数据是否符合约束,如果数据不一致,添加会失败,这时候需要先清理数据。 示例语法的话,引用3里有一个创建表时添加的例子,可以引用过来。另,再补充一个修改现有表的例子,这样用户两种场景都能覆盖到。此,注意事项部分要提到性能问题,如引用2所说,约束有系统开销,大发情况下可能不适合,这时候应用层需要自己做一致性检查。 可能用户的实际需求是在数据库设计时确保数据完整性,所以需要明确的作用和限制。同时,提醒他们名的重要性,方便以后管理,比如删除或修改时需要用到约束名,这点引用1里提到过查找名的方法,但这里问题主要是创建,所以不需要详细展开。 最后,检查语法是否正确,比如FOREIGN KEY后面跟字段,REFERENCES后面跟父表和字段,约束名要唯一,避免重复。确保所有示例代码正确,没有拼写错误,且符合MySQL的语法规范。</think>### MySQL约束创建方法 在MySQL中创建约束需要满足三个核心条件: 1. 父表字段必须是主或唯一约束 2. 存储引擎必须为InnoDB 3. 字段数据类型必须完全匹配 #### 方法一:建表时创建 ```sql -- 创建父表(班级表) CREATE TABLE class_table ( c_id INT PRIMARY KEY AUTO_INCREMENT, c_name VARCHAR(20) NOT NULL ); -- 创建子表(学生表)添加约束 CREATE TABLE stu_table ( s_id INT PRIMARY KEY AUTO_INCREMENT, c_id INT(4), CONSTRAINT fk_class -- 约束命名 FOREIGN KEY (c_id) -- 指定字段 REFERENCES class_table(c_id) -- 关联父表主 ON DELETE CASCADE -- 级联删除设置 ); ``` #### 方法二:修改现有表结构 ```sql ALTER TABLE stu_table ADD CONSTRAINT fk_class FOREIGN KEY (c_id) REFERENCES class_table(c_id) ON UPDATE CASCADE; -- 级联更新设置 ``` ### 关参数说明 - `ON DELETE` / `ON UPDATE` 支持四种操作: - `CASCADE`:级联操作 - `SET NULL`:设为NULL - `RESTRICT`(默认):阻止操作 - `NO ACTION`:与RESTRICT等效 ### 注意事项 1. 字段必须建立**普通索引**(MySQL会自动创建) 2. 建议使用显式命名约束(如`fk_class`) 3. 大数据量场景需评估性能影响[^2] 4. 修改需要先删除原约束再重建[^1] ### 验证约束 ```sql SHOW CREATE TABLE stu_table; ``` 在输出中应看到包含`CONSTRAINT`关字的完整定义[^3]
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值