2014-02-20 122 views
0

所以我有一些表包含一個外鍵,根據上下文引用不同的表和字段。我有一個關鍵的源表,其中包含相關的表和字段名稱。然後,我需要能夠查找這些表/字段中的值。如何使用動態表和字段名稱連接數據

我把它簡化爲示範下表/數據我有:

CREATE TABLE [dbo].[WorkOrderStatus](
    [WorkOrderStatusId] [int] IDENTITY(1,1) NOT NULL, 
    [Name] [nvarchar](60) NOT NULL 
) ON [PRIMARY] 

CREATE TABLE [dbo].[Note](
    [NoteId] [int] IDENTITY(1,1) NOT NULL, 
    [NoteKeySourceId] [int] NULL, 
    [KeyValue] [int] NULL, 
    [Note] [nvarchar](max) NOT NULL, 
) ON [PRIMARY] 

CREATE TABLE [dbo].[NoteKeySource](
    [NoteKeySourceId] [int] IDENTITY(1,1) NOT NULL, 
    [SourceTable] [nvarchar](60) NOT NULL, 
    [SourceField] [nvarchar](60) NOT NULL, 
    [SourceTextField] [nvarchar](60) NOT NULL, 
) ON [PRIMARY] 

GO 

INSERT INTO WorkOrderStatus VALUES('Open') 
DECLARE @OpenStatusId int = SCOPE_IDENTITY(); 

INSERT INTO WorkOrderStatus VALUES('Closed') 
DECLARE @ClosedStatusId int = SCOPE_IDENTITY(); 

INSERT INTO NoteKeySource VALUES('WorkOrderStatus', 'WorkOrderStatusId', 'Name') 
DECLARE @WorkOrderSource int = SCOPE_IDENTITY(); 

INSERT INTO Note VALUES(@WorkOrderSource, @OpenStatusId, 'Opened the work order') 
INSERT INTO Note VALUES(@WorkOrderSource, @ClosedStatusId, 'Closed the work order') 

所以我需要能夠查詢說明的列表,包括SourceTextField在NoteKeySource提到,通過鑑定核心價值。

這裏是我現在的SP,其工作原理:

CREATE PROCEDURE [dbo].[spGetNotes] 
AS 
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED 

CREATE TABLE #NoteTable (
    NoteId int NOT NULL, 
    SourceTable nvarchar(60), 
    SourceField nvarchar(60), 
    SourceTextField nvarchar(60), 
    KeyValue int, 
    Context nvarchar(MAX), 
    Note nvarchar(MAX), 
) 

INSERT INTO #NoteTable (NoteId, SourceTable, SourceField, SourceTextField, KeyValue, Note) 
    SELECT N.NoteId, NKS.SourceTable, NKS.SourceField, NKS.SourceTextField, N.KeyValue, N.Note 
     FROM Note AS N 
      LEFT OUTER JOIN NoteKeySource AS NKS 
       ON NKS.NoteKeySourceId = N.NoteKeySourceId 

DECLARE @Context nvarchar(max) 

DECLARE @Sql nvarchar(255); 
DECLARE @SqlDecl nvarchar(255) = N'@Key int, @Ctx nvarchar(MAX) OUTPUT'; 


DECLARE @NoteId int, @KeyValue int, @SourceTable nvarchar(60), @SourceField nvarchar(60), @SourceTextField nvarchar(60) 

DECLARE db_cursor CURSOR FOR SELECT SourceTable, SourceField, SourceTextField, KeyValue 
     FROM #NoteTable WHERE SourceTable IS NOT NULL FOR UPDATE OF Context 


OPEN db_cursor 
FETCH NEXT FROM db_cursor INTO @SourceTable, @SourceField, @SourceTextField, @KeyValue 

WHILE @@FETCH_STATUS = 0 
BEGIN 
    SET @Sql = N'SELECT @Ctx = ' + @SourceTextField + ' FROM ' + @SourceTable + ' WHERE ' + @SourceField + '= @Key'; 

    EXECUTE sp_executesql @Sql, @SqlDecl, @Key = @KeyValue, @Ctx = @Context OUTPUT 

    UPDATE #NoteTable SET [email protected] WHERE CURRENT OF db_cursor 

    FETCH NEXT FROM db_cursor INTO @SourceTable, @SourceField, @SourceTextField, @KeyValue 
END 

CLOSE db_cursor 
DEALLOCATE db_cursor 


SELECT NoteId, Context, Note from #NoteTable 

DROP TABLE #NoteTable 

RETURN 0 

調用spGetNotes回報:

1:打開:打開工作秩序

2:關閉:關閉工作order

它的工作原理,但它非常醜陋,我只想知道是否有一個更好/更清潔/更合適的方式來做到這一點,而不使用遊標或while循環。我的理解是,動態SQL不能用於普通SQL的子查詢中,所以這是我能想到的最好的。

當談到SQL時,我相對比較環保,所以如果我錯了,請賜教!另外,如果對總體領域問題有更好的整體解決方案,那麼也會受到歡迎和讚賞:)

回答

1

創建一個視圖,在源表中提供單個EAV疊加層。然後將NoteKeySource連接到它。

CREATE VIEW AllSources AS (
    SELECT 
    'SourceTable1' AS [SourceTable], [SourceField], [SourceTextField] 
    FROM SourceTable1 
    UNPIVOT([SourceTextField] FOR [SourceField] IN 
     ('Table1Field1','Table1Field2','Table1Field3','Table1Field4') 
) p 
    UNION ALL 
    SELECT 
    'SourceTable2' AS [SourceTable], [SourceField], [SourceTextField] 
    FROM SourceTable2 
    UNPIVOT([SourceTextField] FOR [SourceField] IN 
    ('Table2Field1','Table2Field2') 
) p 
    UNION ALL 
    SELECT 
    'SourceTable3' AS [SourceTable], [SourceField], [SourceTextField] 
    FROM SourceTable3 
    UNPIVOT([SourceTextField] FOR [SourceField] IN 
    ('Table3Field1','Table3Field2','Table3Field3') 
) p 
    --etc 
) 
+0

謝謝你,這很有道理。我不得不稍微調整一下,但是這讓我走上了一條更乾淨的解決方案。 – Gerald

相關問題