在oracle中,每个表都必须有一个列具有惟一性,比如rowid,在access中也要求每个表必须有一个惟一列,可是在sql server中为何就没有呢?
---------------------------------------
据说rowid是惟一的标志,是物理层次的,oracle查找时就是根据这个列的.可是为何sql server中可以充许所有列都可以重复呢?
从这一点上来说,好象连access都比sql server严谨些.
当然是我不理解才这样说的.可是我确实不解,为何sql server中就不要求每个表都必须有一个惟一性的列呢?(就象access那样,没有惟一的列,保存时它会自动增一个自增列.)
谢谢指教先.
---------------------------------------
据说rowid是惟一的标志,是物理层次的,oracle查找时就是根据这个列的.可是为何sql server中可以充许所有列都可以重复呢?
从这一点上来说,好象连access都比sql server严谨些.
当然是我不理解才这样说的.可是我确实不解,为何sql server中就不要求每个表都必须有一个惟一性的列呢?(就象access那样,没有惟一的列,保存时它会自动增一个自增列.)
谢谢指教先.
-------------------
谢谢,我知道是可以设主键的.
可是我想问的是:
在access或oracle中,如果一个表中没有主键,就必须有一个自增列才行.可是在sql server中,如果一个又没有主键,也没有自增列,也是可以保存的.
这样就会存在这种情况,即多行完全相同.没有任何一个字段能标识这一行.
可是这种情况在access中或oracle中是绝对不可能出现的.
谢谢再.
--------------------
呵呵,谢谢,我知道这只是我的问题,我就是不会才问的呀,我不是学sql server不好,这是世界三大数据库之一,只是我不明白其中的道理,为何有这种不同呢?
讲讲道理吧.老大.
---------------------------------------------In Access,the identity column is not indispensable too,You can also save the structure of table without it.
是我理解错了。
可是我不解,象存在多条记录完全相同的情况下,如何发送一条语句对其中一条进行更新呀。
好象这种情况只能全部更新,而无法用语句只更新其中一条吧。
好象这种情况只能全部更新,而无法用语句只更新其中一条吧。
------------------
不是的,可以单条更新!
Set RowCount 1
Update A
Set ...
From ...
Set RowCount 0
好象这种情况只能全部更新,而无法用语句只更新其中一条吧。
------------------------------------
Just like what you saidIt can't be distinguish from each for DATA BASE SOFT in this situation
解决的办法通常是为表增加IDENTITY自动增量标识列,每插入一行就由系统生成一个新的ID.IDENTITY列的特点是不能修改已生成的值,但可以将SET IDENTITY_INSERT 设置为ON后由用户为该列插入指定值,这种情况下就存在IDENTITY列值重复的可能,所以通常将该列设置UNIQUE约束(也可以设置为主键,但本人倾向于设置UNIQUE约束),防止该列的值重复,以唯一标识每一行.
另外,SQLSERVER还提供了另外一种唯一标识每一行的方法,就是将某个列的数据类型设置为uniqueidentifier,并且将其默认值设为newid(),这样,每插入一行,系统就为该行生成一个全球唯一标识符,以保证行唯一,这种保证行唯一的方式通常应用于复制中.
当使用ADO以行缓冲模式添加新记录时,如果表有IDENTITY列,则默认状态下ADO会为新行的IDENTITY列返回SQLSERVER的@@IDENTITY全局变量值,然后依据该值来刷新ADO新添加记录的列(如显示默认值),类似于这样一个过程:
oRecordSet2.open(select * from table where id = @@identity)
oRecordSet1.Fields(0).value = oRecordSet2.Fields(0).value
......
而且,使用ADO新添加的记录若要刷新,只能通过IDENTITY列,而不能通过其它列,例如uniqueidentifier列,因为新行中只有IDENTITY列能够返回值(@@IDENTITY全局变量值),其它列都是空值.
但是,因为@@IDENTITY返回的是最后插入表的IDENTITY列值,所以,当插入新行的表有INSERT触发器,并且INSERT触发器中向另一个含有IDENTITY列的表(假设为B表)中插入新行时,@@IDENTITY中返回的将是B表新插入行的ID值,这会导致大麻烦.可以在企业管理器中来测试一下:
1.首先在查询分析器中创建ta,tb二个表,ta表中的INSERT触发器中向tb表插入新行.
if object_id('ta') is not null
drop table ta
if object_id('tb') is not null
drop table tb
----创建测试表
create table ta(id int identity,num int,guid uniqueidentifier default newid())
create table tb(id int identity,num int)
----为b表插入3行,id自动生成,分别1,2,3
insert into tb default values
insert into tb default values
insert into tb default values
select * from tb
go
----为a表创建INSERT触发器,每向ta表插入一行,就同时向tb表也插入一行
create trigger tri_insert_test on ta
for insert
as
insert into tb default values
go
2.在企业管理器中打开ta表,向第一行的num中随便输入个整数,再向下移动光标,会发现第一行的id变为4而不是1(另外请注意,只有id列返回值,其它列均为NULL,即使设置了默认值).数值4正是tb的新行的id值!这时,在查询分析器中执行一下select * from ta,发现第一行的id为1而不是4.
接着继续测试:
在企业管理器中修改第一行的num,再将光标移出第一行,会导致错误"无法为更新定位行"错误(可按ESC取消修改),因为在ta表中没有找到id=4的行.
所以,为含有IDENTITY列的表设置INSERT触发器时一定要注意这一点.