之前为了处理用户输入的特殊字符,我将输入内容使用javascript escape方法转义后保存到DB,后来觉的不太合适,需要写一段SQL更新旧资料。找了相关资料,Sql Server 有函数可以将数值转换为字符,例如0x20转换为空格,'0x20'字符串呢,却不行,所以先将'0x20'转换为数值即可;当然,我们可以将旧资料使用C#或Javascript的unescape转换后再保存到DB。
javascript escape的原理: 所有空格、标点、重音符号以及其他非 ASCII 字符都用 %xx 或 %uxxxx(字符值大于 255) 编码代替,其中 xx,xxxx为该字符的十六进制数。例如,空格-- "%20" ,单引号(’)---%u2019
看下面的SQL代码,主要运用SQL SERVER 的字符串函数、NCHAR()、UNICODE()、POWER()等函数
其中 (CHARINDEX('2','0123456789ABCDEF')-1)*POWER(16,3) 是十六进制转十进制算法。比如,'122AB',A的十进制值 = 10*16^1
declare @tenNum INT=0 -- %u2013 SET @tenNum = (CHARINDEX('2','0123456789ABCDEF')-1)*POWER(16,3) + (CHARINDEX('0','0123456789ABCDEF')-1)*POWER(16,2) + (CHARINDEX('1','0123456789ABCDEF')-1)*POWER(16,1) + (CHARINDEX('3','0123456789ABCDEF')-1)*POWER(16,0)
--看懂此语句,基本上就没问题,主要是要清楚函数功能 SELECT '%u2013' AS 'ESCAPE字符串' ,NCHAR(0x2013) AS '十六进制' ,@tenNum AS '十进制值' ,NCHAR(@tenNum) AS '字符' ,UNICODE('–') AS '万国码'
结果如下:
1 DECLARE 2 @REMARK NVARCHAR(MAX)='forward%20with%20this%20project%u2013%20in%20the%20near%20future%u2026%20%28abcd%20ef%20aaa%20efg%20or%20hij%29%20sfsdaf' 3 ,@TEMP NVARCHAR(10) = '' 4 ,@tenNum INT 5 ,@1c CHAR(1) 6 ,@2c CHAR(1) 7 ,@3c CHAR(1) 8 ,@4c CHAR(1) 9 ,@i BIGINT = 1 10 11 SET @REMARK = RTRIM(LTRIM(ISNULL(@REMARK,''))) 12 13 IF LEN(@REMARK) > 0 14 BEGIN 15 16 SET @i = 1 17 --处理%xx格式 18 WHILE PATINDEX('%[%][0-9A-F][0-9A-F]%',@REMARK) > 0 AND @i < 5 19 BEGIN 20 21 SET @TEMP = SUBSTRING(@REMARK,PATINDEX('%[%][0-9A-F][0-9A-F]%',@REMARK),3) 22 23 SELECT @1c = SUBSTRING(@TEMP,2,1),@2c = SUBSTRING(@TEMP,3,1) 24 SET @tenNum = (CHARINDEX(@1c,'0123456789ABCDEF')-1)*POWER(16,1) 25 + (CHARINDEX(@2c,'0123456789ABCDEF')-1)*POWER(16,0)--十六进制转十进制 26 IF NCHAR(@tenNum) IS NOT NULL 27 SET @REMARK = REPLACE(@REMARK,@TEMP,NCHAR(@tenNum)) 28 ELSE 29 SET @i+=1 30 END 31 32 SET @i = 1 33 34 --处理%xxxx格式 35 WHILE PATINDEX('%[%][U][0-9A-F][0-9A-F][0-9A-F][0-9A-F]%',@REMARK) > 0 AND @i < 5 36 BEGIN 37 38 PRINT PATINDEX('%[%][U][0-9A-F][0-9A-F][0-9A-F][0-9A-F]%',@REMARK) 39 SET @TEMP = SUBSTRING(@REMARK,PATINDEX('%[%][U][0-9A-F][0-9A-F][0-9A-F][0-9A-F]%',@REMARK),6) 40 41 SELECT @1c = SUBSTRING(@TEMP,3,1),@2c = SUBSTRING(@TEMP,4,1) 42 ,@3c = SUBSTRING(@TEMP,5,1),@4c = SUBSTRING(@TEMP,6,1) 43 SET @tenNum = (CHARINDEX(@1c,'0123456789ABCDEF')-1)*POWER(16,3) 44 + (CHARINDEX(@2c,'0123456789ABCDEF')-1)*POWER(16,2) 45 + (CHARINDEX(@3c,'0123456789ABCDEF')-1)*POWER(16,1) 46 + (CHARINDEX(@4c,'0123456789ABCDEF')-1)*POWER(16,0) 47 SELECT @1c,@2c,@3c,@4c 48 49 IF NCHAR(@tenNum) IS NOT NULL 50 SET @REMARK = REPLACE(@REMARK,@TEMP,NCHAR(@tenNum)) 51 ELSE 52 SET @i+=1 53 END 54 END 55 56 SELECT @REMARK 'result'
只要理解上面的实现,那么SQL server版 的escape()实现不在话下。