在 NVARCHAR 类型的表之间创建主键和关系

Posted

技术标签:

【中文标题】在 NVARCHAR 类型的表之间创建主键和关系【英文标题】:Creating a primary key and relationships between tables with NVARCHAR type 【发布时间】:2017-01-31 16:55:51 【问题描述】:

我有相当的 SQL 难题。

我是第一个合作社职位的初级程序员,我得到了一个包含三个表的数据库。这三个表中的任何一个都没有主键。这些表彼此之间没有初始关系。这就是数据库的(大致)设计方式。

Table 1     Table2      Table3
========    ========    ========    
SSerial     BSerial     MSerial
B1          data2       data2
B2          data3       data3
B3          data4       data4
M1          data5       data5
M2          data6       data6
M3          data7       data7

SSerial、BSerial 和 MSerial 具有永远不会重复的唯一字母数字值 (nvarchar(MAX))。

BSerial 的值可以在表 1 的 B1、B2 和 B3 中找到。

MSerial 的值可以在 Table1 的 M1、M2 和 M3 中找到。

我正在开发的应用程序的最终目标是允许客户端通过表 1 中的唯一 SSerial 号进行搜索,然后查看 B1、B2 和 B3 中的 BSerial 值。他们还可以对 M1、M2 和 M3 中的 MSerial 值执行相同的操作。

我已经尝试实现一个主键,以便在 Table1 和其他表之间添加关系,但无济于事。

当我尝试创建主键时:

ALTER TABLE dbo.Table2
ADD Table2_ID int NOT NULL IDENTITY (1,1);

ALTER TABLE dbo.Table2
ADD CONSTRAINT PK_Table2_ID PRIMARY KEY (Table2_ID, BSerial);

我很幸运收到了以下错误消息:

Msg 1919, Level 16, State 1, Line 1
Column 'BSerial' in table 'Table2' is of a type that is invalid for use as a key column in an index.

附加信息:

    SSerial、BSerial 和 MSerial 不为 NULL,并且属于 NVARCHAR(MAX) 类型。 B1、B2、B3、M1、M2 和 M3 允许为空,因为并不总是有三个 BSerial 或 MSerial 与 SSerial 相关联。它们的类型为 NVARCHAR(MAX)。 从头开始重新创建数据库并不理想,因为每个表中有数千行数据,但可以做到。

这是我的第一个 Stack Overflow 问题,如果需要更多信息,我非常欢迎详细说明。感谢您的宝贵时间!

【问题讨论】:

索引有大小限制。 technet.microsoft.com/en-us/library/ms191241(v=sql.105).aspx 尝试使用小于 nvarchar(max) 的数据类型。您真的需要在这些字段中添加几乎无限的文本吗? 我坚信我会这样做。序列号的长度相当大,我认为平均为 45-60 个字符,但可能会增长。当我们向客户发货时,他们每天会将 900 多个零件及其信息插入数据库,我必须与我的主管核实它们的长度是否会随着时间而改变。 45-60 个字符很远,far 小于nvarchar(max) 的容量。见What is the maximum characters for the nvarchar(max)?。将其更改为当前的实际最大值加上一点会更好。如果需要更多空间,那么当时增加容量应该不会太难。 【参考方案1】:

将数据类型从NVARCHAR(MAX) 更改为NVARCHAR(450)。 索引的键总大小不能超过 900 字节。

【讨论】:

【参考方案2】:

我会建议重新设计您的数据库,但如果这不切实际,您不需要主键来实现您的目标。为了使下面的代码正常工作,BSerial 和 MSerial 值必须与表 1 中的完全匹配。

    select * from table1 t1
left join table2 t2 on t1.b1 = t2.bserial
left join table2 t3 on t1.m1 = t3.mserial
where t1.sserial = 'some value'

【讨论】:

我能够通过此解决方案获得所需的结果,谢谢!

以上是关于在 NVARCHAR 类型的表之间创建主键和关系的主要内容,如果未能解决你的问题,请参考以下文章

在复合键和外键之间创建关系

oracle中 主键和外键是啥意思?啥地方采用呢?

oracle中 主键和外键是啥意思?啥地方采用呢?

SQL入门经典 之键和约束

SQL入门经典之键和约束

如何在 Phpmyadmin 中使用主键和外键创建关系数据库?