0

我的 webApp 与 2 个数据库服务器 Informix 和 DB2(v9.5 在 localhost 上运行)一起工作,当我使用 informix DB 时,我可以将 null 插入主键(informix DB 处理它并接受 null 并自动增加列(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

4 回答 4

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 插入主键中的任何列的尝试方面同样是正确的。这根本不是你应该被允许做的事情。


回复评论

弗兰克电脑评论说:

奇怪,我的印象是,在将数据加载到具有 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(或者,如果是这样,我做了很长很长的破解过去)。

测试 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.

$

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

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

对于使用 Informix 可以将 NULL 值插入主键列的说法,我比以往任何时候都更加不相信。


更多评论和解释

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

不; 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 用户组)软件存档中获得。那里可用的版本(87.02)接近当前版本(我正在使用 87.06,但我还没有准备好将它发布到世界其他地方,发布时它将是 88.00)。我在 Windows 上不支持它,只是因为我发现 Windows 对开发环境过于不利。不过,它有时也可以在 Windows 上运行。当我发现 Microsoft 发布“Safe C Library”例程时,我的最后一次尝试停止了,但它们提供的例程与标准TR 27341中的例程不同。那个时候我又放弃了。

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

OK. You couldn't specify PRIMARY KEY constraints in that version (those arrived with 5.00, I'm almost certain), but you could create unique indexes on SERIAL columns, etc. To the extent that it is a bug, it has presumably been fixed. It might or might not be fixed in SE 7.26; I'd expect it to be, but haven't demonstrated that it is. It is fixed in 11.70; my tests above demonstrate that.

于 2012-07-11T22:36:33.357 回答
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

于 2012-07-11T17:17:04.320 回答
1

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

insert into table(primarykey,c1, ...) values(null,v1,...).
Try insert into table(c1,...) values(v1,...)
于 2012-07-11T17:17:37.033 回答
1

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

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

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

于 2012-07-11T22:01:47.877 回答