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时,我相对比较环保,所以如果我错了,请赐教!另外,如果对总体领域问题有更好的整体解决方案,那么也会受到欢迎和赞赏:)
谢谢你,这很有道理。我不得不稍微调整一下,但是这让我走上了一条更干净的解决方案。 – Gerald