У меня в моей базе данных много разных таблиц, и мне нужно как-то получить последние вставленные строки из этих таблиц. Как и в социальных сетях. Кроме того, эти таблицы не имеют случайных, но неизвестных имен, поскольку все они генерируются пользователями.
В примере: у меня есть таблицы: A, B, C и D с 5k строк в каждой таблице. Мне нужно как-то получить последние строки из этих таблиц и сделать их упорядоченными по id
, как в простом запросе: "SELECT * FROM table A ORDER BY id DESC"
, но я ищу что-то вроде: "SELECT * FROM A,B,C,D ORDER BY id DESC"
.
Таблицы имеют одинаковую структуру.
Вы можете использовать объединение и порядок, если ваши таблицы имеют одинаковую структуру. Что-то вроде:
select *
from (
select * from A
union all
select * from B
union all
select * from C
) order by id desc
Если таблицы не имеют одинаковой структуры, вы не можете выбрать * из всех и заказать их, и вы можете сделать два запроса. Сначала было бы:
select id, tableName
from (
select id, 'tableA' as tableName from A
union all
select id, 'tableB' as tableName from B
union all
select id, 'tableC' as tableName from C
) order by id desc
Который даст вам последние идентификаторы и таблицы, в которые они вставлены. И тогда вам нужно получить строки из каждой соответствующей таблицы.
С чистым Mysql это будет немного сложно. Вы можете выбрать имена таблиц, например:
SELECT table_name FROM information_schema.tables;
но как их использовать в заявлении? Вам нужно будет генерировать его динамически
Процедура генерации запроса динамически может быть чем-то вроде (я ее не тестировал, но считаю, что с некоторой отладкой она должна работать):
DELIMITER $$
CREATE PROCEDURE buildQuery (OUT v_query VARCHAR)
BEGIN
DECLARE v_finished INTEGER DEFAULT 0;
DECLARE v_table_count INTEGER DEFAULT 0;
DECLARE v_table varchar(100) DEFAULT "";
-- declare cursor for tables (this is for all tables but can be changed)
DEClARE table_cursor CURSOR FOR
SELECT table_name FROM information_schema.tables;
-- declare NOT FOUND handler
DECLARE CONTINUE HANDLER
FOR NOT FOUND SET v_finished = 1;
OPEN table_cursor;
SET v_query="select * from ( ";
get_table: LOOP
FETCH table_cursor INTO v_table;
SET v_table_count = v_table_count + 1;
IF v_finished = 1 THEN
LEAVE get_table;
END IF;
if v_table_count>1 THEN
CONCAT(vquery, " UNION ALL ")
END IF;
SET v_query = CONCAT(vquery," select * from ", v_table );
END LOOP get_table;
SET v_query = CONCAT(vquery," ) order by id desc " );
-- here v_query should be the created query with UNION_ALL
CLOSE table_cursor;
SELECT @v_query;
END$$
DELIMITER ;
Если каждый идентификатор таблицы подсчитывается отдельно, вы не можете заказать по идентификатору, поэтому вам нужно будет вычислить глобальный идентификатор и использовать его во всех ваших таблицах.
Вы можете сделать это следующим образом:
Предполагая, что у вас есть 2 таблицы A, B:
Create Table A(id int NOT NULL auto_increment, name varchar(max), value varchar(max), PRIMARY_KEY(id));
Create Table B(id int NOT NULL auto_increment, name varchar(max), value varchar(max), PRIMARY_KEY(id));
Добавьте еще одну таблицу IDS с идентификатором в качестве первичного ключа с автоматическим добавлением.
Create table IDS (id int NOT NULL auto_increment, ts Timestamp default CURRENT_TIMESTAMP, PRIMARY_KEY(id));
Для всех столбцов идентификатор таблицы следует использовать идентификатор из таблицы IDS в качестве внешнего ключа вместо автоматического увеличения.
Create Table A(id int NOT NULL auto_increment, name varchar(max), value varchar(max), PRIMARY_KEY(id),CONSTRAINT fk_A_id FOREIGN KEY(id) REFERENCE IDS(id) ON DELETE CASCADE ON UPDATE CASCADE);
Create Table B(id int NOT NULL auto_increment, name varchar(max), value varchar(max), PRIMARY_KEY(id),CONSTRAINT fk_A_id FOREIGN KEY(id) REFERENCE IDS(id) ON DELETE CASCADE ON UPDATE CASCADE);
для каждой таблицы добавьте триггер insert, триггер должен сначала вставить строку в таблицу IDS и вставить таблицу LAST_INSERT_ID
в таблицу.
Create TRIGGER befor_insert_A BEFORE INSERT On A
FOR EACH ROW
BEGIN
insert into IDS() values ();
set new.id = LAST_INSERT_ID();
END
Create TRIGGER befor_insert_B BEFORE INSERT On B
FOR EACH ROW
BEGIN
insert into IDS() values ();
set new.id = LAST_INSERT_ID();
END
Теперь вы можете создать представление из всех таблиц с объединением all, строки v теперь можно отсортировать по идентификатору и предоставить вложенный порядок вставки.
Create view V AS select * from A UNION ALL select * from B
Например, вы можете запросить на V последние 10 идентификаторов:
select * from V Order by id desc LIMIT 10
Другой вариант - добавить временную метку для каждой таблицы и отсортировать представление по метке времени.
Привет, вы ищете это? Однако идентификатор не является хорошим столбцом, чтобы увидеть последнее обновление среди разных таблиц.
select *
from A
join B
on 1=1
join C
on 1=1
join D
on 1=1
order by A.id desc