2017-06-13 113 views
-1

共享此代碼僅使用MS SQL解析原始HL7數據語法。這是分割所有|的快捷方式和^分隔符並將每個數據存儲爲一行。 我想分享一下,因爲我一直在四處尋找解決方法,嚴格通過SQL語法解析HL7消息,並且無法找到任何資源。如何僅使用MS SQL解析HL7分隔符語法

我會把它放在那裏,這不是導入HL7消息到SQL數據庫的最有效的方法。還有其他更好的方法(即:C#應用程序 - HL7> XML> DB,第三方軟件,BULK INSERT等)。

這是SQL語法,它將通過|和^分隔符並將它們存儲在TempSplit和TempSplit2表下的行中。這裏的假設是你有一種方法可以將原始HL7文件導入數據庫(即:SSIS)。從此,您可以將存儲在TempSplit2下的結果映射到SQL Segment表。

ID Column =每個值之間的位置|

ID2欄=^

之間的每個值作爲可以導入HL7文件生(原樣)成2列的第一測試的位置。見下面的示例:

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

編輯:正如下面scsimon提到,光標循環兩次,並解析所有數據,而不是什麼你只需要。在我目前的項目中,這很重要,但可能不在你的項目上。隨意修改

下面的代碼:

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

我沒有DV你的幫助,但你真的應該看看[這些分離器中的一個(http://www.sqlservercentral.com/articles/ Tally + Table/72993 /),因爲你擁有的**肯定會有糟糕的表現。**這些會將你的字符串從任何分隔符中分離出來。在這種情況下,你只需要分割字符串的[substring()](https://docs.microsoft.com/en-us/sql/t-sql/functions/substring-transact-sql),然後選擇你想要的列。您需要的唯一遊標是循環遍歷每個單獨的文件,這是您最外層的遊標。其餘部分將消失 – scsimon

+0

您也可以僅使用適當的分隔符[BULK INSERT](https://docs.microsoft.com/en-us/sql/t-sql/statements/bulk-insert-transact-sql)並然後放下你不需要的東西。 – scsimon

+0

感謝您的評論@scsimon。目前,這可以完成我的工作(儘管有性能問題)。我感謝您的意見,我會考慮進入BULK INSERT和我的拆分器 – Isaiah3015

回答

0

帖子上的代碼應通過的HL7消息分隔符解析|和^,如果你想通過〜分隔符解析,那麼你需要爲它添加另一個光標。

下面是它應該是什麼樣子的最終結果是:

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 

從這裏開始,你可以根據「記錄類型」,「ID」和「ID2」的子值數據映射到相應的表。如果同一個段在一個文件中多次發送,則使用RecordTypeID計數器。

希望這將是一些誰被卡住