Можно ли обеспечить уникальность двух таблиц в MySQL?
У меня есть две таблицы, обе описывают пользователей. Ранее пользователи в этих таблицах относились к двум разным системам, однако теперь мы объединяем наши системы аутентификации, и мне нужно убедиться, что в этих двух таблицах есть уникальные имена пользователей. (сейчас слишком много работы, чтобы поместить их все в одну таблицу).






Очевидно, что если в двух таблицах уже есть дубликаты, вам придется решать эту проблему вручную. Двигаясь вперед, вы можете написать триггер, который проверяет обе таблицы, чтобы увидеть, существует ли уже значение, а затем применять его к обеим таблицам.
Я не знаю MySQL, но именно так это можно сделать в Oracle, и я считаю, что MySQL также поддерживает материализованные представления.
Вы создаете материализованное представление для этих двух таблиц. И вы добавляете уникальное ограничение для этого представления.
Это представление необходимо обновлять каждый раз, когда фиксируется изменение одной из двух базовых таблиц.
MySQL также не обеспечивает должного соблюдения целостности внешнего ключа. :(
Даже с InnoDB? Я думал, что версия 5 подходит.
Механизм хранения MyISAM по умолчанию в MySQL не применяет внешние ключи, но InnoDB прост в использовании. InnoDB поддерживает внешние ключи более 4 лет.
Вы можете добавить дополнительную таблицу с одним столбцом в качестве первичного ключа. Затем создайте триггер в каждой из ваших старых пользовательских таблиц, чтобы вставить идентификатор в эту дополнительную таблицу.
create table users1 (
user_id integer primary key,
username varchar(8) not null unique
);
create table users2 (
user_id integer primary key,
username varchar(8) not null unique
);
create table all_usernames (
username varchar(8) primary key
);
create trigger users1_insert before insert on users1 for each row
insert into all_usernames values(new.username);
create trigger users2_insert before insert on users2 for each row
insert into all_usernames values(new.username);
create trigger users1_update before update on users1 for each row
update all_usernames set username = new.username
where username = old.username;
create trigger users2_update before update on users2 for each row
update all_usernames set username = new.username
where username = old.username;
create trigger users1_delete before delete on users1 for each row
delete from all_usernames where username = old.username;
create trigger users2_delete before delete on users2 for each row
delete from all_usernames where username = old.username;
Затем вы можете заполнить таблицу
insert into all_usernames select username from users1;
insert into all_usernames select username from users2;
Возможно, это не прямой ответ на ваш вопрос, но:
Вам следует подумать о переписывании кода и реструктуризации базы данных, чтобы объединить эти две таблицы в одну.
Дизайн, который вы пытаетесь реализовать сейчас, усложнит ваш код и схему базы данных, а также затруднит дальнейшее обновление до другого программного обеспечения или фреймворков баз данных.
Будет ли доступным изменение типа столбца идентификатора? Затем вы можете выбрать идентификаторы GUID, которые будут уникальными для любого количества таблиц.
Вы не можете объявить ограничение UNIQUE для нескольких таблиц, а MySQL вообще не поддерживает ограничения CHECK. Но вы можете создать триггер для поиска совпадающего значения в другой таблице. Вот тестовый SQL-скрипт:
DROP TABLE IF EXISTS foo;
CREATE TABLE FOO (username VARCHAR(10) NOT NULL);
DROP TABLE IF EXISTS bar;
CREATE TABLE BAR (username VARCHAR(10) NOT NULL);
DROP TRIGGER IF EXISTS unique_foo;
DROP TRIGGER IF EXISTS unique_bar;
DELIMITER //
CREATE TRIGGER unique_foo BEFORE INSERT ON foo
FOR EACH ROW BEGIN
DECLARE c INT;
SELECT COUNT(*) INTO c FROM bar WHERE username = NEW.username;
IF (c > 0) THEN
-- abort insert, because foo.username should be NOT NULL
SET NEW.username = NULL;
END IF;
END//
CREATE TRIGGER unique_bar BEFORE INSERT ON bar
FOR EACH ROW BEGIN
DECLARE c INT;
SELECT COUNT(*) INTO c FROM foo WHERE username = NEW.username;
IF (c > 0) THEN
-- abort insert, because bar.username should be NOT NULL
SET NEW.username = NULL;
END IF;
END//
DELIMITER ;
INSERT INTO foo VALUES ('bill'); -- OK
INSERT INTO bar VALUES ('bill'); -- Column 'username' cannot be null
Вам также нужны похожие триггеры ON UPDATE для каждой таблицы, но вам не нужны никакие триггеры ON DELETE.
лучший способ сделать это - объявить другую таблицу с уникальными столбцами и сделать так, чтобы несколько таблиц ссылались на эти таблицы.
Я не думаю, что это действительно помогает, поскольку ничто не мешает двум записям из разных таблиц ссылаться на один и тот же уникальный столбец в третьей таблице. Возможно, вы могли бы сделать это с помощью какой-то полиморфной ассоциации.
К сожалению, MySQL не поддерживает материализованные представления.