Если вы обнаружите, что у вас несколько таблиц с одинаковыми столбцами, у вас, вероятно, плохая схема.То, что вы спрашиваете, не обязательно с хорошо разработанной схемой.Я рекомендую вам задать еще один вопрос о том, как спроектировать схему, чтобы полностью избежать вашей проблемы.
Объединение нефильтрованных строк вместе уязвимо для атаки SQL-инъекцией .Вместо этого, когда это возможно, используйте параметры связывания и передайте значения. Это гарантирует, что они правильно экранированы и заключены в кавычки и не будут неверно истолкованы ни случайно, ни злонамеренно.
SET @q = 'INSERT INTO `' , @tableName, '` VALUES(?,?,?,?,?,?)';
PREPARE stmt FROM @q;
EXECUTE stmt USING @NName, @APName, @AMName, @NomName, @DNIName, @DirectName
Это также решает другие ваши проблемы,не все является строкой.
CALL insert_data ('table_x', 'NULL', 'A', 'B', 'C', 'D', 'E ')
^^^^
Параметры привязки сохранят тип не-строк, таких как целые и нулевые значения.Также отмечу, что N
- это целое число, но вы используете его как имя, которое обычно означает строку.Так что это может быть проблемой.
Теперь о том противном имени таблицы.Мы не можем передать это как параметр связывания.Вы хотите убедиться, что он не может выпрыгнуть из своих кавычек, поэтому `необходимо экранировать.Вы также не хотите, чтобы кто-либо мог перейти к другой базе данных, поэтому .
также должен быть экранирован.Или, что еще лучше, выдаст ошибку .Мы не можем использовать quote()
, потому что это для значений столбцов с другими правилами цитирования.Нам придется написать нашу собственную.
DELIMITER $$
drop procedure if exists check_table_name;
CREATE PROCEDURE check_table_name (
table_name varchar(255)
)
begin
if( locate("`", table_name) ) then
signal sqlstate '45000'
set message_text = 'illegal ` in table name';
elseif( locate(".", table_name) ) then
signal sqlstate '45000'
set message_text = 'illegal . in table name';
end if;
end $$
DELIMITER ;
Теперь мы называем это именем таблицы перед ее использованием.
call check_table_name(@tableName);
SET @q = concat('INSERT INTO `' , @tableName, '` VALUES(?,?,?,?,?,?)');
PREPARE stmt FROM @q;
EXECUTE stmt USING @NName, @APName, @AMName, @NomName, @DNIName, @DirecName;
DEALLOCATE PREPARE stmt;
И если это будет непослушным, мы получим ошибку.
mysql> call insertar_datos("foo`haha, I broke your quoting`bar", 23, 'A', 'B', 'C', 'D', 'E ');
ERROR 1644 (45000): illegal ` in table name
Но опять же Я настоятельно не рекомендую этот подход .В любое время, когда вы объединяете строки, чтобы составить операторы SQL, вы подвержены риску ошибок и недостатков безопасности.Я не уверен, что check_table_name
объясняет все проблемы.
Если вы должны использовать этот подход, рассмотрите вместо этого использование фиксированного набора разрешенных имен.
if name in ("foo", "bar", "baz", "table_x") then
set @tableName = name;
else
signal sqlstate '45000'
set message_text = 'unknown name';
end if;
Я призываю васвместо этого рассмотрите возможность изменения схемы.