假设表TA中的每条记录都指向表TB中的一条记录,而这条记录又指向表TC中的一条记录。如果我要编写一个select语句来从表TA中检索一些结果,并希望包含一个使用在来自表TC的记录上定义的远程属性的条件,那么我必须编写一堆连接语句并记住这些名称将这些表链接在一起的主键和外键。嗯,这很容易做到,但是它也很无聊,尤其是当您编写类似的连接以解决不同查询中的类似问题时...
使用对象表示法来访问子记录/属性会更容易,或类似的东西:
"TA.TB.TC.attribute"
我甚至不愿意使用路径表示法:
"TA/TB/TC/attribute"
当然,为了使这样的东西正常工作,应该有一种预先定义表关系的方法,在某处或类似的东西(伪代码):
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"
这将由翻译转换为:
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中执行此操作?我不是指教义 - 它并不涵盖我在这里经历的所有这些要求。
答案 0 :(得分: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 shell,这意味着你也可以创建函数:
> 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")
}
当然,它不会取代关系数据库,但对于我最近正在开展的很多项目来说,它非常适合。特别是具有自定义字段和元数据的那些,因为它是无模式的。
答案 1 :(得分: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中检索一些结果 并希望包含一个条件 使用在a上定义的远程属性 来自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连接语法比简单的equi-joins更具表现力。
如果你只能用这种语法表达等连接 - 而不是整个连接条件 - 那么为什么要使用呢?