Force InnoDB to recheck foreign keys on a table/tables?

后端 未结 5 914
暖寄归人
暖寄归人 2020-11-28 18:34

I have a set of InnoDB tables that I periodically need to maintain by removing some rows and inserting others. Several of the tables have foreign key constra

5条回答
  •  天命终不由人
    2020-11-28 19:19

    The same check but for invalid UNIQUE keys analysis:

    --> Small bug/feature: It will report duplicate nulls also. (While mysql allows duplicate nulls).

    DELIMITER $$
    
    DROP PROCEDURE IF EXISTS ANALYZE_INVALID_UNIQUE_KEYS$$
    
    CREATE
        PROCEDURE `ANALYZE_INVALID_UNIQUE_KEYS`(
            checked_database_name VARCHAR(64), 
            checked_table_name VARCHAR(64))
    
        LANGUAGE SQL
        NOT DETERMINISTIC
        READS SQL DATA
    
        BEGIN
            DECLARE TABLE_SCHEMA_VAR VARCHAR(64);
            DECLARE TABLE_NAME_VAR VARCHAR(64);
            DECLARE COLUMN_NAMES_VAR VARCHAR(1000); 
            DECLARE CONSTRAINT_NAME_VAR VARCHAR(64);
    
            DECLARE done INT DEFAULT 0;
    
            DECLARE unique_key_cursor CURSOR FOR
                select kcu.table_schema sch,
                       kcu.table_name tbl, 
                       group_concat(kcu.column_name) colName, 
                       kcu.constraint_name constName
                from 
                    information_schema.table_constraints tc
                join 
                    information_schema.key_column_usage kcu 
                on 
                    kcu.constraint_name=tc.constraint_name 
                    and kcu.constraint_schema=tc.constraint_schema
                    and kcu.table_name=tc.table_name  
                where 
                    kcu.table_schema like checked_database_name 
                    and kcu.table_name like checked_table_name 
                    and tc.constraint_type="UNIQUE" group by sch, tbl, constName;
    
            DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
    
            DROP TEMPORARY TABLE IF EXISTS INVALID_UNIQUE_KEYS;
            CREATE TEMPORARY TABLE INVALID_UNIQUE_KEYS(
                `TABLE_SCHEMA` VARCHAR(64), 
                `TABLE_NAME` VARCHAR(64), 
                `COLUMN_NAMES` VARCHAR(1000), 
                `CONSTRAINT_NAME` VARCHAR(64),
                `INVALID_KEY_COUNT` INT
            );
    
    
    
            OPEN unique_key_cursor;
            unique_key_cursor_loop: LOOP
                FETCH unique_key_cursor INTO 
                TABLE_SCHEMA_VAR, 
                TABLE_NAME_VAR, 
                COLUMN_NAMES_VAR, 
                CONSTRAINT_NAME_VAR;
                IF done THEN
                    LEAVE unique_key_cursor_loop;
                END IF;
    
                SET @from_part = CONCAT('FROM (SELECT COUNT(*) counter FROM', '`', TABLE_SCHEMA_VAR, '`.`', TABLE_NAME_VAR, '`', 
                        ' GROUP BY ', COLUMN_NAMES_VAR , ') as s where s.counter > 1');
                SET @full_query = CONCAT('SELECT COUNT(*) ', @from_part, ' INTO @invalid_key_count;');
                PREPARE stmt FROM @full_query;
                EXECUTE stmt;
                IF @invalid_key_count > 0 THEN
                    INSERT INTO 
                        INVALID_UNIQUE_KEYS 
                    SET 
                        `TABLE_SCHEMA` = TABLE_SCHEMA_VAR, 
                        `TABLE_NAME` = TABLE_NAME_VAR, 
                        `COLUMN_NAMES` = COLUMN_NAMES_VAR, 
                        `CONSTRAINT_NAME` = CONSTRAINT_NAME_VAR, 
                        `INVALID_KEY_COUNT` = @invalid_key_count;
                END IF;
                DEALLOCATE PREPARE stmt; 
    
            END LOOP unique_key_cursor_loop;
        END$$
    
    DELIMITER ;
    
    CALL ANALYZE_INVALID_UNIQUE_KEYS('%', '%');
    DROP PROCEDURE IF EXISTS ANALYZE_INVALID_UNIQUE_KEYS;
    
    SELECT * FROM INVALID_UNIQUE_KEYS;
    

提交回复
热议问题