Платформа, чтобы избежать написания повторяющихся соединений в SQL / Выбрать операторы? - PullRequest
1 голос
/ 09 июня 2011

Скажем, что каждая запись в таблице TA указывает на ровно одну запись в таблице TB, которая, в свою очередь, указывает на ровно одну запись в таблице TC.Если мне нужно написать оператор выбора, чтобы получить некоторые результаты из таблицы 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, но только виртуально, а не физически;тем не менее он станет видимым и доступным в запросах:

select * from TA where C_attribute = "something"

Это заставит синтаксический анализатор / интерпретатор пройти через все спецификации, предварительно определенные пользователем, а затем переписать SQL должным образом со всеми этими объединениями.

Итак, есть ли инструмент / инфраструктура, которая делает это в PHP?Я не имею в виду Доктрины - это не покрывает все эти требования, которые я прошел здесь.

Ответы [ 2 ]

2 голосов
/ 09 июня 2011

Что ж, если вы хотите избавиться от объединений, не прибегая к ORM, вам нужно избавиться от своего механизма реляционных баз данных. В конце концов, имя само за себя. Он реляционный, поэтому вы должны объединить записи, чтобы создать отношения.

Возможно, вы ищете объектную базу данных. Документно-ориентированные базы данных , которые также могут быть построены поверх объектных баз данных , также могут соответствовать вашим потребностям.

Я использую 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" ] }

Как видите, он также поддерживает вложенные объекты и массивы. Также он поддерживает ссылки на другие объекты:

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

Конечно, он не заменяет реляционные базы данных, но для многих проектов, над которыми я работаю в последнее время, он идеально подходит. Особенно те, у которых есть настраиваемые поля и метаданные, потому что это без схемы.

1 голос
/ 09 июня 2011

Проблема с базой данных немного неуловима, и вы можете подумать об этом снова.

Скажите, что каждая запись в таблице ТА указывает на ровно одну запись в таблице ТБ, который в свою очередь указывает на ровно один запись в таблице ТС.

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.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". Этот синтаксис даст вам только результат равного соединения, а затем только через эквивалент погони за указателями. Синтаксис SQL-соединения бесконечно более выразителен, чем простые экви-объединения.

Если вы можете выражать только равные соединения - не полный диапазон условий соединения - с таким синтаксисом, зачем вообще его использовать?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...