AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 159564
Accepted
Feillen
Feillen
Asked: 2016-12-31 02:28:16 +0800 CST2016-12-31 02:28:16 +0800 CST 2016-12-31 02:28:16 +0800 CST

不显示从文件导入的特殊字符

  • 772

该场景是一个 SQL Server 实例,一个主要使用 BULK INSERT 操作提供数据的数据库,并且插入的一些文本包含特殊字符,例如ñ因为我在西班牙环境中工作。

所以,在最初的小测试之后,我意识到当我运行一个简单的 时这些特殊字符没有正确显示select,所以我开始检查我能想到的一切:

  • 文件编码:要批量插入的文件具有正确的编码:ANSI
  • 数据库编码:数据库具有正确的编码(谢天谢地):select collation_name from sys.databases where name='DBNAME';结果SQL_Latin1_General_CP1_CI_AS
    • Latin1:使用的字符集。这很适合我
    • 将军:这里没什么有趣的
    • CP1:这意味着它使用代码页 1,简而言之,这意味着代码页 1252 <=> 用于编码 WIN-1252 的代码页,与 Latin1 非常相似
    • CI:不区分大小写
    • AS:对口音敏感,所以 á 与 a 不同
  • 将数据导出到文件并检查:文件编码为ANSI ,但数据显示不正确,没有特殊字符,而是我发现了一些其他字符,使文本难以阅读。

通过这些测试,我得出的结论是数据没有正确存储,这就是它没有正确显示和导出的原因。我在互联网上找到的几乎所有解决方案都建议使用字符串数据类型字段nvarchar而不是varchar字符串数据类型字段,但这并不能解决这种情况。是什么破坏了我的插入?

sql-server import
  • 2 2 个回答
  • 6759 Views

2 个回答

  • Voted
  1. Best Answer
    Solomon Rutzky
    2016-12-31T11:42:48+08:002016-12-31T11:42:48+08:00

    如果字符导入不正确,则以下一个(或两个)区域存在问题,因为这实际上是一个两步过程:

    1. BCP / BULK INSERT 不知道文件是如何编码的并且解释不正确

    2. 目标列是VARCHAR(或CHAR{or TEXT,但不要使用TEXT} )并且该目标列(不是数据库)的排序规则使用的代码页没有错误导入字符的映射。

    这里需要注意的是,导入表所在的数据库的默认排序规则是不相关的。这里唯一重要的排序规则是要导入的每个特定字符串列的排序规则。并且每个字符串列的排序规则都可以不同,它们都不需要与数据库的默认排序规则相同。通常让数据库中大多数列的排序规则与数据库的默认值匹配,因为这将是创建新表和列时使用的排序规则,而不是通过COLLATE关键字指定排序规则。

    第 1 步:文件编码
    BCP / BULK INSERT(或大多数其他读取文件的代码)将不知道文件正在使用什么编码,除非文件使用为数不多的具有字节顺序标记 (BOM)的编码之一。但是扩展的 ASCII 编码不使用字节顺序标记,因此不能以编程方式确定(至少不能确定)。使用扩展 ASCII 编码时,您需要指定代码页,否则将假定为默认值。

    根据bcp Utility的 MSDN 页面,在-C选项下:

    OEM -> 客户端使用的默认代码页。如果未指定-C ,这是使用的默认代码页。

    您可以通过打开命令提示符并运行modeor来确定默认代码页chcp(我更喜欢chcp它,因为如果您传入一个值,它还允许更改代码页)。

    如果您的默认代码页是 850,但文件是使用 Windows-1252 Latin1 (ANSI) 的编码保存的,那么解释文件很容易出现问题,因为这两个代码页之间的字符映射不同。这与 SQL Server 没有任何关系。

    该ñ字符在代码页 1252 上的值为 241。但是,在代码页 850 上,同一字符的值为 164。文件,不管其他任何内容,都是一系列字节,其中一个字节具有十进制值241(因为当它被保存时,它被告知使用代码页 1252 确定ñ需要存储为 241)。现在,当 BCP 读取文件时,如果它使用默认的 MS-DOS 代码页 850,则相同的字节值 241 映射到 character ±。如果您要通过开关指定一个ACP或1252(相同的东西)的代码页-C,那么 BCP 将知道值 241 的字节实际上是ñ. 或者,您可以指定代码页 1255(Windows 希伯来语),然后 BCP / BULK INSERT 会将相同的字节值 241 解释为字符ס.

    第 2 步:目标列数据类型和排序规则

    一旦 BCP / BULK INSERT(或任何客户端应用程序)读取数据,它就会作为这些映射存在,而不仅仅是基本字节值。读入 BCP / BULK INSERT 的任何字符都将作为该字符存储在目标列中,只要该字符可以映射到目标数据类型和排序规则中。NVARCHAR、NCHAR和NTEXT(但不要使用)的目标数据类型NTEXT可以保存所有字符,因此 Collat​​ion 是什么并不重要。但是,如果目标数据类型是VARCHAR, CHAR, 或TEXT然后排序规则将确定代码页,该代码页又确定字符映射。如果目标数据类型是最后提到的 3 种之一,并且使用与用于文件的相同代码页关联的排序规则,那么一切都应该正常工作。或者,如果 Collat​​ion 与不同的代码页相关联,则将尝试映射character,而不是 byte 值。

    意思是,如果 BCP / BULK INSERT 正在使用代码页 1252 和字符ñ(代码页 1252 上的值 241),那么如果您将其导入到VARCHAR具有排序规则的列中SQL_Latin1_General_CP850_CI_AS——它使用代码页 850——然后您将看到一个字符ñ(相同的字符,但代码页 850 上的值为 164)而不是±,它在代码页 850 上具有相同的 241 值。但是,如果您导入到VARCHAR具有排序规则的列中Hebrew_CI_AS-- 它使用代码页1255 - 然后您将看到?而不是ס(代码页 1255 上的值 241),因为在代码页 1255 上没有映射ñ。

    • 5
  2. Feillen
    2016-12-31T02:28:16+08:002016-12-31T02:28:16+08:00

    对于那些可能会遇到与我类似的问题的人来说,对我有用的东西与代码页系统有关。我将进一步详细解释:

    数据库的整理表明数据库使用了代码页 1252,在检查了我的计算机活动代码页(运行cmd,然后在 cmd 中mode)后,我发现它是 850,所以一定是发生了冲突!
    如果计算机无法正确打印我的特殊字符,那么数据库将存储我的计算机打印到的任何愚蠢的字符串。

    我添加了选项CODEPAGE=ACP,它强制批量插入使用 sql 服务器的代码页,一切都很好:)

    • 2

相关问题

  • SQL Server - 使用聚集索引时如何存储数据页

  • 我需要为每种类型的查询使用单独的索引,还是一个多列索引可以工作?

  • 什么时候应该使用唯一约束而不是唯一索引?

  • 死锁的主要原因是什么,可以预防吗?

  • 如何确定是否需要或需要索引

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目

    • 12 个回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Jin 连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve