如何在SQL Server中解析复杂字符串
我试图找出解析SQL Server中以字符串形式存储的复杂JSON对象的最佳方法 我的表格包含以下信息:如何在SQL Server中解析复杂字符串,sql,sql-server,stored-procedures,Sql,Sql Server,Stored Procedures,我试图找出解析SQL Server中以字符串形式存储的复杂JSON对象的最佳方法 我的表格包含以下信息: LogID | Content -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
LogID | Content
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
55271413 | {"LicensePlate":"","FreightHaulerProviderXId":"ABC","FreightProviderReferenceNumber":"5218912","CarrierScac":"XYZ","Latitude":33.595555,"Longitude":-85.854722,"StreetAddress1":"","StreetAddress2":"","City":"","State":"","PostalCode":"","Country":""}
55271414 | {"LicensePlate":"","FreightHaulerProviderXId":"ABC","FreightProviderReferenceNumber":"5218944","CarrierScac":"XYZ","Latitude":37.996666,"Longitude":-78.314444,"StreetAddress1":"","StreetAddress2":"","City":"","State":"","PostalCode":"","Country":""}
55271415 | {"LicensePlate":"","FreightHaulerProviderXId":"ABC","FreightProviderReferenceNumber":"5219079","CarrierScac":"YZB","Latitude":34.027500,"Longitude":-117.522222,"StreetAddress1":"","StreetAddress2":"","City":"","State":"","PostalCode":"","Country":""}
55271416 | {"LicensePlate":"","FreightHaulerProviderXId":"ABC","FreightProviderReferenceNumber":"5219020","CarrierScac":"XYZ","Latitude":37.754722,"Longitude":-121.144166,"StreetAddress1":"","StreetAddress2":"","City":"","State":"","PostalCode":"","Country":""}
55271417 | {"LicensePlate":"","FreightHaulerProviderXId":"ABC","FreightProviderReferenceNumber":"5218911","CarrierScac":"XYZ","Latitude":40.585833,"Longitude":-91.425000,"StreetAddress1":"","StreetAddress2":"","City":"","State":"","PostalCode":"","Country":""}
55271418 | {"LicensePlate":"","FreightHaulerProviderXId":"ABC","FreightProviderReferenceNumber":"5218785","CarrierScac":"XYZ","Latitude":30.747500,"Longitude":-85.270277,"StreetAddress1":"","StreetAddress2":"","City":"","State":"","PostalCode":"","Country":""}
55271426 | {"LicensePlate":"","FreightHaulerProviderXId":"ABC","FreightProviderReferenceNumber":"5219044","CarrierScac":"XYZ","Latitude":33.598333,"Longitude":-97.936388,"StreetAddress1":"","StreetAddress2":"","City":"","State":"","PostalCode":"","Country":""}
我试图解析每个字符串,并将其放入一个新列中,以JSON属性的名称作为列名,相应的值作为行值
例如,下面是我为每一行查找的结果:
LogID | LicensePlate | FreightHaulerProviderXId | FreightProviderReferenceNumber | CarrierScac | Latitude | Longitude | StreetAddress1 | StreetAddress2 | City | State | PostalCode | Country
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
55271413 | | ABC | 5218912 | XYZ | 33.595555 | -85.854722 | | | | | |
我尝试过使用一些可能非常糟糕的SQL逻辑来解析它。实际上,我查找整个字符串,获取一个子字符串,然后手动指定一个列名。对于可伸缩性和性能而言,这不是一个很好的解决方案
SELECT DISTINCT
SUBSTRING(lcon.Content, CHARINDEX('CarrierScac', lcon.Content)+14, CHARINDEX('City',lcon.Content) - CHARINDEX('CarrierScac', lcon.Content) + Len('City')-21) as 'CarrierScac',
SUBSTRING(lcon.Content, CHARINDEX('Latitude', lcon.Content)+10, CHARINDEX('Longitude',lcon.Content) - CHARINDEX('Latitude', lcon.Content) + Len('Longitude')-21) as 'Latitude',
SUBSTRING(lcon.Content, CHARINDEX('Longitude', lcon.Content)+11, CHARINDEX('PositionEventType',lcon.Content) - CHARINDEX('Longitude', lcon.Content) + Len('"PositionEventType')-31) as 'Longitude'
FROM
acg.LogContext lcon
WHERE
lcon.Content LIKE '%XYZ%'
任何帮助我都将不胜感激,因为即使在研究了半天的技术之后,我似乎完全被难倒了
谢谢 一个选项是升级到SQL Server 2016。否则,我会考虑使用NeXOLTFISH库和SQL CLR集成。
JSON。。。似乎CLR受到大多数人的青睐;但这里有一个有趣的TSQL方法 我知道仅仅在这里发布链接是不礼貌的,但这可能是TL;大多数人的DR;正如@Gordon Linoff提到的,2016年将有内置支持。总之,有人提出了一个解决方案:
在一个解析函数和两个交叉应用程序的帮助下
Declare @YourTable table (LogID int,Content varchar(max))
Insert Into @YourTable values
(55271413,'{"LicensePlate":"","FreightHaulerProviderXId":"ABC","FreightProviderReferenceNumber":"5218912","CarrierScac":"XYZ","Latitude":33.595555,"Longitude":-85.854722,"StreetAddress1":"","StreetAddress2":"","City":"","State":"","PostalCode":"","Country":""}'),
(55271414,'{"LicensePlate":"","FreightHaulerProviderXId":"ABC","FreightProviderReferenceNumber":"5218944","CarrierScac":"XYZ","Latitude":37.996666,"Longitude":-78.314444,"StreetAddress1":"","StreetAddress2":"","City":"","State":"","PostalCode":"","Country":""}'),
(55271415,'{"LicensePlate":"","FreightHaulerProviderXId":"ABC","FreightProviderReferenceNumber":"5219079","CarrierScac":"YZB","Latitude":34.027500,"Longitude":-117.522222,"StreetAddress1":"","StreetAddress2":"","City":"","State":"","PostalCode":"","Country":""}'),
(55271416,'{"LicensePlate":"","FreightHaulerProviderXId":"ABC","FreightProviderReferenceNumber":"5219020","CarrierScac":"XYZ","Latitude":37.754722,"Longitude":-121.144166,"StreetAddress1":"","StreetAddress2":"","City":"","State":"","PostalCode":"","Country":""}'),
(55271417,'{"LicensePlate":"","FreightHaulerProviderXId":"ABC","FreightProviderReferenceNumber":"5218911","CarrierScac":"XYZ","Latitude":40.585833,"Longitude":-91.425000,"StreetAddress1":"","StreetAddress2":"","City":"","State":"","PostalCode":"","Country":""}'),
(55271418,'{"LicensePlate":"","FreightHaulerProviderXId":"ABC","FreightProviderReferenceNumber":"5218785","CarrierScac":"XYZ","Latitude":30.747500,"Longitude":-85.270277,"StreetAddress1":"","StreetAddress2":"","City":"","State":"","PostalCode":"","Country":""}'),
(55271426,'{"LicensePlate":"","FreightHaulerProviderXId":"ABC","FreightProviderReferenceNumber":"5219044","CarrierScac":"XYZ","Latitude":33.598333,"Longitude":-97.936388,"StreetAddress1":"","StreetAddress2":"","City":"","State":"","PostalCode":"","Country":""}')
Select LogID
,LicensePlate = max(case when Item='LicensePlate' then Value else null end)
,FreightHaulerProviderXId = max(case when Item='FreightHaulerProviderXId' then Value else null end)
,FreightProviderReferenceNumber = max(case when Item='FreightProviderReferenceNumber' then Value else null end)
,CarrierScac = max(case when Item='CarrierScac' then Value else null end)
,Latitude = max(case when Item='Latitude' then Value else null end)
,Longitude = max(case when Item='Longitude' then Value else null end)
,StreetAddress1 = max(case when Item='StreetAddress1' then Value else null end)
,StreetAddress2 = max(case when Item='StreetAddress2' then Value else null end)
,City = max(case when Item='City' then Value else null end)
,State = max(case when Item='State' then Value else null end)
,PostalCode = max(case when Item='PostalCode' then Value else null end)
,Country = max(case when Item='Country' then Value else null end)
From (
Select LogID
,Item = max(case when RetSeq=1 then RetVal else null end)
,Value = max(case when RetSeq=2 then RetVal else null end)
From (
Select A.LogID
,Grp = B.RetSeq
,C.*
From @YourTable A
Cross Apply (Select RetSeq,RetVal=Replace(Replace(Replace(RetVal,'"',''),'{',''),'}','') From [dbo].[udf-Str-Parse](A.Content,',') ) B
Cross Apply (Select * From [dbo].[udf-Str-Parse](B.RetVal,':') ) C
) N Group By LogID,Grp
) F
Group By LogID
返回
如果需要的话,UDF
CREATE FUNCTION [dbo].[udf-Str-Parse] (@String varchar(max),@Delimiter varchar(10))
Returns Table
As
Return (
Select RetSeq = Row_Number() over (Order By (Select null))
,RetVal = LTrim(RTrim(B.i.value('(./text())[1]', 'varchar(max)')))
From (Select x = Cast('<x>'+ Replace(@String,@Delimiter,'</x><x>')+'</x>' as xml).query('.')) as A
Cross Apply x.nodes('x') AS B(i)
);
--Select * from [dbo].[udf-Str-Parse]('Dog,Cat,House,Car',',')
--Select * from [dbo].[udf-Str-Parse]('John Cappelletti was here',' ')
从SQL Server 2016开始,数据库中内置了JSON支持:。有大量源详细说明了SQL CLR的内存泄漏情况。这个问题解决了吗?不幸的是,我无法升级到2016年,也没有任何第三方集成到我们数据库的perms:你是个天才。非常感谢你!你到底是怎么学会如此惊人的SQL技能的?你有推荐书/网站/在线课程吗?@colonelsanders91 Genius。。。我妻子不会同意的。只能建议通过实践学习,并通过观察重量级击球手来学习。我每天都学到一些东西。这是有趣的部分。