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
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