В приведенном выше комментарии @RajeevRanjan упоминается использование динамического SQL. Это не сработает, но если бы это произошло, это выглядело бы так:
create function related_count(tablename varchar(64), parent int) returns int reads sql data
begin
declare count int default 0;
set @sql = concat('select count(*) into count from `', tablename, '` where id = ', parent);
prepare stmt from @sql;
execute stmt;
return count;
end
Однако это не разрешено:
ОШИБКА 1336 (0A000): Динамический SQL не разрешен в сохраненной функции или триггере
Причина, по которой это не работает, заключается в том, что ваша хранимая функция может быть вызвана выражением в выражении SQL, которое само по себе является динамическим выполнением SQL. Я предполагаю, что MySQL позволяет только один уровень "глубоко" подготовить / выполнить. Вы не можете сделать подготовленный запрос запустить другой подготовленный запрос.
Для этого вам нужно жестко закодировать каждое имя таблицы следующим образом:
create function related_count(tablename varchar(64), parent int) returns int reads sql data
begin
declare count int default null;
if tablename = 'foo' then set count = (select count(*) from foo where id = parent);
elseif tablename = 'bar' then set count = (select count(*) from bar where id = parent);
elseif tablename = 'baz' then set count = (select count(*) from baz where id = parent);
end if;
return count;
end
Это также имеет преимущество в том, что это не уязвимость SQL-инъекций, в отличие от решения PREPARE / EXECUTE (если оно работало).
PS: функция, которая читает из других таблиц, не является deterministic
.