2015-05-13 12 views
0

我有一個用戶填寫的InfoPath表格。它獲得一個唯一的報告編號,並且在報告中他們可以選擇零個或多個受影響的部分,每個部分都有一堆列。受影響部件的列表可能隨着報告的處理而改變。向SharePoint提交或重新提交報表時,會調用SQL存儲過程,其參數包括列數據分號 - 用一個代表多行的NVARCHAR(MAX)分隔。存儲過程分析以分號分隔的NVARCHAR以填充表變量,然後將該表變量與將用於數據分析的主表合併。當用戶只有一個受影響的部件每個報告有給定的部件號時(因爲我的MERGE語句使用它來確定它是否需要更新現有的行或創建一個新的行),並且最初這是一個可以接受的限制。粗糙SQL摘要:MERGE使用表格變量時沒有明顯的匹配條件

CREATE TABLE [Report_to_Parts](
    [ID] [int] IDENTITY(1,1) NOT NULL, 
    [Report_ID] [nvarchar](255) NOT NULL, 
    [PartNumberOrdered] [nvarchar](255) NULL, 
    [OtherColumns] [nvarchar](255) NULL) 

CREATE PROCEDURE [MergeReport_sp] 
    @paramReport_ID nvarchar(255), 
    @paramPartNumberString nvarchar(MAX) = NULL, 
    @paramOtherColumnsString nvarchar(MAX) = NULL 
AS 
BEGIN 
    DECLARE @tempPartTable TABLE (
     [Report_ID] [nvarchar](255) NOT NULL, 
     [PartNumberOrdered] [nvarchar](255) NOT NULL, 
     [OtherColumns] [nvarchar](255) NULL) 

    DECLARE @WorkingPartNumberString nvarchar(255), 
     @WorkingOtherColumnsString nvarchar(255) 

    -- Magic to parse the semicolon delimited parameters omitted 
    WHILE (PartsRemainingToParse) 
    BEGIN 
     INSERT INTO @tempPartTable (
      [Report_ID], 
      [PartNumberOrdered], 
      [OtherColumns]) 
     VALUES (
      @paramReport_ID, 
      @WorkingPartNumberString, 
      @WorkingOtherColumnsString)   
    END 

    MERGE [Report_to_Parts] 
    USING @tempPartTable AS [Source] 
    ON (
     [Report_to_Parts].[Report_ID] = @paramReport_ID AND 
     [Report_to_Parts].[PartNumberOrdered] = [Source].[PartNumberOrdered]) 
    WHEN NOT MATCHED BY TARGET 
     THEN INSERT(
      [Report_ID], 
      [PartNumberOrdered], 
      [OtherColumns]) 
     VALUES (
      @paramReport_ID, 
      [Source].[PartNumberOrdered], 
      [Source].[OtherColumns]) 
    WHEN MATCHED 
     THEN UPDATE SET [OtherColumns]=[Source].[OtherColumns] 
    WHEN NOT MATCHED BY SOURCE AND [Report_to_Parts].[Report_ID] = @paramReport_ID 
     THEN DELETE; 
END 

目前工作的投入和結果,假設與123456 [REPORT_ID]部分不存在在[Report_to_Parts],但其他一些條目做:

EXEC MergeReport_sp 
    @paramReport_ID = N'123456', 
    @paramPartNumberString = N'Part 1;abcd-efg;Part 3;' 
    @paramOtherColumnsString = N'There are many;other columns;but I simplified;' 

SELECT * FROM [Report_to_Parts] WHERE [Report_ID] = N'123456' 

--------------------------------------------------------- 
| ID | Report_ID | PartNumberOrdered | OtherColumns  | 
| 05 | 123456 | Part 1   | There are many | 
| 06 | 123456 | abcd-efg   | other columns | 
| 07 | 123456 | Part 3   | but I simplified | 

EXEC MergeReport_sp 
    @paramReport_ID = N'123456', 
    @paramPartNumberString = N'Part 1;Part 3;New Part;' 
    @paramOtherColumnsString = N'Updates;Work;Too;' 

SELECT * FROM [Report_to_Parts] WHERE [Report_ID] = N'123456' 

----------------------------------------------------- 
| ID | Report_ID | PartNumberOrdered | OtherColumns | 
| 05 | 123456 | Part 1   | Updates  | 
| 07 | 123456 | Part 3   | Work   | 
| 08 | 123456 | New Part   | Too   | 

但因爲它試圖立足東西了PartNumberOrdered以下故障:

EXEC MergeReport_sp 
    @paramReport_ID = N'123456', 
    @paramPartNumberString = N'Part 1;Part 1;' 
    @paramOtherColumnsString = N'Thing 1;Thing 2;' 

現在我需要它能夠很好地處理與多個部件共享的部件號報告。關閉InfoPath和/或SharePoint不是一種選擇,也不會刪除分號解析方面。我正在考慮的選項:

  1. 每次調用存儲過程時,從[Report_to_Parts]中刪除具有匹配[Report_ID]的所有行並插入所有的@tempPartTable行。這是我想要進行數據分析的最終結果,但我擔心這非常低效,並且在使用系統時[ID]會變得不必要的大。
  2. 更改[Report_to_Parts],使其具有[ID]和[Report_ID]的組合鍵,並找出每個[Report_ID]從[1]開始以[ID]自動遞增的方式,然後刪除並插入。
  3. 從[Report_to_Parts]中爲[ID],SELECT添加一列到[tempPartTable]以獲取此[Report_ID]的表中已有的部件的[ID] s,並基於此設置@tempPartTable [ID] s,並且MERGE在[ID]上。
  4. 更改[Report_to_Parts],所以它有一個組合鍵,爲[ID]添加一列到@tempPartTable,自動從1開始遞增,MERGE由[ID]和[Report_ID]添加一列。

我很難想出3代碼,我也絕對可以接受其他想法。 Here's an earlier question I asked about this same system.

+0

是否有可能創建一個視圖,可以代表分隔數據一個實際的表?那麼你可以使用該表作爲更自然的方式來查詢數據庫嗎?老實說,我不確定視圖部分是否可能,因爲它似乎需要一個存儲過程來進行解析。 – KingOfAllTrades

+0

@KingOfAllTrades沒有'WHILE'循環我敢肯定它不可能解析字符串。但我的解析工作很好。這與我正在努力的結果有什麼關係。 –

+0

這也是我所懷疑的,但是也許你覺得你有一個絕招。我對此感興趣,因爲我也將SharePoint用作數據庫。票務系統,應用程序配置和簡單的CRUD應用程序。這些工作很好,你可以很容易地查詢數據庫,一旦你得到列表GUID。你能發佈表格變量和其他表格的樣本數據以及預期結果嗎? – KingOfAllTrades

回答

0

寫這個問題給了我一些想法,我可以通過選項4來解決這個問題。我修改了[Report_to_Parts],使[ID]不是一個標識,並且是一個複合主鍵和[Report_ID]。然後,我更新了存儲過程的代碼(也包括解析「神奇」的情況下,任何人都絆倒在這篇文章試圖解決分析問題):

ALTER PROCEDURE [MergeReport_sp] 
    @paramReport_ID nvarchar(255), 
    @paramPartNumberString nvarchar(MAX) = NULL, 
    @paramOtherColumnsString nvarchar(MAX) = NULL 
AS 
BEGIN 
    DECLARE @tempPartTable TABLE (
     [ID] [int] NOT NULL, 
     [Report_ID] [nvarchar](255) NOT NULL, 
     [PartNumberOrdered] [nvarchar](255) NOT NULL, 
     [OtherColumns] [nvarchar](255) NULL) 

    DECLARE @WorkingPartNumberString nvarchar(255), 
     @WorkingOtherColumnsString nvarchar(255), 
     @PartNumberPos int = CHARINDEX(N';', @paramPartNumberString), 
     @OtherColumnsPos int = CHARINDEX(N';', @paramOtherColumnsString), 
     @PartTableID int = 1 

    WHILE (ISNULL(@PartNumberPos,0) > 0) 
    BEGIN 
     IF @OtherColumnsPos = 0 SET @OtherColumnsPos = 1 

     SET @WorkingPartNumberString = NULLIF(SUBSTRING(@paramPartNumberString,1,@PartNumberPos - 1), '') 
     SET @WorkingOtherColumnsString = NULLIF(SUBSTRING(@WorkingOtherColumnsString ,1,@OtherColumnsPos - 1), '') 

     INSERT INTO @tempPartTable (
      [ID], 
      [Report_ID], 
      [PartNumberOrdered], 
      [OtherColumns]) 
     VALUES (
      @PartTableID, 
      @paramReport_ID, 
      @WorkingPartNumberString, 
      @WorkingOtherColumnsString) 

     SET @PartTableID = @PartTableID + 1 

     SET @paramPartNumberString = SUBSTRING(@paramPartNumberString, @PartNumberPos+1, LEN(@paramPartNumberString)) 
     SET @paramOtherColumnsString = SUBSTRING(@paramOtherColumnsString, @OtherColumnsPos +1, LEN(@paramOtherColumnsString)) 

     SET @PartNumberPos = CHARINDEX(N';',@paramPartNumberString) 
     SET @OtherColumnsPos = CHARINDEX(N';',@paramOtherColumnsString) 
    END 

    MERGE [Report_to_Parts] 
    USING @tempPartTable AS [Source] 
    ON (
     [Report_to_Parts].[ID] = [Source].[ID] AND 
     [Report_to_Parts].[Report_ID] = @paramReport_ID) 
    WHEN NOT MATCHED BY TARGET 
     THEN INSERT(
      [ID], 
      [Report_ID], 
      [PartNumberOrdered], 
      [OtherColumns]) 
     VALUES (
      [Source].[ID], 
      @paramReport_ID, 
      [Source].[PartNumberOrdered], 
      [Source].[OtherColumns]) 
    WHEN MATCHED 
     THEN UPDATE SET 
      [PartNumberOrdered] = [Source].[PartNumberOrdered] 
      [OtherColumns]=[Source].[OtherColumns] 
    WHEN NOT MATCHED BY SOURCE AND [Report_to_Parts].[Report_ID] = @paramReport_ID 
     THEN DELETE; 
END 
相關問題