2016-07-23 30 views
0

不知道如何標題的問題,但希望這是有道理:)如何自動將幾個函數調用的結果插入表中?

我有一個表(OldTable)與一個索引和一列逗號分隔列表。我試圖拆分列表中的字符串,並創建一個新的表,其索引與舊錶中連接的字符串的每個子字符串相關聯。

實施例:

OldTable 
index | list 
1  | 'a,b,c' 
2  | 'd,e,f' 

NewTable 
index | letter 
1  | 'a' 
1  | 'b' 
1  | 'c' 
2  | 'd' 
2  | 'e' 
2  | 'f' 

我已經創建了將分割字符串,並以1列表中返回每個子串作爲記錄作爲這樣的函數:

SELECT * FROM Split('a,b,c', ',', 1) 

,這將導致在:

Result 
index | string 
1 | 'a' 
1 | 'b' 
1 | 'c' 

我希望我可以使用這樣的功能:

SELECT * FROM Split((SELECT * FROM OldTable), ',') 

然後在舊函數中使用OldTable中的id和string列(通過稍微重寫)來創建NewTable。但據我所知,將表發送到函數不起作用,因爲我得到:「子查詢返回多個值...不預先...當子查詢用作表達式。」

我想到的一種解決方案就是在OldTable的所有行上按原樣運行該函數,並將每個調用的結果插入到NewT​​able中。但我不知道如何在沒有函數的情況下迭代每一行。而且我不能發送表格到一個函數中進行迭代,所以我回到了原點。

我可以手動做,但OldTable包含幾個記錄(1000左右),所以它看起來像自動化會更好。

有沒有辦法要麼:

  1. 遍歷OldTable逐行,潤透斯普利特()行,結果添加到newtable中在OldTable所有行。通過函數或通過常規的sql事務
  2. 重寫Split()以獲取表變量全部
  3. 完全擺脫該函數,只是在sql事務中執行它?

我寧願不使用過程(不知道是否有解決方案),主要是因爲我不希望DB內部的功能暴露在外面。如果這是「最好的」/唯一的路要走,我將不得不考慮它。我對SQL很陌生,因此可能是不必要的擔心。

這裏是我的斯普利特()函數,如果需要的話:

CREATE FUNCTION Split (
@string nvarchar(4000), 
@delimitor nvarchar(10), 
@indexint = 0 
) 
RETURNS @splitTable TABLE (id int, string nvarchar(4000) NOT NULL) AS 
BEGIN 
    DECLARE @startOfSubString smallint; 
    DECLARE @endOfSubString smallint; 

    SET @startOfSubString = 1; 
    SET @endOfSubString = CHARINDEX(@delimitor, @string, @startOfSubString); 

    IF (@endOfSubString <> 0) 
     WHILE @endOfSubString > 0 
     BEGIN 
     INSERT INTO @splitTable 
     SELECT @index, SUBSTRING(@string, @startOfSubString, @endOfSubString - @startOfSubString); 

     SET @startOfSubString = @endOfSubString+1; 
     SET @endOfSubString = CHARINDEX(@delimitor, @string, @startOfSubString); 
     END; 

    INSERT INTO @splitTable 
    SELECT @index, SUBSTRING(@string, @startOfSubString, LEN(@string)[email protected]+1);  

    RETURN; 
END 

希望我的問題,並試圖解釋,並可以理解。

回答

3

您正在尋找cross apply

SELECT t.index, s.item 
FROM OldTable t CROSS APPLY 
    (dbo.split(t.list, ',')) s(item); 

在新表中插入只需要一個insertselect into條款。

+0

確實,我非常感謝你!我唯一需要做的改變是「dbo.Split(t.list,',')AS s」而不是「dbo.Split(t.list,',')s(item)」。 –

相關問題