【问题标题】:SQL error on inserting UTF8 string into SQL Server 2008 table将 UTF8 字符串插入 SQL Server 2008 表时出现 SQL 错误
【发布时间】:2013-06-20 14:41:59
【问题描述】:

我在尝试使用 Zeosdb 本机 SQL Server 库从我的 Delphi 7 应用程序将包含 UTF-8 编码的中文字符和标点符号的字符串插入 SQL Server 2008 表(默认安装)时遇到问题。

我记得过去我在使用 PHP 和其他方法将 UTF8 字符串插入 SQL Server 时遇到问题,所以我相信这个问题不是 Zeosdb 独有的。

这种情况不会一直发生,有些 UTF8 编码的字符串可以成功插入,但有些不能。我无法弄清楚导致失败的字符串中是什么。

表架构:

CREATE TABLE [dbo].[incominglog](
    [number] [varchar](50) NULL,
    [keyword] [varchar](1000) NULL,
    [message] [varchar](1000) NULL,
    [messagepart1] [varchar](1000) NULL,
    [datetime] [varchar](50) NULL,
    [recipient] [varchar](50) NULL
) ON [PRIMARY]

SQL 语句模板:

INSERT INTO INCOMINGLOG ([Number], [Keyword], [Message], [MessagePart1], [Datetime], [Recipient]) 
VALUES('{N}', '{KEYWORD}', '{M}', '{M1}', '{TIMESTAMP}', '{NAME}')

参数{KEYWORD}{M}{M1}可以包含UTF8字符串。

例如下面的语句会返回错误:

“颔附近的语法不正确。字符串 'å...¨åŠ›å...‹æœå››ç§å±é™©','2013-06-19 17:07:28','')' 后的非闭合引号。

INSERT INTO INCOMINGLOG ([Number], [Keyword], [Message], [MessagePart1], [Datetime], [Recipient]) 
VALUES('+6590621005', '题', '题 [全力克æœå››ç§å±é™© åšå†³æ‰«é™¤ä½œé£Žä¹‹å¼Š]', '[全力克æœå››ç§å±é™©','2013-06-19 17:07:28', '')

注意:复制粘贴后utf8编码丢失,请忽略实际字符。

我也尝试过使用NVARCHAR 而不是VARCHAR

CREATE TABLE [dbo].[incominglog](
    [number] [varchar](50) NULL,
    [keyword] [nvarchar](max) NULL,
    [message] [nvarchar](max) NULL,
    [messagepart1] [nvarchar](max) NULL,
    [datetime] [varchar](50) NULL,
    [recipient] [varchar](50) NULL
) ON [PRIMARY]

并且还尝试将SQL语句修改为:

INSERT INTO INCOMINGLOG ([Number],[Keyword],[Message],[MessagePart1],[Datetime],[Recipient]) VALUES('{N}',N'{KEYWORD}',N'{M}',N'{M1}','{TIMESTAMP}','{NAME}')

它们也不起作用。我将不胜感激任何指针。谢谢。

已编辑: 如下面的 marc_s 所示,N 前缀必须在单引号之外。在我的实际测试中是正确的,最初的陈述是一个错字,我已经更正了。

带有N前缀的测试也返回错误:

“原标颔附近的语法不正确。后面的非封闭引号 字符串 'å...¨åŠ›å...‹æœ?å››ç§?å?±é™©','2013-06-19 21:22:08','')'。

SQL 语句:

INSERT INTO INCOMINGLOG ([Number],[Keyword],[Message],[MessagePart1],[Datetime],[Recipient]) VALUES('+6590621005',N'原标题',N'原标题 [全力克�四��险 �决扫除作风之弊]',N'[全力克�四��险','2013-06-19','')

。 .

回复 gbn 的回答:我尝试过使用参数化 SQL,但仍然遇到“字符串后未闭合引号”错误。

对于新的测试,我使用了简化的 SQL 语句:

INSERT INTO INCOMINGLOG ([Keyword],[Message]) VALUES(:KEYWORD,:M)

上述语句返回的错误:

“原标颔附近的语法不正确。后面的非封闭引号 字符串'')'。

关于信息,KEYWORD 和 M 的值是:

关键词:原标é¢~

M:原标é¢~ [

。 . .

6 月 20 日的进一步测试 参数化 SQL 查询不起作用,因此我尝试了另一种方法,尝试隔离导致错误的字符。经过反复试验,我设法确定了有问题的角色。

以下字符产生错误:é¢~

SQL 语句:INSERT INTO INCOMINGLOG ([Keyword]) VALUES('题')

有趣的是,请注意返回错误税中的字符串包含一个“?”原始语句中不存在的字符。

错误:字符串 'é¢?)' 后面的引号未闭合。 'é¢?)' 附近的语法不正确。

如果我在罪魁祸首之后立即放置一些拉丁字符,就不会出错。例如,INSERT INTO INCOMINGLOG ([Keyword]) VALUES('题Ok') 工作正常。注意:它不适用于所有字符。

【问题讨论】:

  • 您用来替换{KEYWORD} 的UTF-8 字符串是否包含引号?错误消息似乎表明了这一点。我建议使用不会发生此类错误的参数化查询。
  • 参数化查询也将防止 SQL 注入。
  • 嗨,mjn,我把所有引号都加倍了。我怀疑引号可能不是 UTF8 字符串中唯一的非法字符。
  • 您的 SQL INSERT INTO INCOMINGLOG ([Keyword]) VALUES('题') 在 SSMS 中为我​​工作
  • @gbn 我不确定,但我认为复制到 SSMS 时不一样,也许编码发生了变化。测试的唯一方法是使用代码 - 我创建了 PHP 代码,您可以从 here 下载。有 2 个 PHP 文件,一个带有有效的语句,另一个带有失败的语句。顺便说一句,这篇文章说 MSSQL 不支持 UTF-8 - article link。以前,在使用 UTF-8 之前,我将 UTF-8 转换为宽字符串,但从 SSMS 中查看时它们显示为问号。

标签: sql-server delphi utf-8


【解决方案1】:

UTF-8 中有' 字符异常终止SQL。

经典的 SQL 注入。

使用适当的参数化,基本上不是字符串连接。

编辑,问题更新后...

如果没有 Delphi 代码,我认为我们无法为您提供帮助
所有 SQL 端代码都有效。例如,这适用于 SSMS

DECLARE @t TABLE ([Keyword] nvarchar(100) COLLATE Chinese_PRC_CI_AS);
INSERT INTO @t ([Keyword]) VALUES('题');
INSERT INTO @t ([Keyword]) VALUES(N'题');
SELECT * FROM @t T;

缺少一些东西来帮助我们解决这个问题

另见

【讨论】:

  • 谢谢gbn,我已经尝试过使用参数化SQL,但仍然是同样的错误,请查看我在原始问题中的评论。
  • 我喜欢指出我的 SQL Server 数据库正在使用 Chinese_PRC_CI_AS 排序规则。我使用 SQL 管理工作室手动插入 GBK 编码中的相同数据没有问题 - 但我的软件使用 UTF8 插入。
  • @Joshua:请您添加 Delphi 代码。这可能是客户端错误,而不是 SQL 错误
  • 我为此创建了另一个问题,您可以从那里下载我制作的测试程序的链接 - 单击here。要重现问题,请取消注释“//inserted as utf8”并删除编辑框中的“ok”。
猜你喜欢
  • 2010-11-25
  • 2014-05-30
  • 2023-03-04
  • 2016-02-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-13
  • 1970-01-01
相关资源
最近更新 更多