繁体   English   中英

避免在 SQL/Select 语句中编写重复连接的框架?

[英]Framework to Avoid Writting Repetitive Joins in SQL/Select Statements?

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

使用 object 表示法来访问子记录/属性会容易得多,或者像这样:

"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 指令:

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 的列存在,但只是虚拟的而不是实际的; 尽管如此,它会在查询中变得可见和可访问:

select * from TA where C_attribute = "something"

这将通过用户预定义的所有规范强制解析器/解释器使用 go,然后使用所有这些连接正确地重写 SQL。

那么,在 PHP 中有没有这样的工具/框架? 我不是指教义——它没有涵盖我在这里经历的所有这些要求。

好吧,如果你想摆脱连接而不诉诸 ORM,你必须摆脱你的关系数据库引擎。 毕竟,这个名字是不言自明的。 它是关系型的,因此您必须将记录连接在一起以创建关系。

您可能正在寻找的可能是 object 数据库。 面向文档的数据库,也可以建立在object 数据库之上,也可以满足您的需求。

我使用MongoDB 它具有PHP 扩展,并具有大量有用的功能(最显着的是可扩展性和分片)。

在 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" ] }

如您所见,它还支持嵌套对象和 arrays。 此外,它还支持对其他对象的引用:

> 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")
}

当然,它不会取代关系数据库,但对于我最近从事的许多项目来说,它非常适合。 尤其是那些具有自定义字段和元数据的,因为它是无模式的。

数据库问题有点微妙,您可能需要重新考虑一下。

假设表 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

较早的技术需要应用程序代码在所有表中追踪指针。 关系型 model(和 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”。 该语法只会给你一个等值连接的结果,然后只能通过等效的追逐指针。 SQL 连接语法比简单的等连接更具表现力。

如果你只能用这种语法表达等值连接——而不是所有的连接条件——为什么要使用它呢?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM