简体   繁体   中英

T-SQL string conversion

I have an SNMP message column (formatted as VARCHAR(MAX)) in a SQL table like the one below. Is there a way to convert each message OID into a column/value format?

Message column content sample:

community=PUBLIC, enterprise=1.1.1.1.1.1.1.1.1.1.1, uptime=42170345, agent_ip=1.1.1.1, version=Ver2, ...

Desired result:

community    enterprise              uptime    agent_ip
---------    ----------              ------    --------
PUBLIC       1.1.1.1.1.1.1.1.1.1.1   42170345  1.1.1.1    ...

So basically it would need to split the string by ", " and then return INI values as columns. Note this is on one row (not creating or splitting to multiple rows, just multiple columns)

This is SQL Server 2008 R2.

Thank you.

You can find a splitstring function on the web in many places. Here is how you would use it in a query to do what you want:

select t.*, cols.*
from table t cross apply
     (select max(case when token like 'community=%' then substring(token, 11, len(token))
                 end) as community,
             max(case when token like 'enterprise=%' then substring(token, 12, len(token))
                 end) as enterprise,
             max(case when token like 'uptime=%' then substring(token, 8, len(token))
                 end) as uptime,
             max(case when token like 'agent_ip=%' then substring(token, 10, len(token))
                 end) as agent_ip
      from dbo.SplitString(t.snmp, ',')(idx, token)
     ) cols;

Probably not the most efficient way to do this, but this works:

SELECT
  REPLACE((SUBSTRING(MsgText,CHARINDEX('community=',MsgText),CHARINDEX(', enterprise=',MsgText) - CHARINDEX('community=',MsgText))),'community=','') AS community  
  ,REPLACE((SUBSTRING(MsgText,CHARINDEX('enterprise=',MsgText),CHARINDEX(', uptime=',MsgText) - CHARINDEX('enterprise=',MsgText))),'enterprise=','') AS enterprise
  ,REPLACE((SUBSTRING(MsgText,CHARINDEX('uptime=',MsgText),CHARINDEX(', agent_ip=',MsgText) - CHARINDEX('uptime=',MsgText))),'uptime=','') AS uptime
  ,REPLACE((SUBSTRING(MsgText,CHARINDEX('agent_ip=',MsgText),CHARINDEX(', version=',MsgText) - CHARINDEX('agent_ip=',MsgText))),'agent_ip=','') AS agent_ip
  ,MsgText
FROM Database.dbo.Table

In case anyone needs a method to parse SNMP messages

Here is solution using transforming string to XML which brings more freedom with result processing:

-- Prepare data for solution testing
DECLARE @srctable TABLE (
    Id              INT,
    SnmpMessage     VARCHAR(MAX),
    SnmpMessageXml  XML
)

INSERT INTO @srctable
SELECT Id, SnmpMessage, SnmpMessageXml FROM ( VALUES
(1, 'community=PUBLIC, enterprise=1.1.1.1.1.1.1.1.1.1.1, uptime=42170345, agent_ip=1.1.1.1, version=Ver2',   null)
) v (Id, SnmpMessage, SnmpMessageXml)

-- Transform source formatted string to XML string
UPDATE @srctable
SET SnmpMessageXml = CAST('<row><data ' + REPLACE(REPLACE(SnmpMessage, ',', '"/><data '), '=', '="') + '"/></row>' AS XML)

-- Final select from XML data
SELECT  SnmpMessageXml.value('(/row/data/@community)[1]',  'VARCHAR(999)') AS community,
        SnmpMessageXml.value('(/row/data/@enterprise)[1]',  'VARCHAR(999)') AS enterprise,
        SnmpMessageXml.value('(/row/data/@uptime)[1]',  'VARCHAR(999)') AS uptime,
        SnmpMessageXml.value('(/row/data/@agent_ip)[1]',  'VARCHAR(999)') AS agent_ip,
        SnmpMessageXml.value('(/row/data/@version)[1]',  'VARCHAR(999)') AS version
FROM @srctable AS t

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM