I don’t feel ready to comment on which is better, or about design approaches. Actually, I tend to not answer at all. However, I thought about your problem and that you took the time to clearly describe it, and that is how I approach it.
I would save each metadata data type in my table; So
Table MetaData_Text: ID int identity EntryID int KeyName nvarchar(50) KeyValue nvarchar(max)
MetaData_DateTime, MetaData_Boolean and MetaData_Numeric have the same structure as this, but with the corresponding different data type of the KeyValue column in each case.
The relationship between Entry and each of these tables is 0-Many; Although each row in each of these tables refers to one record.
To add a new metadata element for writing, I would simply use a stored procedure that takes an EntryID, a key name, and optional parameters for a possible metadata data type:
create procedure AddMetaData @entryid int, @keyname varchar(50), @textvalue varchar(max) = null, @datevalue datetime = null, @boolvalue bool = null, @numvalue float = null as ...
For the query, I would define a set of functions for managing each type of (a) metadata data type and (b) testing that needs to be performed for this data type, for example:
create function MetaData_HasDate_EQ(@entryid int, @keyname varchar(50), @val datetime) returns bool as begin declare @rv bool select @rv = case when exists( select 1 from MetaData_DateTime where EntryID = @entryid and KeyName = @keyname and KeyValue = @val) then 1 else 0 end; return @rv end
and include function references in the required request logic according to
SELECT ... FROM entry e ... WHERE (dbo.MetaData_HasText_EQ(e.EntryID, 'KeyName1', 'Test12345') <> 0 AND dbo.MetaData_HasDate_Btwn(e.EntryID, 'KeyName2', '01.09.2012 00:00:00', '01.04.2013 23:59:00') <> 0) OR (dbo.MetaData_HasNum_GT(e.EntryID, 'KeyName3', 15.3) <> 0 AND dbo.MetaData_HasBool_EQ(e.EntryID, 'KeyName4', 1) <> 0)