Subquery
Как вытащить данные из таблицы, имя которой нужно взять из поля другой таблицы, в одном запросе? Я пробовал так, но не получилось:
SELECT t2.* FROM (SELECT t1.TableName FROM objecttypes t1 WHERE t1.ID=5) t2
В результирующем сэте всего одно поле "Table", которое содержит правильное имя таблицы. Но данных из этой таблицы нет.
Только используя динамический sql, иначе никак.
Вы имеете ввиду использование промежуточных переменных, т.е. только через хранимые процедуры?
Цитата: rysak
Вы имеете ввиду использование промежуточных переменных, т.е. только через хранимые процедуры?
Либо можно сделать два запроса: получить имя таблицы, а потом подставить во второй запрос (используя клиента на пхп или чём-то ещё).
Вообще, оптимальным вариантом может быть создание одной большой таблицы и ещё одного поля (типа table_id). Если повесить на него индекс, запросы будут проходить с приличной скоростью.
Тогда можно будет обойтись и одним запросом и не надо будет множества таблиц.
По одной таблице - так оно и ест. Это дерево объектов, для каждого из которых есть родитель в этом же дереве. Одна таблица. Но типов объектов есть 10 штук разных. У каждого типа свой собственный набор полей. Но с точки зрения объектов дерева - они одинаковые. Их можно перемещать по дереву и т.д. Поэтому дополнительные поля лучше всего хранить в дополнительных связанных таблицах. Но поскольку список типов может дополняться в будущем, было бы правильнее создать отдельную таблицу для этого списка, в которой бы для каждого типа был линк на дополнительную таблицу custom-полей. Ну а у каждого объекта был бы линк на тип объекта. Вот и получаем двойной запрос. А иначе линк на дополнительную таблицу нужно хранит в самой таблице объектов, что противоречит главному принципу реляционности БД.
Но как я понял, вариантов нет, нужна хранимая процедура, так?
А уж где его формировать - это зависит от архитектуры вашего по, ваших предпочтений и т.д. Хотите - формируйте на клиенте, как предложил Proger_XP, хотите - сделайте хранимку и формируйте все на сервере, как предложили вы сами, если например трехзвенка и есть сервер приложений, можно на нем..как угодно, главное в том, что придется сформировать строку запроса куда подставить имя вашей таблицы.
P.S. Скорее всего оставлю таблицу типов объектов (для расширяемости через БД) и буду загружать ее при старте любого скрипта (все они будут работать с главной таблицей объектов). Меняться таблица типов будет раз в год, в крайнем случае. Поэтому такая схема подходит. А в запросах к главной таблице буду просто подставлять имя связанной таблицы уже из статического массива в памяти. Не очень элегантно, зато расширяемо, и вопрос с быстродействием снят. Кто что думает о таком подходе, плиз?
Честно говоря, ваше описание получилось очень абстрактным, по крайней мере мне трудно что-то добавить. Попробуйте описать задачу такой структуры, может что посоветуем...
но раз уж выбран подход с разными таблицами, расскажу как бы сделал я.
Я бы посоветовал прежде всего разделить запросы на запросы работы с таблицей с деревом объектов, и запросы работы с таблицами в которых хранятся атрибуты объекта в отдельности.
Например есть дерево разнородных объектов, допустим нечто вроде ActiveDirectory.
в нем разнородные объекты, например Принтер, Юзер, Компьютер.
У принтера есть название, расположение и т.д.
У юзера логин, права пользователя и т.д.
Так вот, я бы задал отдельно методы работы с каждым типом объектов, плюс методы работы с самим деревом объектов и получение типа узла дерева (объекта).
Типа такого:
Printer: GetPrinterByName, CreatePrinter, ..
User: GetUserByLogin, CreateUser, ..
...
ActiveDirTree: GetActiveDirTree, AddNode, RemoveNode, GetNodeType
Все эти методы я бы реализовал в виде хп на сервере (скорость, модульность, удобство поддержки), нежели запросов с клиента или application server-а, далее на клиенте или application server-е (том же веб-сервере к примеру) реализовал бы набор классов, базовый класс узел дерева, и набор классов, наследников от базового каждый из которых представлял бы собой соответвующий объект (т.е. Printer, User, ...) со своим набором методов.
В соответвующих методах этих объектов прописал бы вызовы соответсвующих процедур, там где надо переопределяя методы базового класса реализуя полиморфизм.
Таким образом работа с объектами дерева как с узлами и как с непосредственно объектами - получилась бы прозрачной для пользователей класса. Все процедуры БД лежат в одном месте, удобны для оптимизации отладки и прочего и никакого гемора с динамическим sql.
А, да, забыл уточнить самое главное-то =)
Весь гемор по выбору таблиц для запросов ложитсья на единственный метод построения дерева, который будет создавать объекты того или иного типа.
Конечно можнос казать, дескать при добавлении нового типа придется дописывать этот метод чтоб он умел работать с объектами новго типа, на что могу объективно возразить, что дописывать-то все-равно придется, т.к. для объектов этого типа вам все равно придется создавать таблицу, определять поля и свойства и методы работы с ней.
Пожалуй все.