2016-10-12 49 views
1

嘗試替換我的數據庫中有兩個表的字符串。在TABLE_2更換使用第一個替換爲輸入的結果:使用SQL REPLACE替換字符串和替換是另一個替換的結果

當前狀態(字符串只是一個替身,它可以是任何東西,最重要的部分是破折號):

|table_1 - col1| |table_2 - col1   |  
---------------- ------------------------------ 
|string-1  | |text string-1 text string-3 |  
|string-2  | |text string-3 string-2 t-ext| 
|string-3  | |string-2 text string-3 te-xt| 

期望的結果:

|table_1 - col1 | |table_2 - col1    |  
----------------- ------------------------------ 
|string_1  | |text string_1 text string_3 |  
|string_2  | |text string_3 string_2 t-ext| 
|string_3  | |string_2 text string_3 te-xt| 

簡單地說我想和_更換-在TABLE_1並執行上TABLE_2相應的替代品。

想出了第一部分,但我想不通的TABLE_2更換部件:

SELECT col1, REPLACE(col1, '-', '_') as Replacement 
FROM table_1 
where col1 like '%-%' 

我需要做這樣的事情(這個代碼是不正確的):

SELECT REPLACE(col1, 
    SELECT [col1] FROM [table_1] where col1 like '%-%', 
    SELECT REPLACE([col1], '-', '_') FROM [table_1] where col1 like '%-%')  
from table_2 
+0

哪些DBMS您使用的? –

+0

感謝您的期待,MSSQL –

+0

我不確定我是否關注你 - 如果你可以爲一張桌子做,爲什麼不爲另一個呢? –

回答

1

對於不超過2置換

SELECT t2.col2, REPLACE(REPLACE(t2.col2,t1.col1,REPLACE(t1.col1, '-', '_')),t3.col1,REPLACE(t3.col1, '-', '_')) 
FROM table_2 t2 
JOIN table_1 t1 ON t2.col2 like '%' +t1.col1+'%' AND t1.col1 LIKE '%-%' 
LEFT JOIN table_1 t3 ON t3.col1 <> t1.col1 AND t2.col2 LIKE '%'+t3.col1+'%' AND t3.col1 LIKE '%-%' 
WHERE t2.col2 LIKE '%-%' 
+0

如果table_2 col1通常有3個字符串要替換,會發生什麼情況? – qxg

+0

@qxg當替換的數量可能相當大時,我最好選擇遞歸。 – Serg

1

這是完全的ad-hoc,沒有遞歸需要:

DECLARE @table_1 TABLE(ID INT IDENTITY,col1 VARCHAR(100)); 
INSERT INTO @table_1 VALUES  
('string-1'),('string-2'),('string-3'); 

DECLARE @table_2 TABLE(ID INT IDENTITY,col1 VARCHAR(100)); 
INSERT INTO @table_2 VALUES  
('text string-1 text string-3'),('text string-3 string-2 t-ext'),('string-2 text string-3 te-xt'); 

- 首CTE替換

WITH t1New AS 
(
    SELECT ID AS t1_ID 
      ,t1.col1 AS t1c1 
      ,REPLACE(t1.col1,'-','_') AS new_t1c1 
    FROM @table_1 AS t1 
) 

- 第二個CTE拆分在坯件上

,t2Splitted AS 
(
    SELECT ID 
      ,col1 AS t2c1 
      ,CAST('<x>' + REPLACE(t2.col1,' ','</x><x>') + '</x>' AS XML) AS Casted 
    FROM @table_2 AS t2 
) 

--This CTE映射t2的字符串在T1的值值分配零件

,Mapped AS 
(
    SELECT t1New.* 
      ,t2Splitted.ID AS t2_ID 
      ,ROW_NUMBER() OVER(PARTITION BY t2Splitted.ID ORDER BY (SELECT NULL)) AS PartIndex 
      ,part.value('.','nvarchar(max)') AS Part 
    FROM t2Splitted 
    CROSS APPLY t2Splitted.Casted.nodes('/x') AS A(part) 
    LEFT JOIN t1New ON t1New.t1c1=part.value('.','nvarchar(max)') 
) 

- 如果有映射,新的值取,否則取舊值

,NewValues AS 
(
    SELECT * 
      ,CASE WHEN t1c1 IS NOT NULL THEN new_t1c1 ELSE Part END AS newValue 
    FROM Mapped 
) 

--The最終CTE再會連接用空格字符串中的原始順序

,Final AS 
(
    SELECT nv1.t2_ID 
     ,(SELECT ' ' + nv2.newValue 
     FROM NewValues AS nv2 
     WHERE nv2.t2_ID=nv1.t2_ID 
     ORDER BY PartIndex 
     FOR XML PATH('')) AS FinalValue 
    FROM NewValues AS nv1 
    GROUP BY nv1.t2_ID 
) 

- 這最後一個值是用於更新原始表

UPDATE t2 SET t2.col1=Final.FinalValue 
FROM @table_2 AS t2 
INNER JOIN Final ON Final.t2_ID=t2.ID 

怎麼了你:UPDATE T1,這是一個班輪和最終值甩掉尾隨的空間:-)

SELECT * FROM @table_2 
1

基於變量的替換可以替換爲表格來完成。

DECLARE @Raw NVARCHAR(MAX) = '...'; 
SELECT @Raw= REPLACE(@Raw, P, R) 
FROM (VALUES ('string-1', 'string_1'), 
      ('string-2','string_2'), 
      ('string-3','string_3'), 
      ('string-4','string_4'), 
) AS T(P, R); 

反對錶執行相同的邏輯,思考一些之類的語句

SELECT col1, MultipleReplace(col1, replacement_table(P, R)) 
FROM some_table 

所以創建一個接受一個字符串輸入和替換表的功能。爲了將表傳遞給函數,我們必須創建一個表類型。

CREATE TYPE dbo.MulReplacements AS TABLE 
(
    Pattern NVARCHAR(MAX) NOT NULL, 
    Replacement NVARCHAR(MAX) NOT NULL 
) 

然後,該功能將

CREATE FUNCTION dbo.MulReplace(
    @string AS NVARCHAR(MAX), 
    @replacements AS dbo.MulReplacements READONLY 
) 
RETURNS NVARCHAR(MAX) 
AS 
BEGIN 
    DECLARE @result AS NVARCHAR(MAX) = @string; 

    SELECT @result = REPLACE(@result, R.Pattern, R.Replacement) 
    FROM @replacements AS R; 

    RETURN @result; 
END 

把所有連同動態查詢做的

DECLARE @replacement AS dbo.MulReplacements; 

INSERT INTO @replacement 
SELECT col1, REPLACE(col1, '-', '_') 
FROM (VALUES ('string-1'), ('string-2'), ('string-3')) AS table_1(col1) 

SELECT col1, dbo.Mulreplace(col1, @replacement) 
FROM (VALUES ('text string-1 text string-3'), ('text string-3 string-2 t-ext'), ('string-2 text string-3 te-xt')) AS table_2(col1) 
1

的一種方式。替換實際的表名和列名(註釋在哪裏改變)。

DECLARE @colNames VARCHAR(MAX) = '' 
SELECT @colNames = @colNames + ', [' + table1_Col1 + ']' FROM tableName1 -- Table1 Column and Table1 Name 
DECLARE @ReqColNames VARCHAR(MAX) = STUFF(@colNames, 1, 1, '') 

DECLARE @int int 
SELECT @int = count(*) FROM tableName1 -- Table1 Name 
DECLARE @replace varchar(max) = replicate('REPLACE(', @int) + 't2.table2_Col2' -- Table2 Column 

DECLARE @replaceCols varchar(max) = '' 
SELECT @replaceCols = @replaceCols + ', r.[' + table1_Col1 + '], replace(r.[' + table1_Col1 + '], ''-'', ''_''))' FROM tableName1 -- Table1 Column and Table1 Name 
DECLARE @ReplaceString varchar(max) = @replace + @replaceCols 


DECLARE @cmd varchar(max) = 'SELECT ' + @ReplaceString + ' FROM 
(
    SELECT * FROM tableName1 
    PIVOT 
    (MAX (table1_Col1) FOR table1_Col1 IN (' + @ReqColNames + ')) x 
) r 
CROSS JOIN tableName2 t2' 

EXEC(@cmd) 

靜態查詢:上面的代碼(顯示上面有哪些動態代碼正在生成):

Select replace(replace(replace(t2.table2_Col2 
     , r.[string-1], replace(r.[string-1], '-', '_')) 
     , r.[string-2], replace(r.[string-2], '-', '_')) 
     , r.[string-3], replace(r.[string-3], '-', '_')) 
from 
(
    Select * from tableName1 
    PIVOT 
    (MAX (table1_Col1) FOR table1_Col1 IN ([string-1], [string-2], [string-3])) x 
) r 
CROSS JOIN tableName2 t2 

輸出:

text string_1 text string_3 
text string_3 string_2 t-ext 
string_2 text string_3 te-xt