2011-06-08 66 views
1

假设表TA中的每条记录都指向表TB中的一条记录,而这个记录又恰好指向表TC中的一条记录。如果我要编写一个select语句来从表TA中检索一些结果,并且想要包含一个使用来自表TC的记录上定义的远程属性的条件,那么我必须编写一堆连接语句,并记住名称将这些表链接在一起的主键和外键。嗯,这很容易做到,但是它也很无聊,尤其是当你编写类似的连接来解决不同查询中的类似问题时...避免在SQL/Select语句中写入重复联接的框架?

使用对象表示法访问子对象会容易得多记录/属性,或者是这样的:

"TA.TB.TC.attribute" 

我甚至preffer使用路径表示法:

"TA/TB/TC/attribute" 

当然,对于这样的事情能够正常工作应该有预先的一种方式 - 定义表格的关系,某处或某事l IKE这(伪代码):

table TA(
    has one TB as "B" 
    on (TA.fkey = TB.pkey) 
) 

table TB(
    has one TC as "C" 
    on (TB.fkey = TC.pkey) 
) 

因此,我们可以写一个选择指令是这样的:

select * from TA where B/C/attribute = "something" 

,这将通过解释来coverted到:

select * from TA 
join TB as B on (TA.fkey = TB.pkey) 
join TC as C on (TB.fkey = TC.pkey) 
where C.attribute = "something" 

的方法,另外,甚至可以创建“快捷方式”来创建我在这里称为“远程属性”的方法。例如:

table TA(
    has one TB as "B" 
    on (TA.fkey = TB.pkey); 
    ) 

# define a "shortcut" 
TA.C_attribute = TA/B/C/attribute; 

然后C_attribute将存在作为TA的柱,但只有几乎不fisically;但是它会在查询变得可见和可访问:

select * from TA where C_attribute = "something" 

这会迫使分析器/解释器正确去通过用户预先定义的所有规格,然后重写SQL与所有这些连接。

那么,有没有一个工具/框架,在PHP中呢?我不是指教义 - 它不包括我在这里经历的所有这些要求。

+1

从Doctrine等ORM中缺少哪些功能?从我所看到的,它可以满足你在这里要求的一切。 – notJim 2011-06-08 23:36:00

+0

那你能否把我连接到他们解释如何做定义“远程属性快捷方式”之类的部分?这就是我需要的。谢谢。 – fabio 2011-06-09 00:06:05

回答

2

那么,如果你想摆脱连接而不诉诸ORM,你必须摆脱你的关系数据库引擎。毕竟,这个名字是不言而喻的。它是关系型的,所以你必须将记录结合在一起来创建关系。

你可能看到的可能是一个对象数据库。 Document-oriented databases,也可以建立在object databases之上,也可能适合您的需求。我使用MongoDB。它具有PHP extension,并且具有许多有用的功能(最显着的是可伸缩性和分片)。

在Mongo中,您存储的文档基本上是JSON对象。考虑“mydb的”数据库和集“MYCOLL”(集合类似的表,如果你喜欢):

> x = {"foo":"bar", "hello":"world", "some_list":["a","b","c"]} 
> db.mycoll.save(x)        // save the object 'x' 
> db.mycoll.find()        // search the collection 
{ "_id" : ObjectId("4df0190b01fdc88b103d3354"), "foo" : "bar", "hello" : "world", "some_list" : [ "a", "b", "c" ] } 

正如你所看到的,它支持嵌套对象和数组为好。此外,它支持其他对象的引用:

> y = {"some_ref" : new DBRef("mycoll", x._id)} 
> db.mycoll.save(y);       // save the object 'y' 
> x.foo = "something has changed!"    // change the object 'x' 
> y.some_ref.fetch().foo      // query 'y' for object 'x' 
something has changed! 

是的,它基本上是一个JavaScript的外壳,这意味着你还可以创建功能:

> myfunc = function(foo) { 
... foo.foo = "something else has changed!"; 
... } 
> myfunc(x) 
> x 
{ 
    "foo" : "something else has changed!", 
    "hello" : "world", 
    "some_list" : [ 
     "a", 
     "b", 
     "c" 
    ], 
    "_id" : ObjectId("4df0190b01fdc88b103d3354") 
} 

当然,它不会取代关系型数据库,但对于我最近开展的很多项目来说,它完全适合。特别是那些具有自定义字段和元数据的,因为它是无模式的。

+0

这个“对象数据库”和“面向文档的数据库”对我来说是全新的东西,我会检查一下。不过,我不知道它是否与关系引擎一样优化。 – fabio 2011-06-09 15:51:33

+0

@fabio:这取决于什么,但我可以向你保证,MongoDB速度非常快。 [看这篇文章](http://www.michaelckennedy.net/blog/2010/04/29/MongoDBVsSQLServer2008PerformanceShowdown.aspx),或者自己试试。 :) – netcoder 2011-06-09 16:01:12

1

数据库问题有点微妙,你可能想再次想一想。

说,在表TA 点,每个记录中只有一个表 TB这反过来指向表TC只有一个 记录记录。

create table TA (
    id integer primary key, 
    results char(1) not null 
); 

create table TB (
    id integer primary key references TA (id) 
); 

create table TC (
    id integer primary key references TB (id), 
    remote_attr char(1) 
); 

insert into TA values 
(1,'A'),(2,'B'),(3,'C'); 

insert into TB values 
(1),(2),(3); 

insert into TC values 
(1,'a'),(2,'a'),(3,'b'); 

如果我写SELECT语句 检索表TA 一些成果,并希望包括下述条件 使用上 记录从表TC来定义的远程属性,那么我 必须写一堆加入 语句,还记得 将这些表链接在一起的主键和外键的名称 。

是的,你需要能够查找键的名称,但你只需要一个连接。

select TA.id, TA.results 
from TA 
inner join TC using (id) 
where remote_attr = 'b'; 

id results 
-- 
3 C 

以前的技术需要应用程序代码来追逐所有表中的指针。关系模型(和SQL)可以让你直接参与共同的价值观。

我其实不介意写更明确的版本。

select TA.id, TA.results 
from TA 
inner join TC on (TC.id = TA.id and TC.remote_attr = 'b') 

你实际上并不需要记住按键的名称。在工作中,我的操作数据库有超过一千张表格。我不记得所有键的名字;我只是看他们。 (我不试图记住所有表和视图的名称)。

微妙的数据库问题与此语法有关:“TA.TB.TC.attribute”。该语法只会给你一个equi-join的结果,然后只能通过追赶指针的等价物。 SQL连接语法比仅仅简单的等连接具有更多的表达力。

如果您只能用这种语法来表达等同连接 - 而不是完整的连接条件范围 - 为什么要使用它?

+0

你已经对equi-join的局限性做了一个很好的说明。但是,在您的示例中,假设我们只处理一对一关系类型,您已经设计了一个与“使用”功能很好地配合使用的数据库模式。当我发布这个问题时,我想到的实际情况与一对多关系有关;例如:来自TB的一条记录可能在表TA中有许多相关记录,但TA只能指向表TB中的一条记录。与TB和TC同样的事情。在这种情况下,您建议的模式不适合。 – fabio 2011-06-09 15:48:34

+0

@fabio:如果您要编辑您的问题以反映一对多要求 - 或者更好,请包括样本DDL和INSERT语句 - 我将编辑我的答案。不过,我认为这不会改变等接合问题。 – 2011-06-09 17:13:40

+0

这很好,我不会编辑我的问题。我会尽力在我的下一个问题上更加精确。谢谢。 – fabio 2011-06-09 21:04:41