2011-10-22 37 views
1

我正在使用SSMS 2008,並且我有以下標量函數來接收文本字符串並從Microsoft Word中刪除所有元標記。標籤包含在「< ...>」中,並且在一列中可以有任意數量的標籤/記錄。如何創建一個TSQL替換表函數?

我基於下面的代碼創建了一個標量函數來更新此列中的每一行。但是這個標量函數需要很長時間才能完成。這個表的函數版本會更快嗎?如果是這樣,我怎麼能重寫這個函數來使它表?

WHILE PATINDEX('%[%]%', @str) > 0 
    SET @str = REPLACE(@str, SUBSTRING(@str, 
      PATINDEX('%[%]%', @str), 1), '') 
SELECT @str 

此表功能幾乎可行。但事實證明,它現在不起作用。問題是我試圖在臨時表上使用這個函數。原始表沒有int PK,我不能將一列添加到原始表中。

所以我試圖創建一個基於此表的視圖,然後添加一個PK int列到它。因爲當我試圖創建這個額外的PK INT列(「N」)的觀點,它給了我一個錯誤:

Msg 156, Level 15, State 1, Line 1 
Incorrect syntax near the keyword 'identity'. 

但是ALTER VIEW不支持添加列。有沒有另一種方法來做到這一點?這是我原來的臨時表,我想修改:

select [progress_note].[note_text], [progress_note].[event_log_id] 
INTO #TEMP_PN 
from [evolv_cs].[dbo].[progress_note] 
group by [progress_note].[event_log_id], [progress_note].[note_text] 

[note_text]爲varchar(max)和event_log_id的唯一標識符。因此[note_text]包含一串「<」和「>」字符。我如何修改這個dbo.ufn_StripHTML函數?

我試過你最新的代碼,這是超級快!但是,在通過5700行後,我得到以下錯誤:

Msg 537, Level 16, State 2, Line 1 
Invalid length parameter passed to the LEFT or SUBSTRING function. 

您知道這是關於什麼嗎?

+1

SQL Server的CLR是值得考慮的選擇。 –

+0

如果您的note_text長度>我提供的500個測試示例,那麼您可能需要更多的行。還要確保在修改我的varchar(8000) - > max後進行測試。閱讀更多此處瞭解 - > http://www.sqlservercentral.com/articles/T-SQL/62867/ –

回答

1

繼承人我寫了一個函數來刪除HTML標記(對< ...>)使用基於集合的接近。我很感興趣,看看您是否可以重新使用來剝離Word元標記。

----------------------------------------------------------- 
-- 1. create a number table (this is just a utility table) 
----------------------------------------------------------- 
set nocount on; 
if object_id('dbo.Number') is not null 
begin 
    drop table dbo.Number; 
end 
go 

create table dbo.Number (n int identity(1,1) primary key); 

insert dbo.Number default values ; 
while scope_identity() < 500 
    insert dbo.Number default values ; 

----------------------------------------------------------- 
-- 2. create the function (leverages the utility table) 
----------------------------------------------------------- 
if object_id('dbo.ufn_StripHTML') is not null 
begin 
    drop function dbo.ufn_StripHTML; 
end 
go 
create function dbo.ufn_StripHTML 
    ( @Input  varchar(8000), 
     @Delimiter char(1) 
    ) 
returns varchar(8000) 
as 
begin 

    declare @Output varchar(8000) 
    select @Input = replace(replace(@input, '<', @Delimiter), '>', @Delimiter) 

    select @Output = isnull(@Output, '') + s 
    from ( select row_number() over (order by n.n asc) [i], 
       substring(@Delimiter + @Input + @Delimiter, n.n + 1, charindex(@Delimiter, @Delimiter + @Input + @Delimiter, n.n + 1) - n.n - 1) [s] 
      from dbo.Number n 
      where n.n = charindex(@Delimiter, @Delimiter + @Input + @Delimiter, n.n) and 
       n.n <= len(@Delimiter + @Input) 
      ) d 
    where i % 2 = 1 

    return @Output 

end 
go 

----------------------------------------------------------- 
--3. Example of calling the function when you query 
----------------------------------------------------------- 
if object_id('tempdb..TEMP_PN') is not null 
    drop table #TEMP_PN; 

create table #TEMP_PN (note_text varchar(max), event_log_id int); 

insert into #TEMP_PN 
    select '<b>Some very large bolded text here!</b>', 1 union all 
    select 'no tags here', 2 union all 
    select '<html><body><h1>My First Heading</h1><p>My first paragraph.</p></body></html>', 3 

select [Strip] = dbo.ufn_StripHTML(note_text, '|'), 
     [Orig] = note_text, 
     event_log_id 
from #TEMP_PN 

編輯:移植標表

alter function dbo.ufn_StripHTMLTable 
    ( @Input  varchar(8000), 
     @Delimiter char(1) 
    ) 
returns @ret table (OutString varchar(8000)) 
as 
begin 
    declare @Output varchar(8000) 
    select @Input = replace(replace(@input, '<', @Delimiter), '>', @Delimiter) 

    select @Output = isnull(@Output, '') + s 
    from ( select row_number() over (order by n.n asc) [i], 
         substring(@Delimiter + @Input + @Delimiter, n.n + 1, charindex(@Delimiter, @Delimiter + @Input + @Delimiter, n.n + 1) - n.n - 1) [s] 
       from dbo.Number n 
       where n.n = charindex(@Delimiter, @Delimiter + @Input + @Delimiter, n.n) and 
         n.n <= len(@Delimiter + @Input) 
      ) d 
    where i % 2 = 1; 

    insert into @ret 
     values(@Output); 

    return; 
end 
+0

謝謝!我很好奇 - 用於@delimiter的是什麼? – salvationishere

+0

只需要給它一個不在要解析的數據中的字符。我使用管道,但如果您的數據中有管道,則可配置 –

+0

Hey Nathan,請您再看看我更新的問題嗎? – salvationishere