Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Копирование строк из Грида в таблицу БД из двух связанных таблиц

1.2K
20 октября 2005 года
richel
142 / / 20.01.2005
С темой копирования из одной таблицы с помощью форума давно разобралась. Но вот при усложнении задачи пребываю в глубокой задумчивости...
Есть две связанные по ключу таблицы (Таблица 1 и 2), которые вывожу в 2 Грида.
Связь между таблицами - один ко многим. (База - SQL Server 2000).
Например, в таблице 1 поля такие:
Цитата:
CardID - поле счетчик
GostID - текстовое поле и т.д.


В таблице 2:

Цитата:
BreakID - поле счетчик
CardID - int
Lnos - float и т.д.


Понятно, что ключ связи CardID.
Компоненты загрузки таблиц - ADOQuery.
И есть 2 таблицы (3-я и 4-я), полностью аналогичны по полям исходным. В них копируются
выделенные в Гриде строки.
Нужно:
выделить строки в Гриде 1 (из таблицы 1) и скопировать их в 3 таблицу . Но при этом каким-то образом из таблицы 2 тоже копировать строки, связанные по ключу с табл. 1, в таблицу 4. Чтобы связь эта в новых таблицах была сохранена.
Понимаю, что как-то нужно использовать закладку для табл. 2, но как узнать коды новых ключей, ведь они станут известны только после вставки строк из 1 таблицы?
Еще отмечу, что в данном примере в 3-й и 4-й таблицах поля CardID и BreakID обязательно должны быть полями идентефикации (счетчиками). Поэтому при вставке строк из первой таблицы нельзя предугадать, какие коды CardID получат строки, вставленные в таблицу 3.
Если нужно, могу выложить пример по выполнению 1-й задачи, где копирование происходит из 1 таблицы (без связанной 2-й).

317
20 октября 2005 года
Relax
573 / / 20.09.2000
ун и пусть в 3 и 4 таблице это будут поля идентификации! но необязательно же им быть автоинкрементными - уникальность обеспечится тем что в исходных таблицах эти поля уникальны. так что не усложняй! :)
488
20 октября 2005 года
Mоngооsе
465 / / 01.04.2005
Нужно только определить значение сгенерированного CardId.
Теоретически для этого достаточно, после команды типа

INSERT INTO table3(gostid) VALUES("...")

дать запрос

SELECT SCOPE_IDENTITY()

и после этого вставить записи из 2й таблицы

INSERT INTO table4 (cardid, lnos, ...)
SELECT :new_cardid, lnos, ...
FROM table2 WHERE cardid=: old_cardid
1.2K
21 октября 2005 года
richel
142 / / 20.01.2005
Примерно так я и поступила. Но возникли сложности. В SQL Query Analyzer запрос работает без ошибок. Как только переношу в программу Билдера, выдается сообщение об ошибке. Код такой:
Цитата:
[COLOR=indigo] if(bookmarks.size()==0)return; //Если не выделено ни одной записи

TDataSet* gtkn = Grid_Volume->DataSource->DataSet;

AnsiString sql_tkn = "";

gtkn->DisableControls();
int crno = gtkn->RecNo;
try
{
for(SET::iterator it=bookmarks.begin();it!=bookmarks.end();it++)
{
gtkn->RecNo = *it;

sql_tkn += gtkn->FieldByName("CardID")->AsString + ",";
}
sql_tkn.SetLength(sql_tkn.Length()-1);

// Алгоритм копирования
AnsiString SectorTable = "Loading_Card_Sector"; //Откуда копировать
AnsiString CardTable = "Loading_Card_21030"; //Куда копировать
AnsiString SectorBreak = "Loading_Break_Sector"; //Откуда копировать
AnsiString CardBreak = "Loading_Break_21030"; //Куда копировать

TADOCommand *cmtkn = ADOCommand1;
cmtkn->ParamCheck = true;
cmtkn->Prepared = false;

cmtkn->CommandText = AnsiString("") +"\
Insert Into " + CardTable +" (KodSyst, GostID, NameRD) \n\
Select KodSyst, GostID, NameRD \n\
From " + SectorTable + " \n\
Where CardID in (" + sql_tkn + ") \n\
insert into "+ CardBreak +" (CardID, Sp20i19) \n\
Select tp2.CardID, tc1.Sp20i19 \n\
From "+ SectorBreak +" tc1 \n\
inner join "+ SectorTable + " tp1 on tc1.CardID = tp1.CardID \n\
inner join "+ CardTable + " tp2 on tp2.KodSyst = tp1.KodSyst \n\
Where tp1.CardID in (" + sql_tkn + ") \n\
";
cmtkn->Execute();
}
__finally
{
gtkn->RecNo = crno;
gtkn->EnableControls();
}
[/COLOR]


Ошибка такая:

Цитата:
Пропущен оператор в выражении CardID in(1)


Вопрос такой: почему в Билдере запрашивается какой-то оператор, в чем различие запросов в SQL и Билдере?

488
21 октября 2005 года
Mоngооsе
465 / / 01.04.2005
Определение нового номера CardId не совсем так.

Это гарантировано, что значение KodSyst всегда будет уникальным в CardTable?

Нужно бы посмотреть работают ли запросы с
...
WHERE CardId IN(1,2)

и
...
WHERE CardId=1

Если оба работают, тогда можно изменить конец кода
Код:
cmtkn->Prepared = false;

cmtkn->CommandText = AnsiString("") +"\
Insert Into " + CardTable +" (KodSyst, GostID, NameRD) \n\
Select KodSyst, GostID, NameRD \n\
From " + SectorTable + " \n\
Where CardID in (" + sql_tkn + ") \n\
insert into "+ CardBreak +" (CardID, Sp20i19) \n\
Select tp2.CardID, tc1.Sp20i19 \n\
From "+ SectorBreak +" tc1 \n\
inner join "+ SectorTable + " tp1 on tc1.CardID = tp1.CardID \n\
inner join "+ CardTable + " tp2 on tp2.KodSyst = tp1.KodSyst \n\
Where tp1.CardID ";
if(bookmarks.size()>1)
  cmtkn->CommandText+="in (" + sql_tkn + ")";
else
  cmtkn->CommandText+="=" + sql_tkn;
Мимоходом, если KodSyst уникальный в CardTable, тогда WHERE выражение лишнее.
1.2K
21 октября 2005 года
richel
142 / / 20.01.2005
Цитата:
Нужно бы посмотреть работают ли запросы с
...
WHERE CardId IN(1,2)

и
...
WHERE CardId=1

Если оба работают, тогда можно изменить конец кода


Запрос так работает. Спасибо за подсказку, до этого я не додумалась. Код исправила, теперь ошибка такая:

 
Код:
inner join "+ SectorTable + " tp1 on tc1.CardID =:tp1.CardID \n\
inner join "+ CardTable + " tp2 on tp2.KodSyst =: tp1.KodSyst \n\

Тут у меня, наверное, ошибка =:, было пропущено.
Запускаю код, выскакивает сообщение:
Цитата:
Parameter object is improperly defined. Inconsistent or incomplete information was provided.


Как-то все время запросы с параметром я запускаю с помощью компонента TADOQuery. С помощью TADOCommand еще не приходилось. Может не хватает что-то типа:

 
Код:
cmtkn->Parameters->ParamByName("tp1.KodSyst")->Value = ?;

Цитата:

Мимоходом, если KodSyst уникальный в CardTable, тогда WHERE выражение лишнее.


Да, в CardTable KodSyst - уникальный код.

488
21 октября 2005 года
Mоngооsе
465 / / 01.04.2005
В этом запросе нет параметров, двоеточия лишние.

Потом не можно вместо inner join-ов использовать простой WHERE? Типа:
 
Код:
INSERT INTO CardBreak(CardID, Sp20i19)
SELECT tp2.CardID, tc1.Sp20i19
FROM SectorBreak tc1, SectorTable tp1, CardTable tp2
WHERE tp1.CardID IN (sql_tkn)
  AND tc1.CardID = tp1.CardID
  AND tp2.KodSyst = tp1.KodSyst
И очень трудно разобраться, если так клеить строки. Можно
Код:
...
  String strWhere;
  if(bookmarks.size()>1)
   strWhere = "IN (" + sql_tkn + ")";
  else
    strWhere = "=" + sql_tkn;

  String str;
  str.Format(“INSERT INTO %s(CardID, Sp20i19) \n\
    SELECT tp2.CardID, tc1.Sp20i19  \n\
    FROM %s tc1, %s tp1, %s tp2     \n\
    WHERE tp1.CardID %s             \n\
    AND tc1.CardID = tp1.CardID     \n\
    AND tp2.KodSyst = tp1.KodSyst   \n\",
  CardBreak, SectorBreak, SectorTable,
  CardTable, strWhere);

//ShowMessage(str); // для проверки
  cmtkn->CommandText = str;
  cmtkn->Execute();
}
__finally
{
  gtkn->RecNo = crno;
  gtkn->EnableControls();
}
1.2K
21 октября 2005 года
richel
142 / / 20.01.2005
Цитата:
String str;
str.Format(“INSERT INTO %s(CardID, Sp20i19) \n\
SELECT tp2.CardID, tc1.Sp20i19 \n\
FROM %s tc1, %s tp1, %s tp2 \n\
WHERE tp1.CardID %s \n\
AND tc1.CardID = tp1.CardID \n\
AND tp2.KodSyst = tp1.KodSyst \n\",
CardBreak, SectorBreak, SectorTable,
CardTable, strWhere);


Здесь выдает ошибки, но у меня не получается исправить. В второй строке (“ меняю на (".
И в 7 строке мне не ясно, где же должна закрыться ковычка?
А с остальным я разобралась. Оказывается, я все это хозяйство тестировала на Ацесовской базе. Вот она и не хотела признавать запрос с параметром.
Если написать просто во втором запросе

Цитата:
Where CardID in (" + sql_tkn + ")

, то неправильно происходит вставка строк во вторую таблицу.
Если записать, как Вы указывали ранее:

Цитата:
Where tp1.CardID ";
if(bookmarks.size()>1)
cmtkn->CommandText+=" in (" + sql_tkn + ")";
else
cmtkn->CommandText+=" =" + sql_tkn;


указывает на ошибку в строке Where tp1.CardID ";
Самое интересное, что я не знаю, как исправить.
Я так никогда не пишу, поэтому хочу разобраться, в чем ошибка.

488
21 октября 2005 года
Mоngооsе
465 / / 01.04.2005
Sorry, забыл, что в Buildere при переменном числе аргументов используется макрос ARRAYOFCONST.
 
Код:
String str;
str = Format("INSERT INTO %s(CardID, Sp20i19) \n\
SELECT tp2.CardID, tc1.Sp20i19 \n\
FROM %s tc1, %s tp1, %s tp2 \n\
WHERE tp1.CardID %s \n\
AND tc1.CardID = tp1.CardID \n\
AND tp2.KodSyst = tp1.KodSyst \n",
ARRAYOFCONST((CardBreak, SectorBreak, SectorTable,CardTable, strWhere)));

Цитата:
Если написать просто во втором запросе

Where CardID in (" + sql_tkn + ")

то неправильно происходит вставка строк во вторую таблицу.


Если добавляется море записей, тогда это может из-за соединений.

1.2K
21 октября 2005 года
richel
142 / / 20.01.2005
Цитата:

Если добавляется море записей, тогда это может из-за соединений.


Да, именно море. С запросом попробую разобраться сама.
А исправленный код пока не имею возможность проверить. Нужно переустановить Билдер дома, какой-то глюк. Мне недавно пришлось заливать компьютер. Так что, если будут вопросы, продолжу в понедельник.
А вообще, огромное спасибо.:) Увидела еще одну форму задания строкового формата.

1.2K
24 октября 2005 года
richel
142 / / 20.01.2005
Цитата:
Если добавляется море записей, тогда это может из-за соединений.


А о каких соединениях здесь идет речь?
Код работает. Спасибо огромное. С макросом ARRAYOFCONST мне еще не приходилось сталкиваться. Очень удобна такая запись запроса.
Осталось разобраться с "морем записей".

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог