【发布时间】: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