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
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;