鼎湖二手房:J道- 主键设计用什么字段类型比较好?

来源:百度文库 编辑:偶看新闻 时间:2024/05/02 08:04:00

主键设计用什么字段类型比较好?

redlly http://www.jdon.com Jun 14, 2005 12:21 PM 回复

主键设计用什么字段类型比较好?
一般有采用数字型和字符型,哪种好点?使用多长比较好?


Re: 主键设计用什么字段类型比较好? 发表时间: Jun 22, 2005 6:04 PM 回复 发表人: 54powerman    发表文章: 9 / 注册时间: 2004-12 还是使用序列吧,否则你还要控制Unique约束的问题。


Re: 主键设计用什么字段类型比较好? 发表时间: Jul 3, 2005 5:42 AM 回复 发表人: redlly    发表文章: 40 / 注册时间: 2003-07 > 还是使用序列吧,否则你还要控制Unique约束的问题。

用序列?如果出现这样的问题:
一个公司,底下几个子公司,自公司采用相同的系统,数据库结构都一样,子公司数据每天上报总公司汇总,能保证每个子公司产生的数据的主键都唯一吗?
或者是子公司里有个牛人,越过你的系统在数据库中插入了一条记录,你原来的序列在999,理应下一条记录是1000,可是这时候数据库里已经有了1000,怎么办?


Re: 主键设计用什么字段类型比较好? 发表时间: Jul 3, 2005 12:24 PM 回复 发表人: banq    发表文章: 5064 / 来  自: 上海 / 注册时间: 2002-08 用你的序列产生器,就禁止手工插入序列号了,你可以使用一个校验程序,如果有人手工插入大于现在序列号,视为无效。必须通过程序插入。


Re: 主键设计用什么字段类型比较好? 发表时间: Jul 3, 2005 6:11 PM 回复 发表人: redlly    发表文章: 40 / 注册时间: 2003-07 数据库主键设计之思考

  主键的必要性:
 有些朋友可能不提倡数据库表必须要主键,但在我的思考中,觉得每个表都应该具有主键,不管是单主键还是双主键,主键的存在就代表着表结构的完整性,表的记录必须得有唯一区分的字段,主键主要是用于其他表的外键关联,本记录的修改与删除,当我们没有主键时,这些操作会变的非常麻烦。
  主键的无意义性:
 我强调主键不应该具有实际的意义,这可能对于一些朋友来说不太认同,比如订单表吧,会有“订单编号”字段,而这个字段呢在业务实际中本身就是应该具有唯一性,具有唯一标识记录的功能,但我是不推荐采用订单编号字段作为主键的,因为具有实际意义的字段,具有“意义更改”的可能性,比如订单编号在刚开始的时候我们一切顺利,后来客户说“订单可以作废,并重新生成订单,而且订单号要保持原订单号一致”,这样原来的主键就面临危险了。因此,具有唯一性的实际字段也代表可以作为主键。因此,我推荐是新设一个字段专门用为主键,此主键本身在业务逻辑上不体现,不具有实际意义。而这种主键在一定程序增加了复杂度,所以要视实际系统的规模大小而定,对于小项目,以后扩展不会很大的话,也查允许用实际唯一的字段作主键的。
  主键的选择
我们现在在思考一下,应该采用什么来作表的主键比较合理,申明一下,主键的设计没有一个定论,各人有各人的方法,哪怕同一个,在不同的项目中,也会采用不同的主键设计原则。
第一:编号作主键
此方法就是采用实际业务中的唯一字段的“编号”作为主键设计,这在小型的项目中是推荐这样做的,因为这可以使项目比较简单化,但在使用中却可能带来一些麻烦,比如要进行“编号修改”时,可能要涉及到很多相关联的其他表,就象黎叔说的“后果很严重”;还有就是上面提到的“业务要求允许编号重复时”,我们再那么先知,都无法知道业务将会修改成什么?
  第二:自动编号主键
这种方法也是很多朋友在使用的,就是新建一个ID字段,自动增长,非常方便也满足主键的原则,优点是:数据库自动编号,速度快,而且是增量增长,聚集型主键按顺序存放,对于检索非常有利;数字型的,占用空间小,易排序,在程序中传递也方便;如果通过非系统增加记录(比如手动录入,或是用其他工具直接在表里插入新记录,或老系统数据导入)时,非常方便,不用担心主键重复问题。
缺点:其实缺点也就是来自其优点,就是因为自动增长,在手动要插入指定ID的记录时会显得麻烦,尤其是当系统与其他系统集成时,需要数据导入时,很难保证原系统的ID不发生主键冲突(前提是老系统也是数字型的);如果其他系统主键不是数字型那就麻烦更大了,会导致修改主键数据类型了,这也会导致其他相关表的修改,后果同样很严重;就算其他系统也是数字型的,在导入时,为了区分新老数据,可能想在老数据主键前统一加一个“o”(old)来表示这是老数据,那么自动增长的数字型又面临一个挑战。
  第三:Max加一
由于自动编号存在那些问题,所以有些朋友就采用自己生成,同样是数字型的,只是把自动增长去掉了,采用在Insert时,读取Max值后加一,这种方法可以避免自动编号的问题,但也存在一个效率问题,如果记录非常大的话,那么Max()也会影响效率的;更严重的是并发性问题,如果同时有两人读到相同的Max后,加一后插入的ID值会重复,这已经是有经验教训的了。
  第四:自制加一
考虑Max加一的效率后,有人采用自制加一,也就是建一个特别的表,字段为:表名,当前序列值。这样在往表中插入值时,先从此表中找到相应表的最大值后加一,进行插入,有人可能发现,也可能会存在并发处理,这个并发处理,我们可以采用lock线程的方式来避免,在生成此值的时,先Lock,取到值以后,再unLock出来,这样不会有两人同时生成了。这比Max加一的速度要快多了。但同样存在一个问题:在与其他系统集成时,脱离了系统中的生成方法后,很麻烦保证自制表中的最大值与导入后的保持一致,而且数字型都存在上面讲到的“o”老数据的导入问题。因此在“自制加一”中可以把主键设为字符型的。字符型的自制加一我倒是蛮推荐的,应该字符型主键可以应付很多我们意想不到的情况。
第五:GUID主键
目前一个比较好的主键是采用GUID,当然我是推荐主键还是字符型的,但值由GUID生成,GUID是可以自动生成,也可以程序生成,而且键值不可能重复,可以解决系统集成问题,几个系统的GUID值导到一起时,也不会发生重复,就算有“o”老数据也可以区分,而且效率很高,在.NET里可以直接使用System.Guid.NewGuid()进行生成,在SQL里也可以使用 NewID()生成。优点是:
同 IDENTITY 列相比,uniqueidentifier 列可以通过 NewID() 函数提前得知新增加的行 ID,为应用程序的后续处理提供了很大方便。
便于数据库移植,其它数据库中并不一定具有 IDENTITY 列,而 Guid 列可以作为字符型列转换到其它数据库中,同时将应用程序中产生的 GUID 值存入数据库,它不会对原有数据带来影响。
便于数据库初始化,如果应用程序要加载一些初始数据, IDENTITY 列的处理方式就比较麻烦,而 uniqueidentifier 列则无需任何处理,直接用 T-SQL 加载即可。
便于对某些对象或常量进行永久标识,如类的 ClassID,对象的实例标识,UDDI 中的联系人、服务接口、tModel标识定义等。
  缺点是:
GUID 值较长,不容易记忆和输入,而且这个值是随机、无顺序的。
GUID 的值有 16 个字节,与其它那些诸如 4 字节的整数相比要相对大一些。这意味着如果在数据库中使用 uniqueidentifier 键,可能会带来两方面的消极影响:存储空间增大;索引时间较慢。
我也不是推荐GUID最好,其实在不同的情况,我们都可以采用上面的某一种方式,思考了一些利与弊,也方便大家在进行设计时参考。这些也只是我的一点思考而已,而且可能我知识面限制,会有一些误论在里面,希望大家有什么想法欢迎讨论。


Re: 主键设计用什么字段类型比较好? 发表时间: Jul 5, 2005 1:20 AM 回复 发表人: banq    发表文章: 5064 / 来  自: 上海 / 注册时间: 2002-08 写得非常好,主键是肯定要的,有了之后会方便很多。
有一种Object ID的方法,也就是专门使用sequence包产生ID,不知属于你总结这些类别中哪一个?


Re: 主键设计用什么字段类型比较好? 发表时间: Jul 12, 2005 1:25 AM 回复 发表人: redlly    发表文章: 40 / 注册时间: 2003-07 > 写得非常好,主键是肯定要的,有了之后会方便很多。
> 有一种Object
> ID的方法,也就是专门使用sequence包产生ID,不知属于你总
> 嵴庑├啾鹬心囊桓觯?

专门使用sequence包产生ID,不清楚这里的sequence包产生的ID是否是安某种序列增长型的?其实也没关系,我的理解是由专门的主键生成器按照某种算法生成主键,不管是按照序列型还是hash型生成主键,好像hibernate的自动主键产生就是这种方式。不属于上面总结的任何一种。不过这也不能完全保证主键唯一性,看你的算法好坏了,世事无绝对,谁知道呢,GUID在几百亿次里面还有可能出现重复啊。


Re: 主键设计用什么字段类型比较好? 发表时间: Aug 4, 2005 8:52 PM 回复 发表人: mysapphire    发表文章: 33 / 注册时间: 2003-12 >写得非常好,主键是肯定要的,有了之后会方便很多。
>有一种Object ID的方法,也就是专门使用sequence包产生ID,不知属于你总结这些类别中哪一个?

这种方法很好,在实际的编程当中有很高的灵活性,数据库操作越繁杂这种方法体现的优点越明显,不过要请教一下怎么实现? 比如在DB2中select nextval form seq_1? 这样似乎不行啊!
而且这种方法在一种场合下无法使用:确保主键的连贯性。

Identity列能确保连贯,而且通过Statement.getGeneratedKeys()又能得到新增加的键值,这样也解决了主表-明细表插入的问题,因此选Identity列用作主键可谓是比较广泛的选择。

我个人觉得要用主键的话以上两种方法最可取,不过彼此都有一个互补的缺点:前者无法确保连贯;后者在导数据的时候要额外花点心思。

我现在的开发就遇到一种需要确保主键连贯的场合,无法使用第二种主键,而且也不知道如何使用简单的方法实现第一种方法中提到的Object ID,现在我的苯办法是通过select nextval for seq_1 from temp_table fetch first 1 rows only得到ID的! 希望不要被知道诀窍的人笑掉大牙哦!


Re: 主键设计用什么字段类型比较好? 发表时间: Sep 4, 2005 9:17 PM 回复 发表人: idofindit    发表文章: 1 / 注册时间: 2005-09 我有一疑问,有一表,如下字段:
ID(GUID)主键, 名称, 所属类别, 其它

我插入一条记录,然后再插入一条名称,所属类别都相同的记录,系统不会出现异常, 而我不想让业务上完全相同的两条记录能够被重复插入,怎么办?


Re: 主键设计用什么字段类型比较好? 发表时间: Jun 23, 2005 9:15 PM 回复 发表人: 黑色的白色    发表文章: 10 / 注册时间: 2005-06 我习惯用数字
递增的数字
由系统维护
仅代表个人意见


Re: 主键设计用什么字段类型比较好? 发表时间: Jun 30, 2005 11:06 PM 回复 发表人: banq    发表文章: 5064 / 来  自: 上海 / 注册时间: 2002-08 数据类型设计都是细节问题,在J2EE中不重要了。个人意见仅供参考。


Re: 主键设计用什么字段类型比较好? 发表时间: Jul 18, 2005 8:41 PM 回复 发表人: kevin.ma    发表文章: 16 / 注册时间: 2005-07 有必要写个主键生成器比较好嘛!!!
----------------------------------
浅见


Re: 主键设计用什么字段类型比较好? 发表时间: Jul 20, 2005 5:07 PM 回复 发表人: redlly    发表文章: 40 / 注册时间: 2003-07 其实在如同hibernate等框架中已经提供了适应于不同数据库、不同情况的主键生成器,如identity、uuid.hex等方式。我比较常用uuid.hex方式自动产生主键,它是由Hibernate基于128 位唯一值产生算法生成16 进制数值(编码后以长度32 的字符串表示)作为主键,和数据库无关,也不依赖于sequence,缺点是主键只能是32位的字符型,如果要用到数字型就没法用这种生成方式了。我不知道ejb中有没有类似的主键生成方式,产生不依赖于数据库、sequence或者不需要额外的数据库表保存主键生成历史状态的方法。如果有,能否根据数据库表中的不同主键类型(如数字、字符)自动产生唯一的主键。


Re: 主键设计用什么字段类型比较好? 发表时间: Jul 29, 2005 1:49 PM 回复 发表人: kkkk    发表文章: 3 / 注册时间: 2003-04 请问一下redlly,通常设计的实类ID,你是有Sting还是long类型啊,而数据库中是用varchar还是int呢.


Re: 主键设计用什么字段类型比较好? 发表时间: Jul 29, 2005 3:33 PM 回复 发表人: mythmoon    发表文章: 136 / 注册时间: 2005-03 学习中...实际操作中我采用自动+1,不从0起从1000起+1,思考后发觉没做限制可以插入1000以前的标号啊!哈哈!我要赶快去改啊!


________________________________________
被公司封上网了啊(下载东西太多,烧了设备)!解封不久,刚刚来就学东西.


Re: 主键设计用什么字段类型比较好? 发表时间: Jul 31, 2005 12:55 PM 回复 发表人: aill    发表文章: 75 / 注册时间: 2004-06 我是直接用表示数据类型的字符串+System.currentTimeMillis();大家说怎么样?


Re: 主键设计用什么字段类型比较好? 发表时间: Aug 7, 2005 2:02 PM 回复 发表人: JavaUserDL    发表文章: 5 / 注册时间: 2005-07 > 我是直接用表示数据类型的字符串+System.currentTimeMilli
> ();大家说怎么样?

这种方法不太好,如果有并发的话,容易重复。


Re: 主键设计用什么字段类型比较好? 发表时间: Jul 31, 2005 8:20 PM 回复 发表人: redlly    发表文章: 40 / 注册时间: 2003-07 > 请问一下redlly,通常设计的实类ID,你是有Sting还是long类?> 啊,而数据库中是用varchar还是int呢.


我现在的这个系统用的是varchar2(32),映射到类是String.


Re: 主键设计用什么字段类型比较好? 发表时间: Sep 11, 2005 7:19 PM 回复 发表人: rainbowbuaa    发表文章: 1 / 注册时间: 2005-09 序列


Re: 主键设计用什么字段类型比较好? 发表时间: Aug 1, 2005 10:14 PM 回复 发表人: hdcopy    发表文章: 1 / 注册时间: 2005-08 当前项目中使用hibernate框架中的uuid.hex方式自动产生主键,
但出现了一些问题。

基本系统是用java写的,但部分辅助还是用的delphi(C/S结构的),
在delphi写的部分包含大量记录生成,对并发基本无要求,
对速度要求很高,这个时候新记录的主键无法自动产生。

最后是所有delphi系统生成记录用的数据表的主键改用
自动增量了。

因为使用的数据库是oracle,采用的是sequence,相对
sqlserver的要灵活很多,要不是改动太大,很可能整个
项目的数据表都会改。


Re: 主键设计用什么字段类型比较好? 发表时间: Aug 9, 2005 1:39 PM 回复 发表人: myy    发表文章: 8 / 注册时间: 2005-01 > 当前项目中使用hibernate框架中的uuid.hex方式自动产生主?> ,
> 但出现了一些问题。
>
> 基本系统是用java写的,但部分辅助还是用的delphi(C/S结?> 的),
> 在delphi写的部分包含大量记录生成,对并发基本无要求,
> 对速度要求很高,这个时候新记录的主键无法自动产生。
>
> 最后是所有delphi系统生成记录用的数据表的主键改用
> 自动增量了。
>
> 因为使用的数据库是oracle,采用的是sequence,相对
> sqlserver的要灵活很多,要不是改动太大,很可能整个
> 项目的数据表都会改。

hibernate中的uuid.hex如果类似GUID的话(本人不是很了解),以上问题其实并不难解决,可以用两种方法:

1。客户端生成GUID,用Delphi很容易的:
function GetGUID: String;
var
g : TGUID;
begin
Result:=‘‘;
if S_OK=CreateGuid(g) then
Result:=GUIDToString(g);
end;


2。Oracle生成,如:
insert into a_tab (id,name) values (sys_guid(), ‘tom‘);