Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1] 2 3  Все   Вниз
  Печать  
Автор Тема: Работа с родительской и дочерними таблицами  (Прочитано 53096 раз)
0 Пользователей и 2 Гостей смотрят эту тему.
nikedeforest
Команда клуба

ru
Offline Offline
Пол: Мужской

« : 15-01-2005 16:08 » 

Вот такой вопрос:
Есть 4 таблицы, одна из них справочник. Мне нужно сделать так, чтобы при внесении значения в справочник, который состоит из четырех полей, проверялось есть ли это значение в поле этого справочника, если нет, то добавить его и внести в дочерние таблицы соответствующий порядковый номер для этого значения, если значение уже в справочнике содержиться, то просто в дочерние таблицы внести порядковый номер этого значения. Проблема заключается в том, что в что в справочнике несколько полей, значение вноситься тоько в одно поле, используя триггер ему нельзя передать параметр, следовательно он не будет знать для какого именно поля мне нужно просматривть есть-ли там это значение, либо его нет. А ведь триггер самый оптимальный вариант, и чего-то другой способ на ум не приходит, может что подскажете.
Блин, че-то кажется плохо объяснил Жаль.
Записан

ещё один вопрос ...
nikedeforest
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #1 : 16-01-2005 07:23 » 

Решил, что спасение в хранимой процедуре, но вот незадача, не пойму, выдается ошибка Column unknown
NAME_POLYA, все просмотрел, не вижу где. Если не сложно ткните пальцем
--------------
Код:
set term!!
create procedure control (name_table varchar(10), name_polya varchar(10), znach varchar(50))
as
declare variable temp integer;
begin
temp=0;
select pn from sprav
where :name_polya=:znach
into :temp;
        if (temp=0) then
        begin
               select min(pn) from sprav
               where :name_polya=0
               into :temp;
                     if (temp<>0)then
                          begin
                             insert into sprav (name_polya)
                             values (:znach);
                                insert into name_table (name_polya)
                                values (:temp);
                          end
                     else
                       begin
                            select max(pn) from sprav
                            into :temp;
                                  insert into sprav (pn, name_polya)
                                  values (:temp+1, :znach);
                                      insert into name_table(name_polya)
                                      values (:temp+1);
                       end
        end
        else
          begin
          insert into name_table (name_polya)
          values (:temp);
          end
end!!
set term;
Записан

ещё один вопрос ...
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #2 : 16-01-2005 11:58 » 

спасение, действительно, в ХП

не знаю, что за диалект, наверно IB какой-нибудь, однако
Цитата
where :name_polya=0
Это есть сравнение значения переменной с 0, но не поля таблицы, хранящегося в :name_polya с 0. Для реализации подстановки поля нужно построить динамический запрос (в виде строчки) и выполнить его. Наверно, выполнять его будет функция exec. Но не ручаюсь.

конкретно ошибки здесь
Цитата
insert into sprav (name_polya)
и
Цитата
insert into name_table (name_polya)
и
Цитата
insert into sprav (pn, name_polya)
и
Цитата
insert into name_table(name_polya)
и
Цитата
insert into name_table (name_polya)
двоеточие пропущено. Но всё равно работать не будет, нужен динамический запрос.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
nikedeforest
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #3 : 16-01-2005 13:39 » 

Я пробовал вставить двоеточие в запросы insert into ... , но происходит ругательство на двоеточие. Поэтому, вроде как там я прав.
 С where  я кажется и вправду тупанул, щас проверю. Функция ехес - это, я про такую в SQL не слышал, такую я видел в Си и Дельфи.
« Последнее редактирование: 16-01-2005 13:42 от nikedeforest » Записан

ещё один вопрос ...
nikedeforest
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #4 : 16-01-2005 14:17 » 

убрал двоеточие в where не помогло Жаль. Я не пойму, эта процедура, написанная мною, вообще к жизни не пригодна Жаль?. Где я не прав? Я уже врроде с этими двоеточиями все перепробовал, может дело не в них.
Насчет диалекта, то это interbase поставляемый  с DELPHI 7. Я сначала на нем пишу, потом перевожу на MySQL.

"Для реализации подстановки поля нужно построить динамический запрос (в виде строчки) и выполнить его."-не совсем понял про динамический запрос, может я о нем слышал под другим названием, что это.
Записан

ещё один вопрос ...
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #5 : 16-01-2005 16:48 » 

потому что в insert и в select должны быть названия полей, а не переменные. Повторяю, нужен динамический запрос. Я не ручаюсь за правильность, так как под рукой нету IB, чтобы проверить, но что-то в духе нижеследующего:
Код:
declare variable sqlstr varchar(2000);
sqlstr = 'select pn from sprav where ' + :name_polya + '=' + :znach;
exec :sqlstr into :temp
Т.е. запрос надо записать как текст, вставив в него через сложение строк переменные, содержащие поля. И выполнить эту строчку интерпретатором.
« Последнее редактирование: 20-12-2007 14:54 от Алексей1153++ » Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
nikedeforest
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #6 : 17-01-2005 05:46 » 

Щас попробую, я вообще-то такое первый раз вижу, (обидно, столько книжек прочел). Этот код, он должен находиться в теле процедуры???
Записан

ещё один вопрос ...
nikedeforest
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #7 : 17-01-2005 06:20 » 

Код:
set term!!
create procedure control (name_table varchar(10), name_polya varchar(10), znach varchar(50))
as
declare variable temp integer;
declare variable sqlstr varchar(70);
begin
temp=0;
sqlstr='select pn from sprav where'+ name_polya+'='+:znach;
exec :sqlstr into :temp;
        if (temp=0) then
        begin
............
end!!
set term ;
Вот так сделал, происходит ругательство такого типа
Цитата
Dynamic SQL Error
SQL error code = -104
Token unknown - line 8, char 4
:
Удаляю двоеточие перед sqlstr  происходит ругательство типа, что за sqlstr.
Я вообще удивляюсь, что на ехес ругательства нет, редактор не выделил жирным это слово, т.е. он слово ехес не посчитал за ключевое. А execute procedure это не тоже, что ехес?
« Последнее редактирование: 20-12-2007 14:57 от Алексей1153++ » Записан

ещё один вопрос ...
HandKot
Молодой специалист

ru
Offline Offline

« Ответ #8 : 17-01-2005 07:01 » 

Может конечно не совсем допонял задачу, но мне кажется все можно решить с помощью связей и индексов
Записан

I Have Nine Lives You Have One Only
THINK!
nikedeforest
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #9 : 17-01-2005 08:11 » 

HandKot, теперь я не совсем понял тебя. ИМХО процедура то, что мне надо, вот только проблема стала в том, чтобы написать ее правильно, т.е. чтобы она работала, но видать моих знаний тут недостаточно. Вот и прошу о помощи, чтобы сделать процедуру эту рабочей.
Записан

ещё один вопрос ...
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #10 : 17-01-2005 10:49 » 

Цитата
sqlstr='select pn from sprav where'+ name_polya+'='+:znach;
пусть name_polya = 'test', а znach = '3'
твой запрос образует строчку
Код:
'select pn from sprav wheretest=3'
Не находишь, что здесь пробел пропущен?
В строке должен получаться синтаксически правильный запрос, иначе ничего работать не будет.
« Последнее редактирование: 20-12-2007 14:58 от Алексей1153++ » Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
HandKot
Молодой специалист

ru
Offline Offline

« Ответ #11 : 17-01-2005 11:10 » 

nikedeforest
тута порылся и вроде в IB нет команды EXEC

может тогда попробовать так

Код:
create procedure control (name_table varchar(10), name_polya varchar(10), znach varchar(50))
as
declare variable temp integer;
declare variable sprPN integer;
BEGIN
sprPN = 0
if (name_polya = 'Поле1') then
begin
  SELECT pn FROM sprav WHERE Поле1 = :znach INTO :temp;
  if (temp = 0) then
     'нет такой записи в справочнике - вставляем
     'формируем новый ключ
     SELECT MAX(pn)+1 FROM sprav INTO :temp
     INSERT INTO sprav(pn, Поле1) VALUES (:temp,:znach)   
     sprNP = temp
  else
     SELECT pn FROM sprav WHERE 'Поле1' = :znach INTO :sprPN
  end
end
else
begin
 ---другое поле
end

'всавляем ключ в подчиненные таблицы
if (name_table = 'Таблица1') then
begin
  insert into Таблица1(pn) VALUES (:sprPN)
end
else
begin
 ---другая таблица
end
END!!!

синтаксис неправильный т.к. я не знаком с IB
я просто хочу передать примерное решение
и еще, если сделать не ХП, а функцией возвращающей значение ключа из справочника
и тогда в подчиненные таблицы заносить значение ключа уже не внуьри проверки, а снаружи так
Код:
insert into [Имя таблицы](pn) values (control(ИмяПоля, Значение)
« Последнее редактирование: 20-12-2007 15:00 от Алексей1153++ » Записан

I Have Nine Lives You Have One Only
THINK!
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #12 : 17-01-2005 15:09 » 

Одна эта ошибка
Цитата
Dynamic SQL Error
Говорит, что динамические запросы в IB есть Улыбаюсь Если не пойдёт, можно попробовать писать в скобках. В SQL Server, с которым я работаю, динамические запросы выполняются как exec('select ........'), а вызов процедур без скобок.

exec - это и есть сокращение от execute. Ещё со времён dBase (а может и раньше, не знаю) повелось, что команды можно писать сокращённо Улыбаюсь. В FoxPro (в старых версиях точно) команды различались лишь по первым 4 символам, там и вместо select можно писать sele. Улыбаюсь В других СУБД это не всегда так, но exec - штука довольно распространённая.
« Последнее редактирование: 20-12-2007 15:00 от Алексей1153++ » Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
nikedeforest
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #13 : 17-01-2005 15:16 » 

HandKot, насколько я понял, ты предлагаешь вместо переменных name_polya и name_table использовать конкретно имя столбца(поля) и имя таблицы в запросах . Но понимаешь, таблица-то не одна, их на данный момент уже 3, в дальнейшем их может прибавиться, хотелось бы чтобы ХП не была такой чувствительной к изменением в БД. А еще если представить, что полей тоже не мало, то вообще так подумать, это сколько же мне надо писать оператор if и запросов для каждого поля и таблицы, и опять же никакой расширяемости для БД. Не очень-то подходит твой способ, ты уж не обижайся, но в этом случае мне вообще нет смысла в этой хранимой процедуре, она должна бать все-таки по универсальнее.
dimka, понял, но уже проверю только завтра. Мне надо к экзамену завтрашнему хоть немного подготовиться, поэтому отвечу после экзамена.
 А вот чуть не забыл, у препода сегодня спросил про динамический запрос, оказывается мы такие вовсе не затрагивали (да и в книжках я не встречал), поэтому не мудрено, что я про них не слышал. Но он сказал, что динамический запрос нельзя вставлять в хранимую процедуру. А теперь HandKot говорит, что exec нет в IB. dimka ты уверен, что это то что надо?
Записан

ещё один вопрос ...
nikedeforest
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #14 : 17-01-2005 15:21 » 

Так запросы динамические есть. А вот ехес есть в IB? Может там что-то другое?
Записан

ещё один вопрос ...
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #15 : 17-01-2005 15:22 » 

Не знаю, как в IB... И почему твой преподаватель запрещает вставлять динамические запросы в ХП... Сам язык SQL таких ограничений не накладывает - это лишь причуды IB могут быть.

Попробуй выполнить простую процедуру вида
Код:
create procedure test 
as
begin
exec('select * from sprav');
end
Поиграйся с exec: со скобками и без, заменить на execute и т.п. Если она заработает  - ты получишь безошибочное исполнение, то твой преподаватель ошибается.
« Последнее редактирование: 20-12-2007 15:01 от Алексей1153++ » Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
nikedeforest
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #16 : 17-01-2005 15:30 » 

dimka, т.е. если так как ты говоришь, то мне достаточно туда пробел добавить и все должно заработать. Сам смысл того что я делал правильный?
Записан

ещё один вопрос ...
nikedeforest
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #17 : 17-01-2005 15:33 » 

Блин, когда писал последний пост, не весь прочел предидущий  пост (т.е. твой dimka). Надо в принципе так и сделать как ты сказал, заняться экспериментом с IB.
Записан

ещё один вопрос ...
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #18 : 17-01-2005 17:39 » 

Вот читаю документацию по IB и вижу одну простую инструкцию, исполняющую динамические запросы: EXECUTE IMMEDIATE. Однако, инструкция эта в консоли IB не работает и в ХП соответственно, предназначена для других целей (см. доки  Embedded SQL Guide). Для каких именно - не понял, куда-то это встраивается в код на C/C++. Разбираться тщательно нет времени. Так что, не выйдет. Признаться, я об IB был более высокого мнения.

Тогда остаётся лишь один выход: вынести код на клиентское приложение - там можно динамически запросы собирать и исполнять.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
nikedeforest
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #19 : 17-01-2005 17:56 » 

dimka, ты гонец плохих новостей. Слушай, а в MySql это все реально сотворить? Мне в принципе все это надо для MySql, просто я к нему еще не привык и по началу все делаю на IB. Но в этом случае может придеться сразу в MySql.
Записан

ещё один вопрос ...
Oldy
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #20 : 17-01-2005 20:56 » 

Если позволите, я бы попытался сделать так:

create procedure control (name_table varchar(10), name_polya varchar(10), znach varchar(50))
as
declare variable temp integer;
begin
  temp=0;
  if :name_polya = 'FIeld1' then
  begin
     select pn from sprav where Field1=:znach into :temp;
        if (temp=0) then
          begin
             insert into sprav (Field1)   values (:znach);
            // и далее то, что нужно если значение уникально
          end
        else
          begin
            // здесьделаем что нужно, если значение поля не уникально
          end
  end

  if :name_polya = 'FIeld2' then //все тоже самое, что и для первого поля
  begin
    .
    .
    .
  end
  и т.д.
end

Ну а вообще, я так думаю, желательно завести несколько справочников (по одному на каждое поле), к ним  по триггеру и по уникальному индексу. В случае уникальности значения будет отрабатывать триггер, а в случае его неуникальности возникнет "экзепшн" который можно обработать в хранимой процедуре.
« Последнее редактирование: 20-12-2007 15:02 от Алексей1153++ » Записан

С уважением, Oldy.
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #21 : 17-01-2005 21:03 » 

Описанный способ с условиями выше предлагался, но неудобно...

А насчёт справочников даже согласен. Почему в одной таблице 4 поля, а заполняется лишь одно из них? Это недостаточная нормализация. Это ещё оправдать нужно какими-то соображениями.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Oldy
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #22 : 17-01-2005 21:08 » 

Согласен, что неудобно, но это единственно возможный  способ для InterBase.
Если-бы это был Yaffil или FireBird 1.5 то тогда можно-бы было применить "Execute varchar" или "Execute statement"
см. https://forum.shelek.ru/index.php/topic,3877.0.html
« Последнее редактирование: 17-01-2005 21:40 от Oldy » Записан

С уважением, Oldy.
nikedeforest
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #23 : 17-01-2005 21:51 » 

В справочнике 4 поля (одно поле это порядковый номер оно не считается, получается 3 поля). Объясняю почему заполняется одно поле. Кстати заполняться могут и все поля, но заполнение справочника происходит, когда в дочернюю таблицу нужно внести значение которое в справочнике еще не содержиться. Дочерних табдиц несколько, между собой они никак несвязана, но у них есть одинаковые поля. Вот нам нужно внести значение в одну из дочерних таблиц (заполнить надо все поля). Рассмотри 2 варианта:
1) Мы заносим данные во все поля и получается что во все эти поля вносяться значения которых нет в справочнике, тогда в справочнике заполняються все поля.
2) Мы заносим данные во все поля и получается что для одного поля дочерний таблицы такое значение есть в соответствующем ей поле в справочнике, а вот для других полей нет и соответствующие им поля справочника будут заполнены этими недостающими значениями.
Вроде как понятно объяснил ИМХО.
Возможно вас смутит, что в справочнике в некоторых полях будут храниться значения равные NULL, но сразу скажу, что их будет не так много и в принципе неудобств это по-идеи никаких не несет.В придачу NULL места много не сожрет Улыбаюсь.
Но ответьте на вопрос поставленный мною выше. В MySql можно реализовать то, что мне нужно способом указанным Димкой (ничего что логин по-русски нкаписал?)  через динамический запрос или так, как пытался я (этот способ указан во втором посте этой темы), что было бы еще лучше. 
P.s. Oldy, ссылку еще не смотрел, после того как отправлю пост посмотрю.
Кабздец видать моему экзамену, совсем не могу сосредоточиться Жаль
Записан

ещё один вопрос ...
nikedeforest
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #24 : 17-01-2005 22:08 » 

Oldy, ты той ссылкой очердной раз доказал, что нельзя в IB и в FB 1.0.3(с которой я не знаком и пока нет желания знакомиться)  в запросы select, insert и в фиг еще знает какие передать вместо имени поля переменную. Но скажи, можно ли это сделать в MySql и можно ли использовать динамический запрос в ХП в MySql. Если не ответите, то умру ведь неучем Улыбаюсь
« Последнее редактирование: 17-01-2005 22:11 от nikedeforest » Записан

ещё один вопрос ...
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #25 : 17-01-2005 22:46 » 

nikedeforest, ничего не понял. Давай задачу не на табличках (одна, другая), а по тем реальным данным, что там хранятся - предметную область. У меня сильнейшее предчувствие, что ты слишком уж замудрил со структурой.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
nikedeforest
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #26 : 17-01-2005 23:24 » 

Вот предметная область
В первой таблице имя которой str_pr(строящееся жилье) содержиться 10 полей, я перечислю первые 3, остальные значения не имеют для данной задачи
Поле №1 rayon(район) Поле№2 tip_doma(тип дома) Поле №3 sanuzel(санузел)

Вторая таблица liv_pr(жилой комплекс), в ней 11 полей, но первые 3 такие же как в предидущей таблице, я их перечислять не буду.

Третья таблица kmz_pr(комплекс малоэтажной застройки), в ней 16 полей, но требуеться только первое, которое называется rayon(район).

Таблица справочник имя которой sprav,  состоит из трех полей:
Поле №1 rayon(район) Поле№2 tip_doma(тип дома) Поле №3 sanuzel(санузел)

К каждой таблице приплюсуйте поле pn(порядковый номер), которе по сути является первым, но его думаю можно не учитывать, это так чтоб имели ввиду.
Вроде все. Надеюсь теперь понятно.
dimka,  я тебя умоляю ответь про вопрос о MySql, я думаю это щас важнее. Если можно выполнить эту хранимую процедуру (неважно с динамическим запросом или без), то в принципе все в порядке.
Записан

ещё один вопрос ...
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #27 : 18-01-2005 07:02 » 

знал бы - ответил бы Улыбаюсь Попробуй. Улыбаюсь

Насчёт жилого комплекса - это тебе виднее, зачем там санузел и тип дома. А вот назначение справочника я не понял. Какой интерес хранить всевозможные сочетания районов, типов домов и санузлов? Это 3 отдельных справочника. Объясни, где ты справочник в нынешнем виде используешь.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Oldy
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #28 : 18-01-2005 08:15 » 

nikedeforest , боюсь что возможности MySql еще беднее чем у InterBase. Вот все, что я нашел  http://www.mysql.ru/docs/man/Variables.html по использованию переменных в запросе. Может плохо искал?  Улыбаюсь
Записан

С уважением, Oldy.
HandKot
Молодой специалист

ru
Offline Offline

« Ответ #29 : 18-01-2005 08:54 » 

nikedeforest
есть такая идея:
в справочнике всего 3 поля key - ключ, name_polya - имя поля, znach - значние (твою таблицу справочник положили боком, если можно так выразится)
пример:
key Name_polya Znach
1    Поле1       ффф
1    Поле2       ыыы
2    Поле3       ччч
3    Поле1       ккк
может так решится твоя проблема и с запросом легче будет 

а использование динамических запросов - это результат неправильной структуры данных и плохой признак программирования ИМХО

ЗЫЖ я использую динамические запросы только на клиентской стороне (программа на VB)
Записан

I Have Nine Lives You Have One Only
THINK!
Страниц: [1] 2 3  Все   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines