将UTF8字符串插入SQL Server 2008表时出现SQL错误

时间:2013-06-19 10:49:58

标签: sql-server delphi utf-8

我在使用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的值为:

  

KEYWORD:原æ‡é¢〜

     

M:原æ‡é¢〜[

。 。

  

6月20日的进一步测试参数化SQL查询不起作用,所以我尝试通过尝试隔离导致错误的字符来尝试不同的方法。经过反复试验,我设法找出了有问题的人物。

以下字符会产生错误:é¢〜

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

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

  

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

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

1 个答案:

答案 0 :(得分:3)

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;

缺少帮助我们解决这个问题的东西

另见