MariaDB跨库创建一对一外键关系报错1103,求原因及可行性
跨库建立一对一外键关系报错处理
问题描述
在MariaDB中,Contracts数据库内的Contracts表建表语句如下:
CREATE TABLE `Contracts` ( `Id` bigint(20) NOT NULL AUTO_INCREMENT, `Guid` uuid NOT NULL DEFAULT uuid(), `Locale` varchar(400) NOT NULL, `Title` varchar(400) DEFAULT NULL, `ImageGuid` uuid DEFAULT NULL, `DocumentNumber` bigint(20) DEFAULT NULL, `UtcDate` datetime NOT NULL, PRIMARY KEY (`Id`), UNIQUE KEY `IX_Contracts_Unique_Guid` (`Guid`), UNIQUE KEY `IX_Contracts_Unique_Title_And_UtcDate` (`Title`,`UtcDate`), KEY `IX_Contracts_Guid` (`Guid`), KEY `IX_Contracts_Locale` (`Locale`), CONSTRAINT `Ck_Contracts_NonEmptyGuid` CHECK (`Guid` <> '00000000-0000-0000-0000-000000000000'), CONSTRAINT `Ck_Contracts_NonEmptyImageGuid` CHECK (`ImageGuid` <> '00000000-0000-0000-0000-000000000000') ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci
Tracking数据库内的TruckHeadContracts表建表语句如下:
CREATE TABLE `TruckHeadContracts` ( `Id` bigint(20) NOT NULL AUTO_INCREMENT, `Dummy` varchar(400) NOT NULL, PRIMARY KEY (`Id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci
执行以下添加外键的语句尝试建立一对一关系时:
alter table `TruckHeadContracts` add constraint FK_TruckHeadContracts_Id_Contracts.Contracts_Id foreign key (`Id`) references `Contracts.Contracts` (Id) on update cascade on delete cascade
出现错误:
Error in query (1103): Incorrect table name 'FK_TruckHeadContracts_Id_Contracts'
需要在数据库层面实现两表的一对一关系,且无需修改业务代码,需排查错误原因。
错误分析与解决方法
- 约束名称包含非法字符:MariaDB的约束名称不能包含
.,你写的FK_TruckHeadContracts_Id_Contracts.Contracts_Id里的.导致数据库误将.前的部分识别为表名,引发报错。约束名称应改用下划线或其他合法字符,比如FK_TruckHeadContracts_Contracts_Id。 - 跨库表引用语法错误:引用其他数据库中的表时,正确格式是
数据库名.表名,且如果使用反引号,需要分别包裹数据库名和表名,即referencesContracts.Contracts(Id),而不是把数据库和表名放在同一个反引号里。 - 一对一关系的实现要点:由于
TruckHeadContracts的Id是自增主键(本身唯一),Contracts的Id也是主键(唯一),用TruckHeadContracts.Id作为外键引用Contracts.Id,天然就能保证一对一关系——每个TruckHeadContracts记录只能对应一个Contracts记录,反之亦然。
正确的SQL语句
ALTER TABLE `Tracking`.`TruckHeadContracts` ADD CONSTRAINT `FK_TruckHeadContracts_Contracts_Id` FOREIGN KEY (`Id`) REFERENCES `Contracts`.`Contracts` (`Id`) ON UPDATE CASCADE ON DELETE CASCADE;
(注:如果当前会话已切换到Tracking数据库,也可以省略Tracking.前缀)
内容的提问来源于stack exchange,提问作者Sharif Rezvani
相关产品推荐
相关产品推荐

