我有一个包含两列'NAME'和'ALIAS'的表格。 我希望这两列的内容都是唯一的。 因此,我无法创建已经在'ALIAS'中的'NAME',反之亦然。
不允许使用“ NAME” B,因为先前已在列中使用B 'ALIAS';
不允许使用“ ALIAS” A,因为以前在列中使用了A “ NAME”;
允许使用“ NAME” C,因为以前从未使用过“ C” 允许使用“名称”列,“别名”列和“别名” D,因为 从未在“名称”列和“ “ ALIAS”列;
...
我希望“ NAME”列和“ ALIAS”列中的数据唯一 列
我已经尝试过这种方式,
CREATE TABLE `Group` (
Name VARCHAR(50) NOT NULL DEFAULT '',
Alias VARCHAR(255) DEFAULT NULL,
PRIMARY KEY (Name)
)
ENGINE = MYISAM,
CHECKSUM = 0;
ALTER TABLE `Group` ADD CONSTRAINT Constraint_Group UNIQUE KEY(`Name`, `Alias`);
但“唯一”仅适用于相应的列。
有没有办法得到它?
谢谢。
答案 0 :(得分:0)
您可以从一个表中提取可能的名称,该表在UNIQUE
列上有一个name
约束。这样,您就不能将名称用于多个目的。为了使这项工作切实可行,您将需要另外一列指定名称的类型(如果是用于组名或别名)。您将此列用作外键的一部分。
注意:要运行此功能,您将需要(并且应该始终使用)InnoDB storage engine,以便可以使用外键。
首先,为“所有”可能的名称创建一个表。
CREATE TABLE names (
id INT AUTO_INCREMENT PRIMARY KEY NOT NULL,
name VARCHAR(300) NOT NULL,
kind VARCHAR(15) NOT NULL,
CONSTRAINT UQ_name UNIQUE(name),
CONSTRAINT CH_names_kind CHECK (kind IN ('name', 'alias')),
KEY IX_names_nameAndKind (name, kind)
);
(您需要使用MySQL 8来使CHECK
语句正常工作)
如您所见,name
列具有UNIQUE
约束,因此您不能有重复的条目。同样,每个条目都必须是'name'
或'alias'
的{{1}}条目中的一种,并且由于名称不能重复,因此必须选择。您可以按照以下步骤填写条目:
CHECK
现在最棘手的部分是组表。您不仅需要引用列INSERT INTO names (name, kind) VALUES ('A', 'name');
INSERT INTO names (name, kind) VALUES ('B', 'alias');
INSERT INTO names (name, kind) VALUES ('C', 'name');
,还必须组合引用name
。这也是kind
表中有键IX_names_nameAndKind
的原因。因此,您可以引用多列索引names
和name
,而不是从其他表中引用自动增量列的id值。您可以为组的名称以及组的可选别名执行此操作。 kind
语句可能看起来像这样:
CREATE TABLE
外键CREATE TABLE grps (
id INT AUTO_INCREMENT PRIMARY KEY NOT NULL,
name VARCHAR(300) NOT NULL,
nameKind VARCHAR(15) NOT NULL,
alias VARCHAR(300) NULL,
aliasKind VARCHAR(15) NULL,
FOREIGN KEY FK_grps_nameAndNameKind (name, nameKind) REFERENCES names (name, kind),
CONSTRAINT CH_grps_nameKind CHECK (nameKind IN ('name')),
FOREIGN KEY FK_grps_aliasAndAliasKind (alias, aliasKind) REFERENCES names (name, kind),
CONSTRAINT CH_grps_aliasKind CHECK (aliasKind IN ('alias'))
);
指出,列FK_grps_nameAndNameKind
和name
必须来自nameKind
表(列names
和{{1 }}。 name
和kind
列的外键FK_grps_aliasAndAliasKind
也是如此。但是这里的窍门是限制alias
列只允许值aliasKind
,而nameKind
列只允许值'name'
(请参阅aliasKind
声明)。因此,在引用组名时,它的类型必须为'alias'
;在引用别名时,它的名称必须是类型CHECK
。您可以按如下所示填写表格:
'name'
当您尝试破坏支票和外键时,您会收到预期的错误消息:
'alias'
INSERT INTO grps (name, nameKind, alias, aliasKind) VALUES ('A', 'name', NULL, NULL);
INSERT INTO grps (name, nameKind, alias, aliasKind) VALUES ('C', 'name', 'B', 'alias');
答案 1 :(得分:0)
在@Michael - sqlbot的this thread中得到答案
使用Triger满足我的需求。
DROP TABLE IF EXISTS Groups;
CREATE TABLE groups (
Name varchar(50) NOT NULL DEFAULT '',
Alias varchar(50) DEFAULT NULL,
PRIMARY KEY (Name)
)
ENGINE = MYISAM,
CHARACTER SET utf8,
CHECKSUM = 0,
COLLATE utf8_general_ci;
ALTER TABLE groups
ADD UNIQUE INDEX Alias (Alias);
CREATE TRIGGER trg_Ins BEFORE INSERT ON groups FOR EACH ROW
BEGIN
DECLARE err_msg VARCHAR(128) DEFAULT NULL;
IF EXISTS(SELECT x.alias FROM groups x WHERE x.alias = NEW.name) OR (NEW.Name=New.Alias) THEN
SET err_msg = CONCAT_WS('','cannot insert Name value ',NEW.Name,'; already exists as a Alias');
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = err_msg;
END IF;
IF EXISTS(SELECT x.Name FROM groups x WHERE x.Name = NEW.Alias) OR (NEW.Alias=NEW.Name) THEN
SET err_msg = CONCAT_WS('','cannot insert Alias value ',NEW.Alias,'; already exists as a Name');
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = err_msg;
END IF;
END;
CREATE TRIGGER trg_Upd BEFORE UPDATE ON groups FOR EACH ROW
BEGIN
DECLARE err_msg VARCHAR(128) DEFAULT NULL;
IF EXISTS(SELECT x.alias FROM groups x WHERE x.alias = NEW.name) OR (NEW.Name=New.Alias) THEN
SET err_msg = CONCAT_WS('','cannot Update Name value ',NEW.Name,'; already exists as a Alias');
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = err_msg;
END IF;
IF EXISTS(SELECT x.Name FROM groups x WHERE x.Name = NEW.Alias) OR (NEW.Alias=NEW.Name) THEN
SET err_msg = CONCAT_WS('','cannot Update Alias value ',NEW.Alias,'; already exists as a Name');
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = err_msg;
END IF;
END;
-- TEST INSERT
Insert INTO Groups VALUES ('A','B'); -- OK
Insert INTO Groups VALUES ('B',NULL); -- cannot insert Name value B; already exists as a Alias
Insert INTO Groups VALUES ('C','A'); -- cannot insert Alias value A; already exists as a Name
Insert INTO Groups VALUES ('C','D'); -- OK
Insert INTO Groups VALUES ('E','Z'); -- OK
Insert INTO Groups VALUES ('K','K'); -- cannot insert Name value K; already exists as a Alias
-- TEST UPDATE
UPDATE groups SET `Name`='A' WHERE `Name`='C'; -- Duplicate entry 'A' for key
UPDATE groups set `Name` ='X' WHERE `Name`='E'; -- OK
UPDATE groups set `Alias` ='A' WHERE `Name`='X'; -- cannot Update Name value B; already exists as a Alias
-将尝试更多测试