2010-10-11 222 views
16

我在使用TSQL在博客,文章,书籍,论坛,SO等文件中创建表格的脚本中经常看到“not null primary key”。为什么在TSQL中使用“not null primary key”?

例如,BING会给出630,000个结果)如果要搜索针对“非空”靠近“主键”的“SQL Server”:
http://www.bing.com/search?q=%22not+null%22+NEAR+%22primary+key%22+%22sql+server%22&go=&form=QBRE&filt=lf

我始终认为“NOT NULL”主键,至少在SQL Server中定义的不可分割的一部分
我尝试在SQL Server中创建一个带有和不带“NOT NULL”的主键的表,但无法掌握可能的差异。

即使在快速(短)插图中,为什么所有人都使用“NOT NULL”创建主键?


更新:
如何NULL识别任何东西,或是唯一的(以及防止多个空值,如果一个被允许)?它是未指定的,缺少的,不适用的值

我的问题也暗示了子问题:
如果为PK定义了“NOT NULL”,为什么UNIQUE没有被指定?
什么是PK的定义。它是唯一约束+不是NULL或唯一索引(那么为什么不是NULL)?
Plz给我链接到它的msdn文档。

UPDATE2: @Damien_The_Unbeliever

为什么没有 “NOT NULL” 同义词?

CREATE TABLE T3 
(
    PK int -- NOT NULL commented out 
    , nonPK int -- to double-check my sanity 
    , constraint PK_vgv8 PRIMARY KEY (PK) on [PRIMARY] 
) 

仍然不允许null捐赠:


  • 微软SQL Server Management Studio中


    没有行被更新。

    第2行中的数据未提交。 错误来源:.Net SqlClient数据提供程序。 错误消息:无法将值NULL插入列'PK',表'TestData.dbo.T3';列不允许有空值。 INSERT失败。

    该声明已终止。

    纠正错误并重试或按ESC取消更改。


    OK帮助


UPDATE3:
此,概念和术语的定义,可能会出现不切实际的滋扰。
关于基本概念的一些错误陈述(在沟通/讨论期间的其他意见中)有些被误认为是白痴并且在专业互动和沟通中造成障碍。

我忘了说,NOT NULL是由SSMS为PK编写的脚本!

+0

如果可以唯一标识一条记录,你将如何找到一条记录????? – leppie 2010-10-11 11:24:26

+0

@InSane,我对GOOGLE非常习惯,但是BING碰巧找到了GOOGLE没有做的结果(尤其是删除网页的缓存)。此外,当我只用英文搜索时,google.com重定向到google.ru会给我很多西里尔语(俄语)的结果。 – 2010-10-11 11:31:28

+1

@leppie,我不明白, “PK = UNIQUE + NOT NULL” 在SQL Server中,PLZ发表您的答案 – 2010-10-11 11:33:11

回答

14

被修改为清楚起见

根据该SQL说明书中,主键不能包含NULL。这意味着用“NOT NULL PRIMARY KEY”或“PRIMARY KEY”来装饰列应该做同样的事情。但是您依照SQL标准正确依赖所讨论的SQL引擎。作为一个例子,由于早期的bug,SQL Lite没有正确地实现标准并且允许非整数主键的空值(参见sqlite.org/lang_createtable.html)。这意味着(至少)SQLLite这两个语句执行两个不同的事情。由于“NOT NULL PRIMARY KEY”清楚地指示了意图,并且即使主键被删除也继续在非空值之前生效,所以这应该是优选的语法。

+0

我问了一下PK无“NOT NULL,不是‘NOT NULL’无PK我不能设法在PK场NULL以任何可能的方式 – 2010-10-11 11:49:34

+0

@ vgv8:。很抱歉的混乱,要明确我是说,你可以只是“主键”或“NOT NULL PRIMARY KEY”,他们会都做同样的事情。但如果你删除“主键”,第一条语句将然后允许列允许空值,而其他止跌换句话说,只有第二个真正描述了期望的意图,而第一个正在利用snytax捷径,我相信他们不会,但是如果MS更改SQL以允许主键中存在单个空值那么这两种行为是完全不同的。 – 2010-10-11 12:50:50

+0

我建议忽略手续。像@保罗哈德菲尔德,如果没有其他人参与讨论。我upvoted你的答案更多的在评论给出的链接,有助于深入了解和揭示了一些定义和方法,比主要的自己摇摆。我也发布了子问题http://stackoverflow.com/questions/3906811/why-to-permit-null-in-primary-key。有一些基本的概念和原则,我认为这应该很常见,并且针对不同RDBMS的实现 – 2010-10-11 14:00:18

1

它不是语法要求的,因为如果没有为主键列指定,无论其他列的默认设置如何,这都将是默认设置。

SET ANSI_NULL_DFLT_ON ON /*Set default for columns to allow NULL if not specified*/ 

CREATE TABLE #t 
(
i INT PRIMARY KEY, 
j INT 
) 

SELECT name,is_nullable 
FROM tempdb.sys.columns 
WHERE object_id=object_id('tempdb..#t') 


INSERT INTO #t VALUES (1,NULL) /*Succeeds as j allows NULL*/ 

INSERT INTO #t VALUES (NULL, 1)/*Won't succeed as column doesn't allow nulls*/ 

DROP TABLE #t 
+1

+1中支持我的问题。我真的在发布之前运行过这样的脚本。尽管如此,我还是想明确定义和解释原因。这是基本的概念,我不想在向别人回答这样简单的基本问题时从我小丑身上制造出来 – 2010-10-11 12:40:14

0

所有主键都意味着它是表的标识符,因此它是唯一的定义。唯一并不意味着不为空,所以如果你有要求主键不能为空,你必须明确指定。如果你允许null,你只是说在列中有一个空值是可以的,但是你只允许有一个,因为它必须是唯一的。

+0

您不必明确地指定它。这是通过使它成为PK来暗示的。 – 2010-10-11 11:51:22

8

以下:

CREATE TABLE T1 (
    T1ID int not null primary key 
) 

真是以下简写:

CREATE TABLE T1 (
    T1ID int not null, 
    constraint <system generated name> PRIMARY KEY (T1ID) on [PRIMARY] 
) 

列定义是真正从约束定义完全分离。速记隐藏了两个单独定义的事实。 (当然,如果您使用长手形式,您可以执行诸如跨多列定义主键等)。

编辑,以响应更新。不,你仍然不能在主键中有一个可为空的列。但是,鉴于在create table语句中指定每列的可空性是正常的,忽略它就会感到很奇怪(即使PRIMARY KEY约束隐含/要求它)。

CREATE TABLE T1 (
    T1ID int, 
    constraint <system generated name> PRIMARY KEY (T1ID) on [PRIMARY] 
) 

创建完全相同的表作为前面的代码示例。因此,明确指定列的“非空”性是对结果的更明确确认,而不是要求。

最后,你会发现它在示例代码中经常发生的,因为人们已经开发出自己的数据库,然后使用内置的SQL工具从他们的数据库生成的脚本 - 脚本工具总是把一切都作了明确规定。

+1

我没有问我是否可以。我问为什么除了由SSMS定义的“主键”TSQL定义外,还坚持使用“NOT NULL”脚本 – 2010-10-11 16:05:01

2

我不知道任何允许在PRIMARY KEY约束中使用可空列的DBMS。 SQL标准指定PRIMARY KEY约束中的列不能为空。

在关系模型中,候选键由唯一值组成,而不是空值。这是SQL的一个特性,可以在UNIQUE约束中可选地使用可为空的列。该功能可能会导致很多数据质量问题。我强烈建议您避免在UNIQUE约束中使用可为空的列。如有必要,为非空值创建一个新表,并将UNIQUE约束放在该表上。

1

关于MYSQL有趣的是行为是当你传递一个NULL(或0)值的primary key auto_increment领域非常好。

说你有

create table Users(

    userId int primary key auto_increment 

) ; 

insert into users(userId) values (null) ; -- insert OK 
select * from Users ; -- Shows 1 

所以,如果你传递0或NULL到auto_increment场,它只是选择一个可用值。

如果你把关闭auto_increment财产,插入到主键字段与NULL失败,因为一个主键不能为空,是错误。所以PRIMARY KEY NOT NULL上的NOT NULL至少在MySQL中是隐含的。

0

我似乎是想在另一个方向来解释为什么不空,主键也被接受的一个字段时,主键本身隐含抱着不为空。

让我们说我们有表table1,这意味着它将保存它的值来存储2维数据。如果我创建一个只有一个字段的表格,这是可以接受的,但它在真实物体世界中的实时使用情况如何?我相信这将是一维表格,只是存储一个领域的数据导致无信息。并保持该字段接受空值是没有意义的。

现在,让我们假设,我们定义了一个表2场,这意味着在充满适当的数据,我们可以从各行提取有用信息。

使这些2个字段接受Null值没有任何意义想到,如果我们要推动垃圾或期待COUNT(*)应导致额外的行。如果我们希望使用具有良好的基本概念RDBMS规范化表

所以,我要说的是,将不为空是2周的Fileds强制性ATLEAST。在考虑表是否需要主键作为约束之前,我们总是将teh字段定义为非空。此外,如果需要使用主键,并注意,你可能会随时抛弃它,但不是'非空'

如果我们确信我们不会放弃主键,只使用主键,否则都不为空和主键。

这一切都取决于用法,正如我所说的,必须达到基本的表格定义和Codd的规则才能实现良好的数据库。

相关问题