#sql #json #sql-server #tsql
Вопрос:
У меня есть некоторые данные в базе данных (sql server 2008) в формате JSON с юникодом, как это:
{"PCode":"999999","Code":"123","effect":"u4e2du6587u5b57u6e2cu8a66"}
u4e2du6587u5b57u6e2cu8a66
являются ли китайские иероглифы, как я могу восстановить данные в китайских иероглифах?
Комментарии:
1. как только китайские иероглифы будут преобразованы в шестнадцатеричные…вы не сможете преобразовать их обратно. ваша колонка должна поддерживать юникод. Я думаю, что вы используете varchar для хранения данных вместо Nvarchar.
2. Каков тип данных столбца и версия SQL Server? Обычно
OPENJSON
достаточно одного звонка.3. @ДалеК ответ, который я пробовал
4. @hkguile если вы на самом деле не отвечаете на свой собственный вопрос, вам нужно добавить это в свой вопрос и удалить ответ.
Ответ №1:
Ответ:
Похоже, вы используете SQL Server 2008 (где поддержка JSON недоступна), поэтому одним из возможных подходов является анализ последовательности юникода в формате XML. Обратите внимание, что XML не использует u
обозначения, поэтому вам необходимо преобразовать этот текст JSON с помощью ссылки на символы XML amp;#x[0-9a-fA-F];
:
T-SQL:
DECLARE @text nvarchar(max)
SET @text = N'u4e2du6587u5b57u6e2cu8a66'
DECLARE @xml xml
SET @xml = N'<x>' STUFF(REPLACE(@text, N'u', N';amp;#x'), 1, 1, N'') N';</x>'
SELECT @xml.value('(/x)[1]', 'nvarchar(max)') AS [ChineseText]
Результат:
ChineseText
-----------
中文字測試
Обратите внимание, что с SQL Server 2016 вы можете легко анализировать JSON с помощью JSON_VALUE()
.
SELECT JSON_VALUE(CONCAT(N'["', @text, N'"]'), '$[0]') AS [ChineseText]
Обновить:
Если в JSON есть дополнительные символы, вам необходимо разделить содержимое JSON с помощью XML и u
в качестве разделителя:
DECLARE @text nvarchar(max)
SET @text = N'u4e2dengu6587engu5b57234u6e2cu8a66'
DECLARE @xml xml
SET @xml = CONCAT(STUFF(REPLACE(@text, N'u', N'</x><x>'), 1, 4, N''), N'</x>')
SELECT
CONVERT(xml, N'<x>amp;#x' LEFT(t.value('.', 'nvarchar(max)'), 4) N';</x>').value('(/x)[1]', 'nvarchar(max)'),
STUFF(t.value('.', 'nvarchar(max)'), 1, 4, N'')
FROM @xml.nodes('/x') AS x(t)
FOR XML PATH('')
Результат:
中eng文eng字234測試
Комментарии:
1. похоже, у меня нет функции конкатенации
2. @hkguile, вы можете использовать
оператор объединения.
3. но все равно нужно передать, если какое-то число/eng внутри строки, например, u4e2dengu6587engu5b57234u6e2cu8a66
4. Хороший ответ, 1 с моей стороны!
Ответ №2:
Есть лучшая практика?
DECLARE @Text NVARCHAR(MAX)
DECLARE @stringToSplit NVARCHAR(MAX)
DECLARE @returnList TABLE ([Name] [nvarchar] (500))
set @stringToSplit = 'u4e2du6587u5b57u6e2cu8a66'
DECLARE @name NVARCHAR(255)
DECLARE @pos INT
WHILE CHARINDEX('u', @stringToSplit) > 0
BEGIN
SELECT @pos = CHARINDEX('u', @stringToSplit)
SELECT @name = SUBSTRING(@stringToSplit, 1, @pos-1)
IF @name <> ''
BEGIN
INSERT INTO @returnList
SELECT NCHAR( CONVERT(INT, CONVERT(VARBINARY,@name, 2) ) )
END
SELECT @stringToSplit = SUBSTRING(SUBSTRING(@stringToSplit, @pos 1, LEN(@stringToSplit)-@pos),2,LEN(@stringToSplit))
END
INSERT INTO @returnList
SELECT NCHAR( CONVERT(INT, CONVERT(VARBINARY,@stringToSplit, 2) ) )
select * from @returnList