我需要将此字符“●”插入到VARCHAR
MSSQL 数据库的列中,并将排序规则设置为SQL_Latin1_General_CP1_CI_AS
(或至少模拟我的 Python + Windows MSSQL 驱动程序可能已经完成的操作)。我试图从我的客户那里插入它,但它被插入为?
.
在 Python 中检查的十六进制值\xe2\x97\x8f
是二进制 226、151、143。
排序规则说明 226 已定义,但 143 和 151 未定义。所以我最好是插入226?
我做这个练习的原因是我们的应用程序早先将这个字符插入到 DB 中。在这一点上,我不知道它是如何进入的,因为它通过一个带有 Windows MSSQL 驱动程序的 Python 应用程序,我们的数据库团队编写了一个脚本来纠正它,显然它被替换为“?”。
现在我只是想重现这个场景来问他们为什么它被替换为“?” 因为我们在应用程序中将其替换为空。由于我的应用程序已经修复了这个问题(我们删除了任何大于 127 的内容),我试图直接从后端模拟它以证明它正在被替换为“?” 这实际上是我的主张,我认为它已经完成,因为它在更新查询中说“整理”。
UPDATE pr_response
SET nur_respon =
REPLACE (nur_respon,
SUBSTRING(nur_respon, PATINDEX('%[^ !-~]%' COLLATE Latin1_General_BIN, nur_respon), 1),
'')
WHERE PATINDEX('%[^ !-~]%' COLLATE Latin1_General_BIN, nur_respon) > 0
这是删除 Non-ASCII-Data > 127 的好脚本吗?有人可以用简单的英语解释这个查询吗?
不,该应用程序没有使用排序规则将此字符 ( Black Circle U+25CF ) 插入到
VARCHAR
列中[SQL_]Latin1_General...
。Latin1_General 排序规则使用代码页 1252,它没有这样的字符,似乎也没有“最合适”的映射将其转换为类似的东西。该字符确实存在于某些代码页中,例如韩语和日语排序规则使用的代码页,如以下查询所示(两者都是双字节字符集,这就是转换为
VARBINARY
显示两个字节而不是一个字节的原因):但是,该应用程序可能插入了“•”(Bullet U+2022),它看起来非常相似,只是小了一点。“项目符号”字符在代码页 1252(Dec 149 或十六进制 0x95)中可用。
那么,将“●”替换为“?” 听起来不像修复它;-)。
不管技术细节如何,很明显这两个陈述不能同时为真:不能用“?”代替。并在访问 SQL Server 之前被删除。显然,应用程序代码没有对此进行修复,并且不会删除值超过 127 的所有内容。它正在被转换为“?” 在 SQL Server 中,因为正在插入该字符但在代码页 1252 中不存在。
不,通过
COLLATE
关键字强制二进制排序规则不会将此字符更改为“?”。列的排序规则 (SQL_Latin1_General_CP1_CI_AS
) 和显式排序规则 (Latin1_General_BIN
) 都使用代码页 1252,因此不会更改任何字符。“●”字符被替换为“?” 因为它被插入到
VARCHAR
列中。一旦它作为问号插入,就没有什么需要清理的了,也没有办法将该问号识别为最初来自其他东西,而不是预期的问号。该查询查找任何出现的 ASCII 值大于 127 的字符(这就是它
PATINDEX
所做的),然后获取任何这样的字符(这就是它SUBSTRING
所做的),然后将列中该字符的所有出现替换为空字符串(这就是它的REPLACE
作用)。UPDATE
如果没有找到 ASCII 值超过 127 的字符,则查询不会执行任何操作。此查询一次仅适用于一个字符。因此,如果一列有 2 个或多个 ASCII 值大于 127 的字符不是相同的 ASCII 值,则需要多次执行脚本。
在这种特殊情况下(即用“?”替换“●”),该查询将无济于事,因为该转换正在进行中。该查询仅处理 ASCII 值为 128 - 255 的字符,但“●”不是其中一个字符,因为它一开始就不可能出现在此列中。