MySQL использовать имя таблицы для функции - PullRequest
0 голосов
/ 28 апреля 2018

Когда мы используем оператор, подобный select count(*) from TABLE, функция count () автоматически знает, какую таблицу она считает. Можно ли взять таблицу и использовать ее в определенной пользователем функции.

   drop function if exists related_count;
   create function related_count(parent int(11)) returns int(11) deterministic 
   begin 
    declare count int(11) default 0;
    set count=(select count(*) from TABLENAME where id=parent);
    return count;
   end;

Так что я могу использовать это так:

select count(*),related_count(id) from TABLENAME

Так что я могу использовать одну и ту же функцию независимо от таблицы вместо определения нескольких функций из-за нескольких таблиц.

Есть ли способ переключения между select count(*) from TABLENAME1 where id=parent или select count(*) from TABLENAME2 where id=parent в зависимости от переменной related_count('TABLE1',id)

1 Ответ

0 голосов
/ 28 апреля 2018

В приведенном выше комментарии @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.

...