Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/77.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 关系数据库中的键值对_Sql_Database - Fatal编程技术网

Sql 关系数据库中的键值对

Sql 关系数据库中的键值对,sql,database,Sql,Database,有人有在数据库中存储键值对的经验吗 我一直在使用这种类型的表: CREATE TABLE key_value_pairs ( itemid varchar(32) NOT NULL, itemkey varchar(32) NOT NULL, itemvalue varchar(32) NOT NULL, CONSTRAINT ct_primarykey PRIMARY KEY(itemid,itemkey) )

有人有在数据库中存储键值对的经验吗

我一直在使用这种类型的表:

CREATE TABLE key_value_pairs ( 
    itemid           varchar(32) NOT NULL,
    itemkey         varchar(32) NOT NULL,
    itemvalue       varchar(32) NOT NULL,
    CONSTRAINT ct_primarykey PRIMARY KEY(itemid,itemkey)
)
例如,以下行可能存在:

 itemid            itemkey        itemvalue    
 ----------------  -------------  ------------ 
 123               Colour         Red            
 123               Size           Medium             
 123               Fabric         Cotton
此方案的问题在于提取数据所需的SQL语法相当复杂。 只创建一系列键/值列是否更好

CREATE TABLE key_value_pairs ( 
    itemid            varchar(32) NOT NULL,
    itemkey1        varchar(32) NOT NULL,
    itemvalue1      varchar(32) NOT NULL,
    itemkey2        varchar(32) NOT NULL,
    itemvalue2      varchar(32) NOT NULL,
 . . .etc . . .
)
这将更容易、更快地查询,但缺乏第一种方法的可扩展性。
有什么建议吗?

第一种方法很好。您可以创建一个提取所需数据的UDF并调用它。

根据经验,我发现某些键将被更广泛地使用或更频繁地查询。然后,我们通常将设计稍微去规范化,以便在主“item”表中包含一个特定字段

如果每个项目都有颜色,您可以将颜色列添加到项目表中。织物和尺寸可能使用较少,并且可以在键值对表中分开保存。您甚至可以在键值对表中保留颜色,但复制项表中的数据以获得性能优势

显然,这取决于数据以及您需要键值对的灵活性。它还可能导致属性数据的位置不一致。然而,反规范化确实极大地简化了查询并提高了它们的性能


我通常只考虑在性能变成和发布时去正规化,而不仅仅是简化查询。

第二个表是非常不规范的。我会坚持第一种方法。

如果可能的键很少,那么我会将它们存储为列。但是如果可能的键集很大,那么第一种方法是好的(第二种方法是不可能的)

还是说每件物品只能有有限数量的钥匙,但钥匙可以是一大套


您也可以考虑使用对象关系映射器来更容易地进行查询。

< P>第一个方法在提到的成本上更灵活。p> 第二种方法永远不会像你所说的那样可行。相反,您会这样做(根据您的第一个示例)

当然,这只有在数据量已知且变化不大的情况下才有效


一般来说,任何需要更改表的DDL以完成正常工作的应用程序都应该三思而后行。

我认为您做的是正确的,只要给定类型项的键/值经常更改。
如果它们是相当静态的,那么简单地扩大项目表就更有意义了

我们使用一种类似(但更复杂)的方法,在键/值周围有很多逻辑,以及每个键允许的值类型表。
这允许我们将项定义为键的另一个实例,并且我们的中心表将任意键类型映射到其他任意键类型。它可以很快把你的大脑绑在一起,但是一旦你写下并封装了处理这一切的逻辑,你就有了很大的灵活性


如果需要的话,我可以写更多关于我们所做工作的细节。

我不明白为什么提取数据的SQL对于您的第一个设计来说会很复杂。当然,要获取项目的所有值,只需执行以下操作:

SELECT itemkey,itemvalue FROM key_value_pairs WHERE itemid='123';
或者,如果您只需要该项目的一个特定键:

SELECT itemvalue FROM key_value_pairs WHERE itemid='123' AND itemkey='Fabric';

第一种设计还为您提供了灵活性,可以随时轻松添加新键。

如果键是动态的,或者有大量键,请使用您的映射表作为第一个示例。此外,这是最通用的解决方案,随着您添加更多的键,它在未来的扩展性最好,很容易编写SQL以获取数据,并且数据库将能够比您想象的更好地优化查询(即,我不会把精力投入到过早地优化这个案例中,除非它被证明是以后测试的瓶颈,在这种情况下,你可以考虑下面的两个选项)。
如果键是一个已知的集合,并且它们并不多(有另一个解决方案介于两者之间。您可以使用xml类型列作为键和值。因此,您保留itemid字段,然后有一个xml字段,其中包含为某些键-值对定义的xml,如

然后,当您从数据库中提取数据时,您可以用多种不同的方式处理xml。这取决于您的使用情况。这是一个可扩展的解决方案。

只要业务需求仍然可以满足,违反规范化规则就可以了。拥有
键1、值1、键2、值2、…键n、值n
就可以了,直到您需要
键n+1、值n+1
时为止


我的解决方案是一个共享属性的数据表和唯一属性的XML。这意味着我同时使用这两种属性。如果一切(或大多数事情)有一个size,那么size就是表中的一列。如果只有对象a有属性Z,那么Z就会存储为XML,就像Peter Marshall已经给出的答案一样。

在大多数情况下,您会使用第一种方法,这是因为您还没有真正坐下来思考您的模型。“嗯,我们还不知道键是什么。”。一般来说,这是一个非常糟糕的设计。它将比实际使用键作为列(它们应该是列)要慢

我还想问为什么你的id是varchar

在极少数情况下,您确实必须实现一个键/值表,第一种解决方案很好,不过,我通常希望将键放在一个单独的表中,这样您就不会将varchar存储为键/值表中的键

例如


你可以甚至去坚果并给键添加一个“类型”,允许一些类型检查。

在继续你的方法之前,我谦恭地建议你退后一步,考虑如果你真的想把这个数据存储在一个“键值对”表中。我不知道你的应用程序,但是我的经验表明每次我做W。
SELECT itemvalue FROM key_value_pairs WHERE itemid='123' AND itemkey='Fabric';
CREATE TABLE valid_keys ( 
    id            NUMBER(10) NOT NULL,
    description   varchar(32) NOT NULL,
    CONSTRAINT pk_valid_keys PRIMARY KEY(id)
);

CREATE TABLE item_values ( 
    item_id NUMBER(10) NOT NULL,
    key_id  NUMBER(10) NOT NULL,
    item_value VARCHAR2(32) NOT NULL,
    CONSTRAINT pk_item_values PRIMARY KEY(item_id),
    CONSTRAINT fk_item_values_iv FOREIGN KEY (key_id) REFERENCES valid_keys (id)
);