Oracle数据库切换SQLServer数据库解决方案 -- 序列

序列(Sequence)是Oracle数据库中独有的,由于在项目中使用Sequence生成的数据做为主键,所以必须有一套完整可行的转换方案来替代。

涉及到的程序应该改动尽可能的小。

我们应该提供一个跟Oracle数据库取序列方法差不多的函数,来缓解由于数据库不同,导致的额外工作量。

这里我们来看一下微软的解决方案。

使用到的工具为Microsoft SQL Server Migration Assistant 2005 for Oracle(以下简称SSMA)

该工具可以从微软网上免费下载。

 

在源数据库Oracle中建立一个测试数据库TestDB_Seq,里面只有一个序列Seq_Test

在目标数据库SQLServer中建立一个空数据库TestDB_Ssq。

 

之后我们将两个数据库加载到SSMA中 Convert Schema一下

 

image

 

这里我们还可以在Type Mapping 中看到微软对两种不同数据库之间,提供的数据类型解决方案

image

这里,Oracle中的序列最终被生成到dbo的Sequence Emulations中

image

 

 

右键SQLServer数据源中的SEQ_TEST,选择Synchronize with Database

image

点击OK,就完成了使用SSMA对Sequence的移植。

 

下面我们来看看SQLServer中到底发生了什么。

image

在表里面,对应的生成了一个名为$SSMA_seq_SEQ_TEST的表。

表中只有一个ID字段,类型为numeric(38,0),非空,自增

同时在存储过程中生成了一个名为$SSMA_sp_get_nextval_SEQ_TEST的存储过程。

 

 

执行该存储过程,通过参数curval,我们就可以每次得到一个不同的增量。

以下为存储的内容和执行的结果。

 

1  set  ANSI_NULLS  ON
2  set  QUOTED_IDENTIFIER  ON
3  go
4 
5  ALTER   proc   [ dbo ] . [ $SSMA_sp_get_nextval_SEQ_TEST ]   @curval  numeric( 38 , 0 ) out  as   insert   [ dbo ] . [ $SSMA_seq_SEQ_TEST ]   default   values   set   @curval   =   scope_identity ()

 

 

image

 

好吧,文章就到这里,相信你也看到了微软对不同数据库之间转移的解决方案,希望上面存储过程里面的代码,会对你有所帮助。

 

BTW:终于明白前辈们为什么这样写代码

public User BuildUser()
{
    User.ID = getSEQ("SEQ_USer");
    User.Name = "Gavin";
}

 

当时天真的认为,这样生成实体的话,在Insert操作时候,需要连接两次数据库,一次用来读取ID,另一次执行Insert操作。

不如不给User.ID赋值,直接在Insert语句中使用SEQ_User.nextval。惭愧,惭愧!

转载于:https://www.cnblogs.com/CGavin/archive/2010/04/26/1721502.html

<think>我们正在解决PostgreSQL到Oracle数据传输乱码问题,尽管两边字符集都是UTF-8。 根据引用[3]和引用[4]的信息,PostgreSQL和Oracle虽然都使用UTF-8字符集,但可能存在一些不兼容的情况,特别是当处理多字节字符(如中文)时。 引用[4]中提到,使用orafce的substrb函数在PostgreSQL中截取多字节字符时可能产生乱码,这说明即使字符集相同,底层处理方式可能有差异。 可能的原因: 1. 客户端连接设置:在数据传输过程中,客户端连接(如JDBC)的字符集设置可能不正确。 2. 数据库字符集细节:虽然都是UTF-8,但具体实现可能有差异(如Oracle的AL32UTF8和PostgreSQL的UTF8),或者排序规则不同。 3. 数据传输工具:如果使用ETL工具或自定义程序,可能在传输过程中没有正确设置字符集。 解决方案: 1. 检查客户端连接字符集设置: 在连接Oracle和PostgreSQL的JDBC连接字符串中,确保指定了正确的字符集。 例如,对于Oracle,可以设置:`jdbc:oracle:thin:@host:port:service?useUnicode=true&characterEncoding=UTF-8` 对于PostgreSQL,可以设置:`jdbc:postgresql://host:port/database?characterEncoding=utf8` 但是,根据引用[5],在MySQL的JDBC连接中,我们看到了设置字符集的参数,同样在Oracle和PostgreSQL的JDBC驱动中也有类似参数。 2. 确认数据库字符集的细节: -Oracle中,查询:`SELECT * FROM nls_database_parameters WHERE parameter LIKE '%CHARACTERSET%';` 应该看到NLS_CHARACTERSET为AL32UTF8(推荐)或UTF8(注意Oracle的UTF8是旧版,最多支持3字节,而AL32UTF8支持4字节)。 - 在PostgreSQL中,查询:`SHOW server_encoding;` 应该为UTF8。 如果Oracle使用的是UTF8(而不是AL32UTF8),那么它可能不支持某些Unicode字符(如emoji),但一般情况下中文字符是支持的。 3. 检查传输过程中的编码转换: 如果使用ETL工具(如Kettle),确保在每一步都指定了字符集为UTF-8。 如果使用程序(如Java),确保在读取和写入时都指定了字符集为UTF-8。 4. 测试直接查询: 在PostgreSQL中,使用`psql`命令行工具,执行`\encoding`确保是UTF8,然后查询包含中文的数据,看是否正常。 在Oracle中,同样用SQL*Plus或SQL Developer查询,看是否正常。 5. 如果以上都正确,问题可能出现在特定函数或操作上(如引用[4]中的substrb问题),在传输过程中避免使用此类函数,或者确保使用正确的函数。 6. 如果问题仍然存在,考虑在传输过程中使用二进制格式(如PostgreSQL的bytea)或者Base64编码,然后在Oracle端解码,但这会增加复杂性。 根据引用[3]的提示,更改PostgreSQL的字符集时要注意兼容性,但这里我们不更改字符集,而是确保传输过程正确。 步骤总结: 1. 确认两端数据库的字符集(如上所述)。 2. 检查JDBC连接字符串(或使用的其他连接方式)中的字符集设置。 3. 在程序或ETL工具中,确保所有步骤都使用UTF-8编码。 4. 测试小量数据,特别是包含多字节字符的数据,观察乱码是否出现。 如果问题仍然存在,请提供更多信息,例如: - 你使用的数据传输工具或方法(如JDBC、ODBC、ETL工具等)。 - 具体的乱码表现(如整个字符串乱码,还是部分字符乱码)。 - 数据库版本和JDBC驱动版本。 注意:引用[1]和引用[2]提到了一些历史字符集问题,但这里我们假设两边都是UTF-8,所以重点检查连接设置和传输过程。 希望这些步骤能帮助你解决问题。</think>### PostgreSQL 到 Oracle 数据传输乱码问题解决方案(UTF-8 环境) #### 问题分析 尽管两边数据库字符集均为 UTF-8,乱码通常由以下原因引起: 1. **连接层字符集不匹配** JDBC/ODBC 连接参数未显式声明 UTF-8 编码(引用[5])。 2. **字符集实现差异** PostgreSQL 的 `UTF8` 与 Oracle 的 `AL32UTF8` 存在字节处理差异(引用[4])。 3. **客户端工具配置错误** 数据传输工具(如 ETL 工具)未正确处理编码转换。 4. **特殊字符处理异常** 多字节字符(如中文)在函数处理时被截断(引用[4])。 --- #### 解决步骤 ##### 1. **确认数据库字符集** - **PostgreSQL** ```sql SHOW server_encoding; -- 应为 UTF8 ``` - **Oracle** ```sql SELECT * FROM nls_database_parameters WHERE parameter IN ('NLS_CHARACTERSET', 'NLS_NCHAR_CHARACTERSET'); -- NLS_CHARACTERSET 应为 AL32UTF8 ``` > 💡 若 Oracle 使用 `UTF8`(非 `AL32UTF8`),需重建库为 `AL32UTF8`(引用[2])。 ##### 2. **配置连接参数** 在数据传输工具(如 JDBC)中显式指定 UTF-8: ```java // PostgreSQL JDBC 示例 jdbc:postgresql://host/db?characterEncoding=utf8&stringtype=unspecified // Oracle JDBC 示例 jdbc:oracle:thin:@host:port:SID?useUnicode=true&characterEncoding=UTF-8 ``` > ✅ 关键参数:`characterEncoding=utf8`(引用[5])。 ##### 3. **处理多字节字符** - 避免在传输过程中使用 `substrb()` 等字节操作函数(引用[4])。 - 改用字符安全函数: ```sql -- PostgreSQL 端使用 substr() SELECT substr('中国123', 2, 2); -- 返回"国1" ``` ##### 4. **检查客户端环境** - 确保操作系统 Locale 支持 UTF-8: ```bash # Linux/Mac echo $LANG # 应为 zh_CN.UTF-8 或 en_US.UTF-8 ``` - Windows 使用 `chcp 65001` 切换控制台编码。 ##### 5. **测试数据流** 通过二进制格式验证编码: ```sql -- PostgreSQL 测试 SELECT '中文测试'::bytea; -- 应显示 UTF-8 字节序列:\xe4b8ad... -- Oracle 测试 SELECT RAWTOHEX(UTL_I18N.STRING_TO_RAW('中文测试')) FROM dual; -- 结果应与 PostgreSQL 的字节序列一致 ``` ##### 6. **使用中间格式** 若直接传输失败: 1. 将 PostgreSQL 数据导出为 UTF-8 CSV: ```sql COPY table TO '/path/data.csv' WITH (FORMAT CSV, ENCODING 'UTF8'); ``` 2. 在 Oracle 端使用 `SQL*Loader` 导入: ```sql LOAD DATA CHARACTERSET UTF8 INFILE 'data.csv' INTO TABLE table... ``` --- #### 常见错误排查 - **错误提示**:`ERROR: new encoding (UTF8) is incompatible` 原因:模板数据库与目标库字符集冲突(引用[3])。 方案:创建新库时指定 `TEMPLATE template0`。 - **乱码集中在特定字符**: 检查是否为 4 字节 Unicode 字符(如 emoji),Oracle 的 `UTF8` 字符集不支持,需升级到 `AL32UTF8`(引用[2])。 > 📌 **终极方案**:若所有尝试失败,使用十六进制中间表暂存数据,避免字符解释差异。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值