Oracle认为空字符串为NULL,而SQL Server则不认为NULL-最佳处理方式是什么?
我必须编写一个组件来在Oracle数据库中重新创建SQL Server表(结构和数据)。该组件还必须获取输入到Oracle数据库中的新数据,然后将其复制回SQL Server。
将数据类型从SQL Server转换为Oracle没问题。但是,Oracle和SQL Server之间的关键区别引起了严重的麻烦。 SQL Server认为空白字符串("")与NULL值不同,因此可以将char列定义为NOT NULL,但仍在数据中包含空白字符串。
Oracle认为空白字符串与" NULL"值相同,因此,如果将" char"列定义为" NOT NULL",则无法插入空白字符串。每当" NOT NULL"字符列在原始SQL Server数据中包含空白字符串时,这都会导致我的组件损坏。
到目前为止,我的解决方案是在我的任何镜像Oracle表定义中都不使用NOT NULL
,但是我需要一个更可靠的解决方案。这必须是代码解决方案,因此答案不可能是"使用某某的SQL2Oracle产品"。
我们将如何解决这个问题?
编辑:这是我到目前为止提出的唯一解决方案,它可能有助于说明问题。由于Oracle在NOT NULL列中不允许使用"",因此我的组件可以拦截来自SQL Server的任何此类值,并将其替换为" @"(例如)。
当我向Oracle表中添加新记录时,如果我确实要插入"",我的代码必须写" @",并且当我的代码将新行复制回SQL Server时,它必须拦截" @"。而是写""。
我希望有一种更优雅的方式。
编辑2:是否可能有一个更简单的解决方案,例如Oracle中的某些设置使它像对待所有其他主要数据库一样对待空白字符串?而且此设置在Oracle Lite中是否也可用?
解决方案
我们是否必须在SQL Server系统中允许使用空字符串?如果我们可以向SQL Server系统添加禁止空字符串的约束,则这可能是最简单的解决方案。
我看不到一个简单的解决方案。
也许我们可以将值存储为一个或者多个空白->''
,在Oracle中不是NULL,或者可以通过额外的字段/表和适配器层来跟踪这种特殊情况。
如果要迁移数据,则可能必须用空格代替空字符串。不是很优雅,但可行。这是Oracle的令人讨厌的"功能"。
我的典型解决方案是在SQL Server中添加一个约束,以强制受影响的列中的所有字符串值的长度都大于0:
CREATE TABLE Example (StringColumn VARCHAR(10) NOT NULL) ALTER TABLE Example ADD CONSTRAINT CK_Example_StringColumn CHECK (LEN(StringColumn) > 0)
但是,如上所述,我们无法控制SQL数据库。因此,我们确实有四个选择(如我所见):
- 将空字符串值视为无效,跳过那些记录,提醒操作员并以某种方式记录日志,从而可以轻松地手动更正/重新输入。
- 将空字符串值转换为空格。
- 将空字符串值转换为代码(即" LEGACY"或者" EMPTY")。
- 回滚传输遇到这些列中的空字符串值,然后对SQL Server数据库所有者施加压力以更正其数据。
第四是我的偏爱,但并非总是可能的。我们执行的操作实际上将取决于oracle用户的需求。最终,如果无法对SQL数据库做任何事情,我将向oracle业务系统所有者解释该问题,解释选项和后果,然后由他们做出决定:
注意:我相信在这种情况下,SQL Server实际上表现出"正确"的行为。
它很讨厌,可能会有意想不到的副作用。.但是我们可以只插入" chr(0)"而不是""。
drop table x drop table x succeeded. create table x ( id number, my_varchar varchar2(10)) create table succeeded. insert into x values (1, chr(0)) 1 rows inserted insert into x values (2, null) 1 rows inserted select id,length(my_varchar) from x ID LENGTH(MY_VARCHAR) ---------------------- ---------------------- 1 1 2 2 rows selected select * from x where my_varchar is not null ID MY_VARCHAR ---------------------- ---------- 1