Хранимая процедура Aurora с сохранением значений
Я создал хранимую процедуру, чтобы получить максимальное значение в каждом столбце INT в нашей базе данных, сохранить его в таблице и вычислить процент использования, исходя из максимального допустимого значения для этого типа int.
Первый шаг очищает таблицу и устанавливает значение auto inc обратно на единицу больше, чем последнее использованное значение, вместо того, чтобы позволять innodb угадывать какое-то случайное следующее начальное значение для вставок. Затем я использую информационную схему для вставки любых столбцов со схемой, таблицей, столбцом, типом int и maxValue, разрешенными для этого типа int.
Достаточно простая проблема заключается в курсоре, в случае этой базы данных последняя вставленная запись схемы предназначена для схемы wordpress. Когда он попадает в цикл курсора, он терпит неудачу, потому что по какой-то причине он использует wordpress для значения в первой итерации цикла.
DROP PROCEDURE if exists log_int_over_run;
DELIMITER ;;
CREATE PROCEDURE `log_int_over_run`()
MODIFIES SQL DATA
not deterministic
BEGIN
DECLARE x_id INT;
DECLARE x_currentMaxValue BIGINT(20);
DECLARE x_schemaName VARCHAR(50) DEFAULT 0;
DECLARE x_tableName VARCHAR(50) DEFAULT 0;
DECLARE x_columnName VARCHAR(50) DEFAULT 0;
DECLARE setCurrentValue VARCHAR(400);
DECLARE setLargerValue VARCHAR(400);
DECLARE last_row INT;
DECLARE current_max INT;
DECLARE columns CURSOR FOR select id,schemaName,tableName,columnName,currentMaxValue from datateam.intOverRunLog where tableName !='intOverRunLog' and `ignore` != 1 order by id;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET last_row = 1;
SET last_row=0;
-- Remove any weird auto_inc gaps at the end of that last insert
SET @m = (SELECT IFNULL(MAX(id),0) + 1 FROM datateam.intOverRunLog);
SET @s = CONCAT('ALTER TABLE datateam.intOverRunLog AUTO_INCREMENT=', @m);
PREPARE stmt1 FROM @s;
EXECUTE stmt1;
DEALLOCATE PREPARE stmt1;
-- Load up any new tables
insert ignore INTO datateam.intOverRunLog (schemaName,tableName,columnName,dataType,`maxValue`)
select C.TABLE_SCHEMA,C.TABLE_NAME,C.COLUMN_NAME,C.COLUMN_TYPE,
@max_value := CASE
WHEN COLUMN_TYPE like 'int(%) unsigned' THEN 4294967295
WHEN COLUMN_TYPE like 'int(%)' THEN 2147483647
WHEN COLUMN_TYPE like 'bigint(%) unsigned' THEN 18446744073709551615
WHEN COLUMN_TYPE like 'bigint(%)' THEN 9223372036854775807
WHEN COLUMN_TYPE like 'mediumint(%) unsigned' THEN 16777215
WHEN COLUMN_TYPE like 'mediumint(%)' THEN 8388607
WHEN COLUMN_TYPE like 'smallint(%) unsigned' THEN 65535
WHEN COLUMN_TYPE like 'smallint(%)' THEN 32767
WHEN COLUMN_TYPE like 'tinyint(%) unsigned' THEN 255
WHEN COLUMN_TYPE like 'tinyint(%)' THEN 127
ELSE "UNKNOWN"
END as max_value
FROM information_schema.columns C
JOIN information_schema.tables T on C.TABLE_SCHEMA = T.TABLE_SCHEMA and C.TABLE_NAME = T.TABLE_NAME
where C.TABLE_SCHEMA NOT IN ('information_schema','performance_schema','mysql','sys')
and C.TABLE_NAME NOT IN ('intOverRunLog')
AND COLUMN_TYPE like 'int%';
-- TODO Deactivate any tables/columns that may have changed
-- Get a list of schema/table/columns and iterate through it
OPEN columns;
column_cursor : LOOP
-- SET @value = NULL;
FETCH columns INTO x_id,x_schemaName,x_tableName,x_columnName,x_currentMaxValue;
IF last_row=1 THEN
LEAVE column_cursor;
END IF;
select x_schemaName;
-- SET setCurrentValue = CONCAT('select max(`',x_columnName,'`) INTO @value from `',x_schemaName,'`.`',x_tableName,'`;');
-- select x_schemaName as SchemaName;
SET setCurrentValue = CONCAT('update intOverRunLog set currentMaxValue = (select max(`',x_columnName,'`) from `',x_schemaName,'`.`',x_tableName,'`) where `schemaName` = \'',x_schemaName,'\' and tableName = \'',x_tableName,'\' and columnName = \'',x_columnName,'\';');
SET @sql=setCurrentValue;
select @sql;
PREPARE s1 FROM @sql;
EXECUTE s1;
DEALLOCATE PREPARE s1;
IF @value IS NOT NULL THEN
select x_id,current_max as tableValue,x_currentMaxValue as currentMaxValue,current_max as `second`;
END IF;
END LOOP column_cursor;
CLOSE columns;
END;;
DELIMITER ;
Когда я запускаю его, я получаю:
ERROR 1146 (42S02): Table 'wordpress.apiLog' doesn't exist
И вывод переменной @sql:
update intOverRunLog set currentMaxValue = (select max(`id`) from `wordpress`.`apiLog`) where `schemaName` = 'wordpress' and tableName = 'apiLog' and columnName = 'incoming_link_count';
Первая схема в таблице intOverRunLog - «архив». Итак ... зачем было устанавливать переменную x_schemaName на wordpress? Похоже, это связано с
insert ignore
часть, если я вынимаю ее, она работает нормально.
Также вот определение таблицы, в которую я вставляю это:
CREATE TABLE `intOverRunLog` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`schemaName` varchar(50) NOT NULL,
`tableName` varchar(50) NOT NULL,
`columnName` varchar(50) NOT NULL,
`dataType` varchar(50) NOT NULL,
`maxValue` bigint(20) NOT NULL,
`currentMaxValue` bigint(20) NOT NULL,
`pct` float(10,2) GENERATED ALWAYS AS (((`currentMaxValue` / `maxValue`) * 100)) VIRTUAL,
`ignore` tinyint(1) NOT NULL DEFAULT '0',
`created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`modifed` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`deleted` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY (`id`),
UNIQUE KEY `unique_key` (`schemaName`,`tableName`,`columnName`,`dataType`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8