当我从SQL Server导入tinyint列到Oracle 10g时,为什么会得到负值?

Dan*_*now 0 sql-server dblink character-encoding oracle10g

我最近遇到了一个问题,我们正在运行一个数据迁移脚本,以通过Oracle DBLink将数据从SQL Server迁移到Oracle 10g。一切正常,直到我们在生产Oracle环境中运行脚本为止。对于在SQL Server中定义为tinyint的某些列,我们发现SQL Server数据库中大于127的值现在为负值(比原始值小256)。为什么该脚本在开发和测试数据库中起作用,而在生产中却不起作用?

Dan*_*now 5

我之所以要回答自己的问题,是因为Google和StackOverflow无法帮助我解决这一问题,至少在我使用的搜索字词方面没有帮助。在开始研究时,我们发现SQL Server将tinyint视为无符号字节(0到255),而Oracle则将其视为有符号字节(-128到127)。但是我们将其导入到NUMBER(3)列中是合适的。出于某种原因,编写数据迁移脚本的人需要使用Oracle的to_number函数来读取SQL Server tinyint列。因此,如果您在开发和测试环境中运行此查询,则在第二列中返回了一些奇怪的字符,但在生产环境中的两列中都返回了相同的负数。

SELECT to_number("SomeTinyIntColumn"), "SomeTinyIntColumn"
FROM MySQLServerDBLink@mydomain.com
Run Code Online (Sandbox Code Playgroud)

我们最终发现,它在开发和测试环境中起作用的原因是那里的字符集是UTF-8,但在生产中却是西欧的8位字符集:

SELECT value$ FROM sys.props$ WHERE name = 'NLS_CHARACTERSET';
-- Dev and Test: AL32UTF8
-- Prod: WE8ISO8859P1
Run Code Online (Sandbox Code Playgroud)

因此,如果您正在为Oracle数据库使用UTF-8字符集,那么似乎可以通过DBLink将SQL Server tinyint列读取为单个UTF-8字符并将其转换为Oracle NUMBER(3)列。如果DBLink自己处理了转换(这使不必要的to_number转换),那将是很好的选择,但是似乎它并不真正知道如何处理SQL Server tinyint

希望有一天能对其他人有所帮助!