首先,感谢Stack Overflow上的所有人过去,现在和将来的帮助。你们已经把我从灾难中拯救出来(我自己的设计和其他方面)太多次了。
本期是我公司决定从Microsoft SQL Server 2005数据库过渡到PostgreSQL 9.4的一部分。我们一直在关注Postgres wiki(https://wiki.postgresql.org/wiki/Microsoft_SQL_Server_to_PostgreSQL_Migration_by_Ian_Harding)上的注释,这些是我们对相关表格所遵循的步骤:
在Windows客户端上下载表数据:
bcp "Carbon.consensus.observations" out "Carbon.consensus.observations" -k -S [servername] -T -w
复制到Postgres服务器[运行CentOS 7]
在Postgres服务器上运行Python预处理脚本以更改编码并清理:
import sys
import os
import re
import codecs
import fileinput
base_path = '/tmp/tables/'
cleaned_path = '/tmp/tables_processed/'
files = os.listdir(base_path)
for filename in files:
source_path = base_path + filename
temp_path = '/tmp/' + filename
target_path = cleaned_path + filename
BLOCKSIZE = 1048576 # or some other, desired size in bytes
with open(source_path, 'r') as source_file:
with open(target_path, 'w') as target_file:
start = True
while True:
contents = source_file.read(BLOCKSIZE).decode('utf-16le')
if not contents:
break
if start:
if contents.startswith(codecs.BOM_UTF8.decode('utf-8')):
contents = contents.replace(codecs.BOM_UTF8.decode('utf-8'), ur'')
contents = contents.replace(ur'\x80', u'')
contents = re.sub(ur'\000', ur'', contents)
contents = re.sub(ur'\r\n', ur'\n', contents)
contents = re.sub(ur'\r', ur'\\r', contents)
target_file.write(contents.encode('utf-8'))
start = False
for line in fileinput.input(target_path, inplace=1):
if '\x80' in line:
line = line.replace(r'\x80', '')
sys.stdout.write(line)
执行SQL加载表:
COPY consensus.observations FROM '/tmp/tables_processed/Carbon.consensus.observations';
问题是COPY命令失败并出现unicode错误:
[2015-02-24 19:52:24] [22021] ERROR: invalid byte sequence for encoding "UTF8": 0x80
Where: COPY observations, line 2622420: "..."
鉴于这很可能是因为表中的数据不好(也包含合法的非ASCII字符),我试图在上下文中找到实际的字节序列,我不能这样做在任何地方找到它(看看有问题的行,正则表达式替换字符作为预处理的一部分,等等)。作为参考,这个grep什么都不返回:
cat /tmp/tables_processed/Carbon.consensus.observations | grep --color='auto' -P "[\x80]"
我在追踪这个字节序列在上下文中的位置时做错了什么?
答案 0 :(得分:0)
我建议将 SQL 文件(看似 /tmp/tables_processed/Carbon.consensus.observations )加载到具有 hex的编辑器中模式。这应该允许您在上下文中查看它(取决于确切的编辑器)。
gVim (或基于终端的 Vim )是我推荐的一个选项。
例如,如果我在 gVim 中打开包含此内容的 SQL 副本文件:
1 1.2
2 1.1
3 3.2
我可以通过命令%!xxd
(在 gVim 或终端 Vim 中)或菜单选项工具>将其转换为十六进制模式。转换为HEX 。
产生这个显示:
0000000: 3109 312e 320a 3209 312e 310a 3309 332e 1.1.2.2.1.1.3.3.
0000010: 320a 2.
然后,您可以运行%!xxd -r
将其转换回来,或者菜单选项工具>转换回来。
注意:这实际上修改了文件,因此建议对原始文件的副本执行此操作,以防万一以某种方式写入更改(您必须明确保存缓冲区)在 Vim )。
这样,你可以在左边看到十六进制序列,在右边看到它们的 ASCII 等价物。如果您搜索80
,您应该可以在上下文中查看它。使用 gVim 时,两种模式的行编号会有所不同,如本示例所示。
但是,您发现的第一个80
可能就是那条线,因为如果有更早的那条,那么它很可能会失败。
另一个可能有助于我过去使用过的工具是图形十六进制编辑器GHex。由于这是一个GNOME项目,不太确定它是否可以与 CentOS 一起使用。 wxHexEditor据说可以与 CentOS 一起工作,看起来很有希望从网站上看,虽然我还没有使用它。它是作为大量文件"的十六进制编辑器,所以如果您的 SQL 文件很大,那么可能就是这样。