如何在DB2中的主键中插入空值?

时间:2012-07-11 17:10:38

标签: database db2 informix

我的webApp使用2个DataBase服务器Informix和DB2(v5.5在localhost上运行),当我使用informix DB时,我可以将null插入主键(informix DB处理它并接受空值并自动增加列( Serial8))但是当我切换到使用DB2时它不起作用并且这个错误产生了(DB2 SQL错误:SQLCODE = -407,SQLSTATE = 23502,SQLERRMC = TBSPACEID = 2,TABLEID = 280,COLNO = 0,DRIVER = 3.50 .152,sqlCode = -407)看起来DB2不允许主键(BigInt)的空值,那么如何强制DB2允许主键空值?总而言之,我希望DB2允许我为此列插入空值,并在每次插入时自动增加其中的值

这是创建表格的脚本:

CREATE TABLE corr.CORRESPONDENCE  (
this is the specified col---->CORR_ID BIGINT NOT NULL,
    CORR_NAME VARCHAR(255) NOT NULL,
    CORR_NO VARCHAR(255),
    CREATE_DATE_TIME TIMESTAMP NOT NULL,
    DELIVERY_DATE_TIME DATE,
    NO_OF_ATTACH INTEGER,
    SITE_ID VARCHAR(20),
    DELIVERY_ID VARCHAR(20),
    CREATE_USER BIGINT NOT NULL,
    SECURITY_ID BIGINT,
    DELIVERY_BY VARCHAR(20),
    WORKFLOW_ID BIGINT
)
DATA CAPTURE NONE ;

ALTER TABLE corr.correspondence ADD CONSTRAINT u143_159 PRIMARY KEY 
(corr_id)  ;

4 个答案:

答案 0 :(得分:2)

哪个版本的Informix?表格的架构是什么?什么是INSERT语句?您使用哪种API来访问Informix?运行客户端代码的平台是哪个?运行数据库服务器的平台是什么?

我不相信你可以在Informix中的类似SERIAL的列中插入空值。您的表上是否有主键约束,或者只是没有NOT NULL且没有PRIMARY KEY约束的SERIAL8列?您不能将NULL直接插入SERIAL8列(也不能通过推理,插入SERIAL或BIGSERIAL列)。

演示(在RHEL 5 Linux x86 / 64上使用Informix 11.70.FC6的开发版本;客户端基于ESQL / C,客户端和服务器都在同一台机器上):

SQL[1910]: begin;
SQL[1911]: create table t1(s8 serial8 not null, v1 char(8) not null);
SQL[1912]: insert into t1(s8, v1) values(null, "works?");
SQL -391: Cannot insert a null into column (t1.s8).
SQLSTATE: 23000 at /dev/stdin:6
SQL[1913]: rollback;
SQL[1914]: begin;
SQL[1915]: create table t1(s8 serial8 primary key, v1 char(8) not null);
SQL[1916]: insert into t1(s8, v1) values(null, "works?");
SQL -703: Primary key on table (t1) has a field with a null key value.
SQLSTATE: IX000 at <<temp>>:2
SQL[1917]: rollback;
SQL[1918]: create table t1(s8 serial8, v1 char(8) not null);
SQL[1919]: insert into t1(s8, v1) values(null, "works?");
SQL -391: Cannot insert a null into column (t1.s8).
SQLSTATE: 23000 at <<temp>>:2
SQL[1920]: drop table t1;
SQL[1921]:

打扰了,我忘了在1917年之后重启交易!

这表现得完全正常;不应该允许您将NULL插入SERIAL8(或SERIAL或BIGSERIAL)列。您可以在这些列中插入零,并自动分配新值。但是你不能也不应该在列中插入NULL。

DB2拒绝尝试将NULL插入主键的任何列中也是正确的。它根本不是你应该被允许做的事情。


回答评论

Frank Computer评论道:

  

奇怪的是,我的印象是,当将数据加载到带有SERIAL列的表中时,如果我没有为SERIAL列提供值,它会在插入期间将NULL转换为零,就像加载一样数据包含零?

     

另外,使用ISQL Perform,当我在包含SERIAL列的表中插入新行时,我不会为SERIAL列提供值,但Perform会显示零(0)并且在点击Escape之后,它将它转换为下一个最高的INT值!

我的反应是:

  
      
  • LOAD由客户端中一个复杂的子程序完成,该子程序用于处理数据,它可以/将处理SERIAL列的NULL。

  •   
  • 使用ISQL,Perform在数据输入期间显式强制执行0并报告插入的值;再次,客户端代码正在防止错误。

  •   
     

这就是为什么知道用于演示问题或功能的重要性的原因。现在我必须使用DB-Access进行LOAD和NULL演示...我不认为我的SQLCMD程序在LOAD期间修复了SERIAL列的NULL(或者,如果是的话,我做了那个hack很久很久以前)。

测试DB-Access(这次是在Mac OS X 10.7.4上从IDS 11.70.FC2),用:

xx.unl

|data for row 1|1|
|data for row 2|2|

xx.sql

BEGIN;
CREATE TABLE load_null(s8 SERIAL8 PRIMARY KEY, v32 VARCHAR(32) NOT NULL, i INTEGER NOT NULL);
LOAD FROM "xx.unl" INSERT INTO load_null;
ROLLBACK;

数据库访问输出

$ dbaccess stores xx

Database selected.


Started transaction.


Table created.


  703: Primary key on table (load_null) has a field with a null key value.

  847: Error in load file line 1.
Error in line 3
Near character position 41

Transaction rolled back.


Database closed.

$

这并不支持将SERIAL8列的DB-Access映射NULL映射为零&#39;假设。这是SERIAL8而不是简单的SERIAL,但当我将SERIAL8更改为SERIAL时,我得到了同样的错误;与BIGSERIAL同上。我没有ISQL,而不是Mac上的DB-Access(懒惰;我刚刚做了端口,但没有安装它,因为它不是官方的,而且它不是GA),并且两个LOAD命令之间可能存在差异,但相对不太可能。

在相同的SQL和数据(卸载)文件上测试SQLCMD,我收到相同的错误消息。

我更不相信可以使用Informix将NULL值插入主键列。


更多评论和解释

  

虽然我知道LOAD不是Informix SQL本机语句,但我认为它被添加到SE(标准引擎)和OL(OnLine)引擎中?

没有; LOAD语句由客户端程序中的代码处理:DB-Access,ISQL,I4GL,DB-Load,DB-Import。在每种情况下,语句由客户端识别和解析,转换为准备好的合适的INSERT语句,然后客户端读取并解析数据文件,并一次一行地将数据发送到服务器(逻辑上;实际上; ,有一个INSERT游标,它允许你对插入进行批处理操作。)

  

或者LOAD语句实际上是调用SE / OL或onload.exe中的DBLOAD.EXE实用程序吗?

否:LOAD语句不涉及DB-Load,也不涉及ON-Load。

  

SQLCMD的来源是否可用?如果是这样,我可以转储dbaccess并将其替换为SQLCMD的精简版本吗?

是。它可以从IIUG(国际Informix用户组)Software Archive获得。那里可用的版本(87.02)接近当前版本(我使用的是87.06,但是我还没有准备好将它发布到世界其他地方,并且当它是88.00时它将是88.00发布)。我不会在Windows上支持它,只是因为我觉得Windows在开发环境中太敌对了。不过,它有时会在Windows上运行。当我发现微软发布了“安全C库”时,我的最后一次尝试就停止了。例程,但它们提供的例程与标准TR 27341中的例程不同。那时我又放弃了。

  

我刚刚确认我的ole SE-4.10 clunker在插入带有LOAD的加载文件时接受SERIAL列的NULL值。

行。您无法在该版本中指定PRIMARY KEY约束(那些以5.00到达,我几乎可以肯定),但您可以在SERIAL列上创建唯一索引等等。如果它是一个bug,它就是大概是固定的。它可能会或可能不会在SE 7.26中修复;我期待它,但没有证明它是。它固定在11.70;我上面的测试证明了这一点。

答案 1 :(得分:1)

您不能将空值插入主键DB2。相反,您需要修改插入查询以插入新密钥,或者只是不将其包含在Insert语句中并让数据库自动处理它...

如果我们知道插入查询(或至少部分插入查询),这将有所帮助。我们可以就如何纠正它提供更好的指导。但是,请猜测问题的根源:

假设表格如下:

ID INTEGER NOT NULL GENERATED DEFAULT (START WITH 1, INCREMENT BY 1)
SomeOtherField VARCHAR(50)

您的陈述应该是:

Insert into MyTable (SomeOtherField) Values ('somevalue')

而不是

Insert into MyTable (ID, SomeOtherField) Values (null, 'somevalue')

Insert into  Values (null, 'somevalue')

可以在此处找到类似的问题和更多信息:http://www.dbforums.com/db2/669352-autoincrement-fields.html

答案 2 :(得分:1)

您应该尝试以下SQL语句来解决您的问题:

insert into table(primarykey,c1, ...) values(null,v1,...).
Try insert into table(c1,...) values(v1,...)

答案 3 :(得分:1)

使用Informix SERIAL列,您可以插入零(0),它会自动将其转换为下一个可用的最大整数值。您也可以插入特定的整数值,只要它尚未使用,因为SERIAL列具有唯一约束。

你的问题很模糊。主键也可以是非SERIAL数据类型并接受NULL值。如果是这种情况,我建议你创建一个代理键(通常是一个自动增量列),以便唯一地标识每一行。

您使用的主键是什么以及将NULL插入主键的原因是什么?是因为在您插入行时,该值未知,但稍后会更新具有已知值?.. NULL作为主键往往会使事情无法正常工作,尤其是在连接到子表中的外键时。如果您的主键没有唯一约束,那意味着您可能有多个行具有重复的NULL值作为其主键..在任何数据库中都不是一个好主意,包括DB2!