How to parse HL7 delimiters using only MS SQL Syntax

倾然丶 夕夏残阳落幕 提交于 2020-01-01 22:29:09

问题


Sharing this code that parses raw HL7 data using only MS SQL Syntax. It's a quick way of splitting all the | and ^ delimiters and store each data as a row. I wanted to share this because I've been looking around for way to parse HL7 Message strictly through SQL Syntax and was not able to find any resources.

I would put it out there that this is not the most efficient method to import HL7 messages to SQL databases. There are other better methods (ie: C# app - HL7 > XML > DB, 3rd party software, BULK INSERT etc.).

This is SQL syntax that will read through the | and ^ delimiter and store them in rows under TempSplit and TempSplit2 tables. The assumption here is that you have a way to import the raw HL7 file into a database (ie: SSIS). From then on, you can map the results stored under TempSplit2 to your SQL Segment table.

ID Column = position of each value between |

ID2 column = position of each value between ^

As a first test you can import the HL7 file raw(as is) into 2 column. See sample below:

  Row     val                                        Filename
  ------------------------------------------------------------------
  1       MSH|^~\&|EIH7|                       HL7_Filename.dat
          AB-PBA^AB PBA^ISO|Company|TestComp|
          20160830230713||ADT^A04|23071
          408302016752373|P|2.6|     

EDIT: As mentioned by scsimon below, the cursor loops twice and parses all data, rather than what you just need. In my current project, this was important but maybe not on yours. Feel free to modify it

Here's the code:

USE <yourdb>
Go
set nocount on


Create table dbo.TempSplit(
                    filename varchar(MAX),
                    RecordType varchar(MAX),
                    value varchar(MAX) ,
                    id int )
Create table dbo.TempSplit2(
                    filename varchar(MAX),
                    RecordType varchar(MAX),
                    value varchar(MAX) ,
                    id int ,
                    subvalue varchar(MAX) ,
                    id2 int )

truncate table dbo.TempSplit
truncate table dbo.TempSplit2
DECLARE HL7_Cursor CURSOR FOR select distinct filename 
from <your raw HL7 table>
DECLARE @tempid varchar(max) 

Open HL7_Cursor
Fetch next from hl7_cursor into @tempid
While @@FETCH_STATUS = 0
BEGIN
Declare @Rowcnt int=0
DECLARE HL7_Cursor2 CURSOR FOR select val from <<your raw HL7 table>> where filename =  @tempid
DECLARE @tempid2 varchar(max) 

Open HL7_Cursor2
Fetch next from hl7_cursor2 into @tempid2
While @@FETCH_STATUS = 0
            BEGIN
            set @Rowcnt = @Rowcnt +1
            DECLARE @RtnValue table 
                (
                    value varchar(MAX) ,
                    id int 
                 ) 

            DECLARE  @result varchar(1000),
                     @List varchar(MAX),
                     @SplitOn varchar(5),
                     @GetIndex smallint,
                     @ID int,
                     @val varchar(max),
                     @recordid varchar(max),
                     @filename varchar(1000) ,

                     @cnt int=0
            SET @list =   @tempid2

            SET @SplitOn = '|'
            SET @GetIndex = 0

            DECLARE @start INT, @end INT 
            SELECT @start = 1, @end = CHARINDEX(@SplitOn, @list) 
            WHILE @start < LEN(@list) + 1 BEGIN 
                BEGIN 
                IF @end = 0 
                begin 
                SET @end = LEN(@list) + 1
                end
                END

                Insert Into @RtnValue (id,value)
                Select @cnt,SUBSTRING(@list, @start, @end - @start) 
                SET @start = @end + 1 
                SET @end = CHARINDEX(@SplitOn, @list, @start)
                set @cnt= @cnt+1     
                END 

                insert into dbo.TempSplit
                select @tempid filename,
                       case  when 
                        (Select count(value) 
                         from @RtnValue) = 0 then value 
                        else 
                        (Select  value 
                         from @RtnValue 
                         where id =0)end Recordtype, 
                        value,id,@Rowcnt from @RtnValue
                        delete from @RtnValue
                        set  @cnt  =0


FETCH NEXT From HL7_Cursor2 into @tempid2                                       
END                     
Close hl7_cursor2
deallocate hl7_cursor2

FETCH NEXT From HL7_Cursor into @tempid                                     
END                     
Close hl7_cursor
deallocate hl7_cursor

truncate table dbo.TempSplit2
DECLARE HL7_Cursor3 CURSOR FOR select  * from dbo.TempSplit 
DECLARE @file varchar(max),@rt varchar(max),@valu varchar(max),@idz int 
,@rowcnt2 int

Open HL7_Cursor3
Fetch next from hl7_cursor3 into @file,@rt,@valu,@idz,@rowcnt2
While @@FETCH_STATUS = 0
        BEGIN
            DECLARE @RtnValue2 table 
                (

                    value varchar(MAX) ,
                    id int,
                    filename  varchar(MAX)
                ) 

            DECLARE  @result2 varchar(1000),
                     @List2 varchar(MAX),
                     @SplitOn2 varchar(5),
                     @GetIndex2 smallint,
                     @ID2 int,
                     @val2 varchar(max),
                     @recordid2 varchar(max),
                     @filename2 varchar(1000) ,
                     @cnt2 int=0
            SET @list2 =      @valu

            SET @SplitOn2 = '^'
            SET @GetIndex2 = 0

            DECLARE @start2 INT, @end2 INT                
            SELECT @start2 = 1, @end2 = CHARINDEX(@SplitOn2, @list2) 
            WHILE @start2 < LEN(@list2) + 1 BEGIN 
                BEGIN 
                IF @end2 = 0 
                begin 
                SET @end2 = LEN(@list2) + 1
                end
                END
            Insert Into @RtnValue2 (id,value,filename)
            Select @cnt2,SUBSTRING(@list2, @start2, @end2 - @start2) ,@file
            SET @start2 = @end2 + 1 
            SET @end2 = CHARINDEX(@SplitOn2, @list2, @start2)
            set @cnt2= @cnt2+1   
            END 
            insert into dbo.TempSplit2
        select @file,@rt,@valu,@idz,value,id,@rowcnt2 from @RtnValue2
        delete from @RtnValue2
        set  @cnt2  =0

FETCH NEXT From HL7_Cursor3 into @file,@rt,@valu,@idz ,@rowcnt2                                 
 End                        
Close hl7_cursor3
deallocate hl7_cursor3

回答1:


The code on the post should parse through the HL7 Message delimiters of | and ^, if you want to parse through the ~ delimiter, then you will need to add another cursor for it.

Here's the end result of what it should look like:

Row   filename         RecordType Value    id Subvalue  id2  RecordTypeID                                 
------------------------------------------------------------------
1     HL7_filename.dat    MSH      MSH      0   MSH     0       1
2     HL7_filename.dat    MSH      ^~\&     1           0       1
3     HL7_filename.dat    MSH      ^~\&     1   ^~\&    1       1
4     HL7_filename.dat    MSH     EIH7      2   EIH7    0       1

From here on, you can map the subvalue data based on the "RecordType", "id" and "id2" to your corresponding tables. RecordTypeID counter is used if the same segment was sent more than once in one file.

Hopefully this will be a help to some who are stuck



来源:https://stackoverflow.com/questions/44530932/how-to-parse-hl7-delimiters-using-only-ms-sql-syntax

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!