2017-08-17 225 views
1

,我有以下我的數據庫中的文本字符串:SQL Server的一個字符串中刪除多個字符串

Value1 - Value2: Value3 - Value4: Value5 - Value6: 

我需要刪除破折號之間的破折號和一切,直到結腸

的上述結果將變成:

Value1: Value3: Value5: 

基本上,有可能是值的無窮無盡的,但也可能僅只是一個系列的一員。

需要注意的是:值可以是任何字符串!

有沒有簡單的方法來做到這一點?優選沒有UDF。任何人都可以幫我解決這個問題嗎?提前致謝!

編輯:我同意這是一個非常糟糕的實施。數據庫的其餘部分本身並不是這樣。這只是一張桌子。我從中得到的查詢將用於所有值分離爲多個別名的視圖中。感謝您的諒解

+1

在開始之前,它看起來像執行非常差在單個列使用文本EAV'的'。我強烈建議停止並規範您的模式。或者至少使用某種類型的結構化數據,比如'XML' /'JSON' – lad2025

+1

您應該修復數據模型,使每個實體有一行,每個值在單獨的行中。如果你不能這樣做,你應該解釋爲什麼你要在一個字符串中存儲多個值 - 這不是存儲數據的SQLish方式。 –

+2

請考慮重構您的數據庫。這是一個糟糕的設計。 閱讀[在數據庫列中存儲分隔列表真的不好嗎?](http://stackoverflow.com/questions/3653462/is-storing-a-delimited-list-in-a-database-column-really-那麼 - 壞),在那裏你會看到很多原因,爲什麼這個問題的答案是**絕對是!** –

回答

0
SELECT substring(NameValue, 1, charindex('_', NameValue)-1) AS Names, 
    substring(NameValue, charindex('_', NameValue)+1, LEN(NameValue)) AS Values 
FROM Table 

編輯:像這樣的東西放一個函數或存儲過程與臨時表組合應該適用於多行,這取決於你前行分隔符,你也應該刪除CHAR(13)開始:

DECLARE @helper varchar(512) 
DECLARE @current varchar(512) 
SET @helper = NAMEVALUE 
WHILE CHARINDEX(CHAR(10), @helper) > 0 BEGIN 
    SET @current = SUBSTRING(@helper, 1, CHARINDEX(CHAR(10), NAMEVALUE)-1) 
    SELECT SUBSTRING(@current, 1, CHARINDEX('_', @current)-1) AS Names, 
     SUBSTRING(@current, CHARINDEX('_', @current)+1, LEN(@current)) AS Names 
    SET @helper = SUBSTRING(@helper, CHARINDEX(CHAR(10), @helper)+1, LEN(@helper)) 
END 
SELECT SUBSTRING(@helper, 1, CHARINDEX('_', @helper)-1) AS Names, 
    SUBSTRING(@helper, CHARINDEX('_', @helper)+1, LEN(@helper)) AS Names 
+1

請不要使用並建議分割字符串的循環。這種類型的分路器的性能是可怕的。這是一個更好的選擇。 http://www.sqlservercentral.com/articles/Tally+Table/72993/和其他一些選項。 http://sqlperformance.com/2012/07/t-sql-queries/split-strings –

1

您可以使用拆分功能......儘管您的值不應該像這樣存儲在第一位。

declare @table table (col1 varchar(256)) 
insert into @table 
values 
('Value1 - Value2: Value3 - Value4: Value5 - Value6:') 

select 
    ReturnVal = replace(ltrim(left(Item,charindex('-',Item))),'-',':') 
from 
    @table 
    cross apply dbo.DelimitedSplit8K(col1,':') 
where 
    Item <> '' 

退貨

+-----------+ 
| ReturnVal | 
+-----------+ 
| Value1 : | 
| Value3 : | 
| Value5 : | 
+-----------+ 

或者,一個醜陋的黑客攻擊拿回來你想要的

select distinct 
    --ReturnVal = replace(ltrim(left(Item,charindex('-',Item))),'-',':') 
    ReturnVal = 'V' + STUFF((
      SELECT replace(left(Item,charindex('-',Item)),'-',':') 
      FROM 
      @table 
      cross apply dbo.DelimitedSplit8K(col1,':') 
    FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '') 
from 
    @table 
    cross apply dbo.DelimitedSplit8K(col1,':') 
where 
    Item <> '' 

退貨

ReturnVal 
Value1 : Value3 : Value5 : 

JEFF MODEN SPLITTER

CREATE FUNCTION [dbo].[DelimitedSplit8K] (@pString VARCHAR(8000), @pDelimiter CHAR(1)) 
--WARNING!!! DO NOT USE MAX DATA-TYPES HERE! IT WILL KILL PERFORMANCE! 

RETURNS TABLE WITH SCHEMABINDING AS 
RETURN 

/* "Inline" CTE Driven "Tally Table" produces values from 1 up to 10,000... 
enough to cover VARCHAR(8000)*/ 

    WITH E1(N) AS (
       SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
       SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
       SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 
       ),       --10E+1 or 10 rows 
     E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows 
     E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max 
cteTally(N) AS (--==== This provides the "base" CTE and limits the number of rows right up front 
        -- for both a performance gain and prevention of accidental "overruns" 
       SELECT TOP (ISNULL(DATALENGTH(@pString),0)) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4 
       ), 
cteStart(N1) AS (--==== This returns N+1 (starting position of each "element" just once for each delimiter) 
       SELECT 1 UNION ALL 
       SELECT t.N+1 FROM cteTally t WHERE SUBSTRING(@pString,t.N,1) = @pDelimiter 
       ), 
cteLen(N1,L1) AS(--==== Return start and length (for use in substring) 
       SELECT s.N1, 
         ISNULL(NULLIF(CHARINDEX(@pDelimiter,@pString,s.N1),0)-s.N1,8000) 
        FROM cteStart s 
       ) 
--===== Do the actual split. The ISNULL/NULLIF combo handles the length for the final element when no delimiter is found. 
SELECT ItemNumber = ROW_NUMBER() OVER(ORDER BY l.N1), 
     Item  = SUBSTRING(@pString, l.N1, l.L1) 
    FROM cteLen l 
; 
GO 
相關問題