Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > БД в Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 31.07.2010, 12:15   #1
Alexei91
Заблокирован
Форумчанин
 
Аватар для Alexei91
 
Регистрация: 30.12.2009
Сообщений: 544
Сообщение Delphi. TreeView. Firebird: Вложенный SQL-запрос.

Приветствую всех.
В запросе
Цитата:
SELECT * FROM S_NOMENCLATURE WHERE (GRP=1)AND
(SELECT UUID FROM S_NOMENCLATURE WHERE NAME=:NAME))
Где GRP - smallint,
UUID - varchar(22).
Параметр Name берётся из TreeView.Selected.Text.
Запрос используется для определения подгрупп в таблице (представление
данных 1 таблицы в виде дерева).
происходит ошибка "Multiple rows in singleton select".

Ошибка связана со вторым SELECT,когда в TreeView на событие
OnExpanding (при раскрытии) TreeView.Selected.Text по-видимому поступает одновременно несколько параметров Name. Почему?
Я-то выделяю/раскрываю 1 узел. Вот код:

Цитата:
procedure TForm1.CreateRootsTree;
var
I: integer;
RootNode: TTreeNode;
begin
qTree.SQL.Clear; //Все корневые узлы имеют parent_uuid='''00000000000000000000 00"
qTree.SQL.Add('select * from s_nomenclature where (parent_uuid=' + //grp=1 - признак группы
'''0000000000000000000000'')and(grp =1)');
qTree.Open;
while not Qtree.Eof do //пока есть записи
begin
RootNode := MyTree.Items.AddObject(nil, qTree.FieldByName('name').AsString,
Pointer(qTree.FieldByName('UUID').A sString));
MyTree.Items.AddChild(RootNode, '');
qTree.Next; RootNode.ImageIndex := 0;
end;
end;

procedure TForm1.FormShow(Sender: TObject);
begin
CreateRootsTree;
end;

procedure TForm1.MyTreeCollapsing(Sender: TObject; Node: TTreeNode;
var AllowCollapse: Boolean);
begin
Node.ImageIndex := 0;
end;

procedure TForm1.MyTreeExpanding(Sender: TObject; Node: TTreeNode;
var AllowExpansion: Boolean);
var
I: integer;
begin
//При раскрытии
qTree.Close;
qTree.SQL.Clear;
qTree.SQL.Add('select * from s_nomenclature where (grp=1)and(parent_uuid=' +
'(select uuid from s_nomenclature where name=:name))');
qTree.ParamByName('name').AsString := MyTree.Selected.Text;//непонятно
qTree.Open;
Node.DeleteChildren;
while not Qtree.Eof do
begin //отображаю потомков
TreeNode := MyTree.Items.AddChildObject(Node, qTree.FieldByName('name').AsString,
Pointer(qTree.FieldByName('UUID').A sString));
MyTree.Items.AddChildFirst(TreeNode , '');
TreeNode.ImageIndex := 0;
TreeNode.SelectedIndex := 1;
qTree.Next;
end;
end;
Принцип действия:
1) Формирую только корневые узлы с ложным потомком (чтоб раскрывалось)
2) При раскрытии пользователем узла формируются потомки этого узла.
Перед этим ложный потомок и все остальные потомки удаляются.
...
или
где можно скачать небольшой Freeware-компонент с исходниками для отображения таблицы БД в виде дерева, если ID и PARENT_ID - строки, а не числа?
Темы для WordPress. Русские WordPress шаблоны
Alexei91 вне форума Ответить с цитированием
Старый 31.07.2010, 13:43   #2
soleil@mmc
SQL-коддинг
Участник клуба
 
Регистрация: 16.01.2009
Сообщений: 1,192
По умолчанию

вы нам для начала поведайте каким образом работает такой запрос
Цитата:
SELECT * FROM S_NOMENCLATURE WHERE (GRP=1)AND
(SELECT UUID FROM S_NOMENCLATURE WHERE NAME=:NAME))
а то похоже что он просто не дописан
soleil@mmc вне форума Ответить с цитированием
Старый 31.07.2010, 14:38   #3
Alexei91
Заблокирован
Форумчанин
 
Аватар для Alexei91
 
Регистрация: 30.12.2009
Сообщений: 544
Сообщение

Цитата:
вы нам для начала поведайте каким образом работает такой запрос
По наименованию (Name) происходит выбор идентификатора (UUID),
который затем передаётся в SELECT * FROM S_NOMENCLATURE WHERE (GRP=1)AND(<отсюда получаю UUID>).
Самое интересное, что этот запрос работает. А вот передаётся
значение для Name:
qTree.ParamByName('name').AsString := MyTree.Selected.Text;
Здесь qTree - TIBQuery, MyTree - TTreeView.
Смотрите делфийский код. Так вот получается, что в какой-то момент в строчке
qTree.ParamByName('name').AsString := MyTree.Selected.Text
видимо образуется эта ошибка (причём не всегда).
Вся загвоздка в MyTree.Selected.Text - имя узла TreeView, получаемое
при развертывании.

Цитата:
а то похоже что он просто не дописан
Запустите любой запрос. Например,из демки Employee.fdb:
select * from customer where (cust_no=(select cust_no from customer where cust_no=1004)) - будет работать.
Темы для WordPress. Русские WordPress шаблоны
Alexei91 вне форума Ответить с цитированием
Старый 01.08.2010, 00:00   #4
soleil@mmc
SQL-коддинг
Участник клуба
 
Регистрация: 16.01.2009
Сообщений: 1,192
По умолчанию

давайте по порядку

ваш запрос
Код:
SELECT * FROM S_NOMENCLATURE WHERE (GRP=1)AND
(SELECT UUID FROM S_NOMENCLATURE WHERE NAME=:NAME))
1) внутренний запрос, согласен, возвращает какой-то или какие-то ууид/ууиды
Код:
SELECT UUID FROM S_NOMENCLATURE WHERE NAME=:NAME
правда, для читабельности желательно имена параметров начинать с буквы P - так потом быстрее искать по коду запроса и путаницы меньше

2) первая часть обрамляющего запроса тоже чота там сделает
Код:
SELECT * FROM S_NOMENCLATURE WHERE (GRP=1) AND
но дальше мы видим связку по условию "И"
т.е. вернуть все записи, удовлетворяющие условию группа = 1 и УУИД/УУИДЫ

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

Цитата:
Сообщение от Alexei91 Посмотреть сообщение
Запустите любой запрос. Например,из демки Employee.fdb:
select * from customer where (cust_no=(select cust_no from customer where cust_no=1004)) - будет работать.
угу
работать будет, но смысла в нем никакого
проще уж сделать просто запрос
Код:
select * from customer where cust_no=1004
soleil@mmc вне форума Ответить с цитированием
Старый 01.08.2010, 07:04   #5
Alexei91
Заблокирован
Форумчанин
 
Аватар для Alexei91
 
Регистрация: 30.12.2009
Сообщений: 544
Сообщение

Цитата:
а что делают эти ууиды - равны, не равны, существуют в этом наборе данных???
UUID - уникальный идентификатор записи в таблице, генерится через функцию uuid_create() из uuidlib.dll.
Parent_UUID - UUID предка
.
Например,
UUID записи равен какому-нибудь 'dahSDsaD1Aad1jh!1s12da'.
Parent_uuid='000000000000000000000' - нет предка,это корневой узел.
В общем Parent_UUID хранит UUID предка, а GRP - признак того,что
запись - группа.
Т.к. Name уникален из
Код:
SELECT UUID FROM S_NOMENCLATURE WHERE NAME=:NAME
теоретически должен возвращать не более 1 записи с UUID.
Думаю у меня ошибка в делфийском коде => ошибка с запросом.
Посмотрите DELPHI-код:
Код:
procedure TForm1.CreateRootsTree;
var
I: integer;
RootNode: TTreeNode;
begin
qTree.SQL.Clear; //Все корневые узлы имеют parent_uuid='''00000000000000000000 00"
qTree.SQL.Add('select * from s_nomenclature where (parent_uuid=' + //grp=1 - признак группы
'''0000000000000000000000'')and(grp =1)');
qTree.Open;
while not Qtree.Eof do //пока есть записи
begin
RootNode := MyTree.Items.AddObject(nil, qTree.FieldByName('name').AsString,
Pointer(qTree.FieldByName('UUID').A sString));
MyTree.Items.AddChild(RootNode, '');
qTree.Next; RootNode.ImageIndex := 0;
end;
end;

procedure TForm1.FormShow(Sender: TObject);
begin
CreateRootsTree;
end;

procedure TForm1.MyTreeCollapsing(Sender: TObject; Node: TTreeNode;
var AllowCollapse: Boolean);
begin
Node.ImageIndex := 0;
end;

procedure TForm1.MyTreeExpanding(Sender: TObject; Node: TTreeNode;
var AllowExpansion: Boolean);
var
I: integer;
begin
//При раскрытии
qTree.Close;
qTree.SQL.Clear;
qTree.SQL.Add('select * from s_nomenclature where (grp=1)and(parent_uuid=' +
'(select uuid from s_nomenclature where name=:name))');
qTree.ParamByName('name').AsString := MyTree.Selected.Text;//похоже здесь ошибка
qTree.Open;
Node.DeleteChildren;
while not Qtree.Eof do
begin //отображаю потомков
TreeNode := MyTree.Items.AddChildObject(Node, qTree.FieldByName('name').AsString,
Pointer(qTree.FieldByName('UUID').A sString));
MyTree.Items.AddChildFirst(TreeNode , '');
TreeNode.ImageIndex := 0;
TreeNode.SelectedIndex := 1;
qTree.Next;
end;
end;
Темы для WordPress. Русские WordPress шаблоны
Alexei91 вне форума Ответить с цитированием
Старый 01.08.2010, 08:04   #6
Alexei91
Заблокирован
Форумчанин
 
Аватар для Alexei91
 
Регистрация: 30.12.2009
Сообщений: 544
Радость

Всё заработало!
Я просто во время отладки навводил несколько записей с одинаковыми Name отсюда и ошибка Multiple rows in singleton select во время раскрытия некоторых узлов дерева.
Код:
SELECT * FROM S_NOMENCLATURE WHERE (GRP=1)AND /*подзапрос2*/
(SELECT UUID FROM S_NOMENCLATURE WHERE NAME=:NAME)/*подзапрос1*/)
Подзапрос1 возращал несколько UUID за ход в подзапрос2 или типа того.
Большое спасибо за советы.
Темы для WordPress. Русские WordPress шаблоны
Alexei91 вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Firebird 2.5. Группировка и вложенный запрос. Антон Ю.Б. SQL, базы данных 8 02.07.2010 17:22
вложенный запрос выборка по многим критериям Droid БД в Delphi 2 23.05.2010 19:31
Создание новых таблиц в MS SQL SERVERE через SQL запрос в Delphi S_Yevgeniy Помощь студентам 1 27.10.2009 06:26
Запрос SQL из Access в Delphi Talemir БД в Delphi 5 26.08.2009 20:46
sql запрос delphi viperrr Помощь студентам 13 03.07.2009 03:08