哪个版本的 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 值!
我的第一反应是:
这就是为什么了解使用什么来演示问题或功能很重要的原因。现在我必须使用 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.