2015-06-25 89 views
0

我有我想寫從返回查詢存儲包含在關鍵位置的佔位符,像這樣的標記HTML模板表...返回正則表達式從SQL查詢匹配

<div> 
    <div>{FirstName}</div> 
    <div>{LastName}</div> 
</div> 

列出所有行中使用的所有佔位符。

SELECT Template 
FROM MyTable 
WHERE ???? 

因此,對於上面的例子,結果我想要的是......

{FirstName} 
{LastName} 

我已經看到了SQL使用正則表達式的人,但無法弄清楚如何只返回匹配,而不是整列值。 同樣值得注意的是,我希望每場比賽有理想的結果,但是如果我得到匹配的每行逗號分隔列表或將做的事情。

+0

您的匹配由{}標識,對嗎? SQL Server或MySQL?你在你的標籤中使用兩個! – Ionic

+0

我的不好,mysql被刪除。 – War

+0

K,我會提供 – Ionic

回答

1

我會用numbers table來解決這個問題,無論如何它都非常有用,所以如果你沒有,我會考慮創建一個,但爲了完整的答案,我會假設你沒有一個並且不能創建一個。在這種情況下,你可以很容易地使用動態生成號碼列表:

WITH N1 AS (SELECT N FROM (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) n (N)), 
N2 (N) AS (SELECT 1 FROM N1 AS N1 CROSS JOIN N1 AS N2), 
N3 (N) AS (SELECT 1 FROM N2 AS N1 CROSS JOIN N2 AS N2), 
--N4 (N) AS (SELECT 1 FROM N3 AS N1 CROSS JOIN N3 AS N2) 
Numbers (Number) AS (SELECT ROW_NUMBER() OVER(ORDER BY N) FROM N3) 

SELECT Number 
FROM Numbers; 

這將啓動與一個table value constructor(N1)創建10行的表,然後它加入與自己這個表獲得100行(N2)的表格,然後將N2連接到自身以獲得10,000行(N3),這可以根據需要重複,最後使用ROW_NUMBER()在每行中獲得序號。 Aaron Bertrand在generating a set or sequence without loops上完成了一個非常全面的系列,並且這種方法出現在最前面(作爲一種即時創建表格的方法)。

一旦你有了這個號碼錶,您可以在加入到您的模板使用SUBSTRING找到每個"{"的位置:

SELECT t.Template, 
     StartPosition = n.Number 
FROM dbo.T 
     INNER JOIN Numbers n 
      ON SUBSTRING(t.Template, n.Number, 1) = '{'; 

你的榜樣,這將返回16,和43。然後你可以使用CHARINDEX找到下面每個"{""}"

SELECT t.Template, 
     StartPosition = n.Number, 
     EndPosition = CHARINDEX('}', t.template, n.Number) + 1 
FROM dbo.T 
     INNER JOIN Numbers n 
      ON SUBSTRING(t.Template, n.Number, 1) = '{'; 

然後你就可以再次使用SUBSTRING提取術語之間的每個開始和結束位置。因此,一個完整的示例應該是:

DECLARE @T TABLE (Template NVARCHAR(MAX)); 
INSERT @T (Template) 
VALUES ('<div> 
    <div>{FirstName}</div> 
    <div>{LastName}</div> 
</div>'); 

WITH N1 AS (SELECT N FROM (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) n (N)), 
N2 (N) AS (SELECT 1 FROM N1 AS N1 CROSS JOIN N1 AS N2), 
N3 (N) AS (SELECT 1 FROM N2 AS N1 CROSS JOIN N2 AS N2), 
--N4 (N) AS (SELECT 1 FROM N3 AS N1 CROSS JOIN N3 AS N2) 
Numbers (Number) AS (SELECT ROW_NUMBER() OVER(ORDER BY N) FROM N3) 

SELECT t.Template, 
     StartPosition = n.Number, 
     EndPosition = CHARINDEX('}', t.template, n.Number) + 1, 
     Term = SUBSTRING(t.template, n.Number, CHARINDEX('}', t.template, n.Number) + 1 - n.Number) 
FROM @T t 
     INNER JOIN Numbers n 
      ON SUBSTRING(t.Template, n.Number, 1) = '{'; 
+0

想像一個SQL人肯定會顛倒世界...這是令人印象深刻的東西,謝謝:) – War

+0

@ion解決方案有點容易理解,雖然所以我要去那個場合。 – War

+0

工程就像一個治療:)謝謝GarethD! – War

1

看到這個:

CREATE TABLE #temp(id int identity(1,1), template nvarchar(max)) 

INSERT INTO #temp(template) 
SELECT REPLICATE(N'<div> 
    <div>{FirstName}</div> 
    <div>{LastName}</div> 
</div>',1000) 

;WITH cte AS(
    SELECT id, 
     SUBSTRING(template,CHARINDEX(N'{',template),CHARINDEX(N'}',template)-CHARINDEX(N'{',template)+1) as match, 
     SUBSTRING(template,CHARINDEX(N'}',template)+1,LEN(template)) as templateRest 
    FROM #temp 
    UNION ALL 
    SELECT id, 
     SUBSTRING(templateRest,CHARINDEX(N'{',templateRest),CHARINDEX(N'}',templateRest)-CHARINDEX(N'{',templateRest)+1) as match, 
     SUBSTRING(templateRest,CHARINDEX(N'}',templateRest)+1,LEN(templateRest)) as templateRest 
    FROM cte 
    WHERE templateRest LIKE N'%}%' 
) 
SELECT t.id, t.template, c.match 
-- Only distinctive: 
-- SELECT DISTINCT t.id, t.template c.match 
FROM cte AS c 
INNER JOIN #temp AS t 
     ON c.id = t.id 
OPTION(MAXRECURSION 1000) -- if needed, this value could still be raised 

DROP TABLE #temp 
GO 

可以過濾它爲模板,並檢索所有比賽。

+0

感謝:) – War

+0

沒問題。只需提一點。如果您的模板中有超過100個模板標記,則可能會中止。您可以在查詢中使用「MAX_RECURSION」選項提高這些限制。只是要提到這一點。 – Ionic

+0

好了,做了一些測試,這實際上不起作用,它返回子模塊錯誤與我的模板:( – War