Sql 连接到表名保存在列中的表

Sql 连接到表名保存在列中的表,sql,sql-server,tsql,Sql,Sql Server,Tsql,我有这张桌子: ProjectHistory( Id INT, CreatedDate DateTime, CreatedBy INT, TableName NVARCHAR(100), FieldName NVARCHAR(150), Value NVARCHAR(MAX), LookupTableName NVARCHAR(100), Look

我有这张桌子:

    ProjectHistory(
        Id INT, 
        CreatedDate DateTime, 
        CreatedBy INT, 
        TableName  NVARCHAR(100),
        FieldName  NVARCHAR(150),
        Value NVARCHAR(MAX), 
        LookupTableName NVARCHAR(100), 
        LookupTableIdFieldName NVARCHAR(150), 
        LookupTableValueFieldName NVARCHAR(150)
    )
此表包括项目的更改历史记录。因此,它说明了何时以及由谁更改了表中的哪个字段。如果跟踪更改的字段来自查找表,则保存查找表名称、ID字段名称和值字段名称(这是数据库的简化版本,实际数据库的结构略有不同)

我对插入此表没有任何问题。问题是当我想向用户显示数据,并且我想加入查找表以显示查找值而不是ID时

表中记录的一个示例:

    TableName  FieldName  Value LookupTableName   LookupTableIdFieldName LookupTableValueFieldName
    ---------  ---------  ----- ---------------   ---------------------- -------------------------
    "Project"  "StatusId" 4     "ProjectStatuses" "StatusId"              "StatusName"

我想知道什么是查询这个表并为更改加载查找表值的最佳和最有效的方法。例如,对于上面的记录,我想显示StatusId为4的StatusName(如“已拒绝”),以及其他审核值,如CreatedBy和CreatedDate。

这是一种痛苦。动态sql:

declare @tc table (id int identity primary key,  tbl varchar(20), lu varchar(20), luv int, col varchar(20));
insert into @tc values ('bid', 'auctionID', 1, 'BiddingPrice');
declare @tbl varchar(20);
declare @lu varchar(20);
declare @luv int;
declare @col varchar(20);
select @tbl = tbl, @col = col, @lu = lu, @luv = luv from @tc where id = 1;
declare @sql varchar(100) = 'select b.' + @col + ' ' +
                            'from ' + @tbl + ' b ' +
                            'where b.' + @lu + ' = ' + cast(@luv as varchar(10));
select @sql;
exec(@sql);
为什么要将
NVARCHAR(MAX)
用于
Value
?这应该是一个
int

为什么不将实际值存储在
ProjectHistory
中,省去很多麻烦呢?如果有人更改了查找表中的值,则项目历史记录不再有效

另一种选择是只使用一个具有复合键的查找表

masterlookupVarchar  
id int   composite 
row int  primary key
val varchar(100) not null 

简单的答案是你不能。不能使用列的值来定义相关数据是什么表。这意味着你有两个选择,两个都不是“好的”。第一种方法是对每个可能的表使用
左联接
;如果您有很多表,这可能会执行得很差。如果一次只从一个链接表中获取数据,那么可以改用动态SQL。然而,这种设置会导致糟糕的数据库设计,因此最好的答案是实际修复设计,而不是尝试编写查询以使用现有的数据。连接到其他表的唯一可行方法是使用基于ProjectHistory表的动态SQL。无论如何,您的模式设计看起来像EAV。谢谢您的评论。正如我所说的,这不是实际的模式设计,实际的模式有点不同,更规范化。我只是想让这里简单一点。除此之外,设计背后总是有一个需求,我认为这里不是讨论这个问题的地方。我以前尝试过动态查询,但没有找到一个好的解决方案。如果您能发布您的解决方案,我将不胜感激。@Larnu。正如拉努指出的,没有什么好的解决办法。我的建议是使用动态SQL的存储过程。通常建议在将对象名称组合到查询中时使用它。@哈博:是的,同意。谢谢,有多个查找表。所以,对于你的工作答案,我必须用游标或其他不可取的方法来包装这段代码。@Bahman,你有更好的方法吗?这是对上述问题的回答。你不需要一个全面的答案吗?值是nvarcahr(max),因为它可以保存int以外的其他值。它保存任何项目字段上的每个值更改。与查询结果相比,在此表中插入记录时的性能对我来说更重要。这就是为什么我在插入记录时避免使用额外的数据库查询来获取查找值。然而,如果我找不到更好的方法,我就得照你说的去做