带有varchar变量的MySQL外键失败

时间:2013-05-11 18:18:55

标签: mysql

我在MySQL 5.6.10中遇到了一对父子表的问题。 Django app也涉及下游,以及源自SAS的.tab数据文件。

父表(ccs1)定义了18个我正在标记idx的高级医疗代码,它使用varchar(2)字段表示数字1到18.子项定义了138个子代码,它们提供了另一个级别父级代码的医疗细节:1.1,1.2,2.1,2.2,2.3等,也在其自己的表中标记为idx。在子代中,我创建了另一个名为ccs1_id的varchar(2)变量,该变量是子idx代码中的第一个数字,并且我试图将其设置为父表中等效idx变量的外键引用。 (这是对那些好奇的人使用行业标准的CCS表 - 总共有4个级别,例如4.4.5.1,否则我不会保留varchar表示。)

在子表中读取时,foreign_key_checks = 0的数据插入失败。当我关闭密钥检查时,数据似乎正确读入(在MySQL工作台gui中查看)。当我尝试使用django应用程序中的数据并通过父外键引用过滤子表值时,它只成功过滤 2 数字(字符)的高级代码:10。18从父级键1到9的过滤失败。

这两个表都使用相关变量构造为varchar(2) - 我在下面的每一个中都包含了SHOW CREATE TABLE输出。

到目前为止,我最好的线索来自SHOW ENGINE日志的最新外键错误,当我尝试加载父子表时,foreign_key_checks = 1.父加载成功,然后子项失败:

TRANSACTION 1022234, ACTIVE 0 sec inserting, thread declared inside InnoDB 5000
mysql tables in use 1, locked 1
4 lock struct(s), heap size 320, 1 row lock(s), undo log entries 1
MySQL thread id 177, OS thread handle 0x2280, query id 12426 localhost 127.0.0.1 root        
System lock
LOAD DATA LOCAL INFILE '/abc/dim_dx_ccs2.tab'
INTO TABLE dim_dx_ccs2
IGNORE 1 LINES
(idx, idxm, label, ccs1_id)
Foreign key constraint fails for table `phrat`.`dim_dx_ccs2`:
,
CONSTRAINT `ccs1_id_refs_idx_1213764e` FOREIGN KEY (`ccs1_id`) REFERENCES `dim_dx_ccs1`    (`idx`)
Trying to add in child table, in index `ccs1_id_refs_idx_1213764e` tuple:
DATA TUPLE: 2 fields;
0: len 2; hex 310d; asc 1 ;;
1: len 4; hex 80000103; asc     ;;

But in parent table `phrat`.`dim_dx_ccs1`, in index `idx`,
the closest match we can find is record:
PHYSICAL RECORD: n_fields 2; compact format; info bits 0
0: len 1; hex 31; asc 1;;
1: len 4; hex 80000052; asc    R;;

在这种情况下,它应该在父表中搜索值“1”。看看最后9行,看起来MySQL的varchar数据类型是在修剪后将父表的idx值视为长度为1,并在修剪之前将其与长度为2的值进行比较?也就是说,给定的十进制值310d(十进制:12557)和31(十进制:49)在我读入的数据中没有任何意义,它应该只在1到18之间。 1:字段看起来合适,那些是每个表的主键(ID),第一个条目(外键值为“1”或“1”)。

我错过了一些更基本的东西,或者这是问题的根源?如果是这样我怎么解决它?我想我可以切换到设置长度的CHAR值,这可能会解决,但我想确保我理解这里发生了什么。

这里的参考是SHOW CREATE TABLE输出

-------------------------------------------------------------------------------------+
 dim_dx_ccs1 | CREATE TABLE `dim_dx_ccs1` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `idx` varchar(2) COLLATE utf8_unicode_ci NOT NULL,
 `idxm` varchar(2) COLLATE utf8_unicode_ci NOT NULL,
 `label` varchar(64) COLLATE utf8_unicode_ci NOT NULL,
 PRIMARY KEY (`id`),
 UNIQUE KEY `idx` (`idx`),
 UNIQUE KEY `idxm` (`idxm`)
 ENGINE=InnoDB AUTO_INCREMENT=65 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci |
-------------+--------------------------------------------------------------------------------------


 dim_dx_ccs2 | CREATE TABLE `dim_dx_ccs2` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `idx` varchar(5) COLLATE utf8_unicode_ci NOT NULL,
 `idxm` varchar(5) COLLATE utf8_unicode_ci NOT NULL,
 `label` varchar(128) COLLATE utf8_unicode_ci NOT NULL,
 `ccs1_id` varchar(2) COLLATE utf8_unicode_ci NOT NULL,
 PRIMARY KEY (`id`),
 UNIQUE KEY `idx` (`idx`),
 UNIQUE KEY `idxm` (`idxm`),
 KEY `ccs1_id_refs_idx_1213764e` (`ccs1_id`),
 CONSTRAINT `ccs1_id_refs_idx_1213764e` FOREIGN KEY (`ccs1_id`) REFERENCES `dim_dx_ccs1` (`idx`)
 ENGINE=InnoDB AUTO_INCREMENT=259 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci |
-------------+----------------------------------------------------------------------------------------

其他详情:

  • 数据表源自Unix服务器(SAS所在的位置),但随后将.tab文件导出到Windows环境。

1 个答案:

答案 0 :(得分:1)

查看详细信息,看起来tab文件中包含CR / LF,而导入只需要LF。

这使得预期的0x31('1')导入为0x31 0x0d('1 \ r'),这与主表中的任何值都不匹配,因此导入失败。