Проблема с запросом на обновление
t1 - склад, где есть товар.
t2 - накладная, для списания части товара со склада.
Хочу cделать запрос на обновлениe:
"UPDATE t1 INNER JOIN t2 ON t1_ID = t2_ID SET t1_Col = t1_Col - t2_Col"
(в аксесе такой код работаeт)
а тут выдаёт ошибку...
использую
BDE-Query
Подскажите как можно реализовать подобное обновление
использую BDE-Query
Если БД - ACCESS, то использовать ADO. Более того, можно написать ВСЕ запросы в самом ACCESS (вкладка "Запросы"), и вызвать их по имени через AdoStoredPoc
Базы не на аксесе, таблицы старые, парадокс 7...
Просто я пробовал такой запрос в аксесе написать, работает, а тут не хочет...
t1 - склад, где есть товар.
t2 - накладная, для списания части товара со склада.
Хочу cделать запрос на обновлениe:
"UPDATE t1 INNER JOIN t2 ON t1_ID = t2_ID SET t1_Col = t1_Col - t2_Col"
(в аксесе такой код работаeт) а выдаёт ошибку...
использую
BDE-Query
Подскажите как можно реализовать подобное обновление
Пиши так,
123 - это количество
34 - это код записи (тоже что и уникальный ключ)
pQ->SQL->Add( "UPDATE t1 SET t1_Col = 123 WHERE t1_ID = 34" );
или, используя параметры для хранения значений
pQ->SQL->Add( "UPDATE t1 SET t1_Col = :Quant WHERE t1_ID = :KeyCode" );
pQ->Params->Items[0]->Value = 123;
pQ->Params->Items[1]->Value = 34;
123 - это количество
34 - это код записи (тоже что и уникальный ключ)
pQ->SQL->Add( "UPDATE t1 SET t1_Col = 123 WHERE t1_ID = 34" );
или, используя параметры для хранения значений
pQ->SQL->Add( "UPDATE t1 SET t1_Col = :Quant WHERE t1_ID = :KeyCode" );
pQ->Params->Items[0]->Value = 123;
pQ->Params->Items[1]->Value = 34;
Так нужно переберать все записи...
Похожим способом я и реализировал, но это не правельно, хотелось бы услышать ответ спецов...
Похожим способом я и реализировал, но это не правельно, хотелось бы услышать ответ спецов...
Необходимо правильно строить структуру базы. И зачем все записи перебирать?
Подскажи как написать запрос, что б уменьшить количество товара в 1 таблице, на значения товара в 2 таблице.
если конечно я тебя правильно понял
если конечно я тебя правильно понял
Несовсем.
Есть 2 таблицы
Т1 - это склад с товаром и таблица
Т2 - Накладная (в эту таблицу клиент наберает товар со склада)
(к примеру он выбрал 5 шт процессоров из 10 и 2 ОЗУ из 15)
При сохранение накладной, количество на складе должно уменьшится, то есть процов должно остаться 5 а ОЗУ 13.
Есть 2 таблицы
Т1 - это склад с товаром и таблица
Т2 - Накладная (в эту таблицу клиент наберает товар со склада)
(к примеру он выбрал 5 шт процессоров из 10 и 2 ОЗУ из 15)
При сохранение накладной, количество на складе должно уменьшится, то есть процов должно остаться 5 а ОЗУ 13.
мля. юный чел - читай хотябы Дейта. Он писал давно - но то что писал актуально до сих пор.
склад с товаром - чисто ИМХО конечно - но это приходные накладные. Потому как, хоть меня убейте, если товар на склад неоприходован - то хрен ты его спишешь. Второе - та же таблица документов - расходные накладные. Чисто мое понимание - тут как минимум отсутствует еще три таблицы - и никаких проблем быть не может. Простешим запросом - не надо считать количество - надо просто(для MSSQL):
@idtovara int,
...
AS
{
declare @idmaindoc;
set @idmaindoc = NULL
INSERT INTO tableMain (idtovara,idcontragent, data,iddoctype)values(@idtovara,@idcontragent,NOW(),@@iddoctype);
set @idmaildoc = IDENT_CURRENT('tableMain')
}
и далее
для парадокса это делается просто без ХП.
Кроме того - в чем прелесть использования собственно парадокса? Юзайте нормальные сервера БД. Тем более что выбор есть. Учитесь работать нормально а не через ж.
Похожим способом я и реализировал, но это не правельно, хотелось бы услышать ответ спецов...
А что в этом "переборе записей" не правильно?
Например, ты в накладную ( таблицу t2 ) заносишь перечень "увозимого со склада" товара, с указаныым количеством. Затем тебе необходимо "утвердить" эту накладную. По логике необходимо для каждой записи из накладной уменьшить количество товара на складе ( в таблице t1 ). А как это сделать иначе? как не перебором всех записей в накладной и изменения соответствующей записи на складе. Неужели существуют какие-то "особо умные SQL запросы" которые сделают всё сами?
Например, ты в накладную ( таблицу t2 ) заносишь перечень "увозимого со склада" товара, с указаныым количеством. Затем тебе необходимо "утвердить" эту накладную. По логике необходимо для каждой записи из накладной уменьшить количество товара на складе ( в таблице t1 ). А как это сделать иначе? как не перебором всех записей в накладной и изменения соответствующей записи на складе. Неужели существуют какие-то "особо умные SQL запросы" которые сделают всё сами?
Нет не существуют. Существуют люди - которые делают "все сами" - при условии - что у людей руки с плечей растут. Как минимум. Накуя млять, за выражение простите, утверждать накладную? И на куя - говоря языком простым записи перебирать? Не ужели это сложно - и на ХУЯ вся РБД если простое - сответствие моножества множеству - что сложного - ведь просто решается
Например, ты в накладную ( таблицу t2 ) заносишь перечень "увозимого со склада" товара, с указаныым количеством. Затем тебе необходимо "утвердить" эту накладную. По логике необходимо для каждой записи из накладной уменьшить количество товара на складе ( в таблице t1 ). А как это сделать иначе? как не перебором всех записей в накладной и изменения соответствующей записи на складе. Неужели существуют какие-то "особо умные SQL запросы" которые сделают всё сами?
не правильно в этом переборе одно - логика.
Уважаемый kot_,
У Вас что, месячные ... ;)
И настроение плохое ...
И Вы "матом" разговариваете ...
----------------------------------------------
Если не затруднит, раскажите пожалуйста про
Я на своей работе написал бухгалтерскую программу, которая,
как обсуждалось выше, занимается "перебором" записей. И делает это
уже 7 лет, и как-то не внапряг ... ;)
Учится никогда не поздно!
Если Я не общался с теми кто умнее меня, или не нашёл нужную книгу ... - это конечно "минус" мне, но, повторюсь,
учится никогда не поздно.
Пожалуйста, поподробнее о "сответствие моножества множеству" применительно к SQL и т.п.
SQL операция JOIN (FULL, INNER, LEFT, RIGHT)
Об этих операторах SQL мне известно и я их использую в своей программе. Я думаю, kot_ говорит о чём-то другом ...
Давайте поговорим об этом на примере бухгалтерии.
Таблица TOVAR : (товар)
int TovarID - код записи, он же уникальный код товара
char TovarName - наименование товара
Таблица NALICHIE: ( наличие )
int NalichieID - код записи
int NalichieTovarID - код товара
int NalichieTovarQuantity - количество
Таблица NAKLADNAYA : (накладная)
int NakladnayaID - код записи
int NakladnayaTovarID - код товара
int NakladnayaTovarQuantity - количество товара
bool NakladnayaSet - признак "проведенной" записи
Чтобы увидеть накладную о "Перевозке товара со склада" используем
SQL с оператором JOIN
INNER JOIN "NAKLADNAYA" N
ON T.TovarID = N.NakladnayaTovarID
ORDER BY T.TovarName
и увидим список наименований товара с количеством, которое
необходимо забрать со склада.
Но это лишь "подготовленная" накладная. Чтобы она вступила в силу,
необходимо произвести уменьшение количества товара в таблице NALICHIE.
Для этого в цикле выполним модификации записей в таблице NALICHIE и NAKLADNAYA используя SQL с оператором UPDATE
TQuery *Upd = ... - указатель на объект TQuery для модификации данных
for (int i = 0; i < RecordCount; i++)
{
// если запись не "проведена"
if ( !Data->FieldByName( NakladnayaSet )->AsBoolean )
{
// Шаг 1 - уменьшим кол-во в наличии на складе
Upd->Close();
Upd->SQL->Clear();
Upd->SQL->Add( "UPDATE NALICHIE SET" );
Upd->SQL->Add( "NalichieTovarQuantity = NalichieTovarQuantity - :TQuant" );
Upd->SQL->Add( "WHERE NalichieTovarID = :TID" );
// через параметры присвоим значения количества и кода записи
Upd->Params->Items[0]->Value = Data->FieldByName( NakladnayaTovarQuantity )->AsInteger;
Upd->Params->Items[1]->Value = Data->FieldByName( NakladnayaTovarID )->AsInteger;
Upd->ExecSQL();
// Шаг 2 - установим признак "проведено" для записи в накладной
// чтобы избежать повторения этой операции
Upd->Close();
Upd->SQL->Clear();
Upd->SQL->Add( "UPDATE NAKLADNAYA SET" );
Upd->SQL->Add( "NakladnayaSet = true" );
Upd->SQL->Add( "WHERE NakladnayaID = :NID" );
// через параметры присвоим значение кода записи
Upd->Params->Items[0]->Value = Data->FieldByName( NakladnayaID )->AsInteger;
Upd->ExecSQL();
}
}
То, что описано в цикле, Я назваю "перебором" записей.
Если Я правильно понял kot_-а, существует более красивое и "современное" решение подобной задачи. Вот об этом решении Я и прошу его написать. ;)
Upd->SQL->Add( "NakladnayaSet = true" );
Upd->SQL->Add( "WHERE NakladnayaID = :NID" );
// через параметры присвоим значение кода записи
Upd->Params->Items[0]->Value = Data->FieldByName( NakladnayaID )->AsInteger;
Upd->ExecSQL();
вот это можно одним запросом сделать, ане перебором
т.е. примерно так: WHERE NAKLADNAYA.NakladnayaID = Data.NakladnayaID
Upd->SQL->Add( "NakladnayaSet = true" );
Upd->SQL->Add( "WHERE NakladnayaID = :NID" );
// через параметры присвоим значение кода записи
Upd->Params->Items[0]->Value = Data->FieldByName( NakladnayaID )->AsInteger;
Upd->ExecSQL();
вот это можно одним запросом сделать, ане перебором
т.е. примерно так: WHERE NAKLADNAYA.NakladnayaID = Data.NakladnayaID
Не совсем понял как связать текст SQL запроса с объектом TQuery.
Можешь полный код привести?
но в общем и целом
Upd->SQL->Add( "WHERE NakladnayaID = :NID" );
Upd->Params->Items[0]->Value = Data->FieldByName( NakladnayaID )->AsInteger;
вот эти 2 строчки с перебором всей таблицы заменяются на условие SQL запроса (который написал выше) и он делает это одним махом
выполняем запрос и таблица (поле количество) товаров уменьшается на количество указанное в накладной:
INNER JOIN Naklad
ON Tovar.Id=Naklad.Id
SET Tovar.CountTov = Tovar.CountTov-Naklad.CountTov;
хы... от чего ушли, к тому и пришли :D
UPDATE Tovar
SET CountTov = Tovar.CountTov - Naklad.CountTov
FROM Naklad INNER JOIN
Tovar ON Naklad.Id = Tovar.Id
а вообще в любой нормальной СУБД есть SQL designer
с ним можно и не знать совсем языка, он сам все сделает
Если Я правильно понял kot_-а, существует более красивое и "современное" решение подобной задачи. Вот об этом решении Я и прошу его написать. ;)
Зачем в базе таблица NALICHIE? В двух местах хранить одни и те же данные? Это не просто "не современно" как вы изволили выразится - это прямой путь к возникновению ошибок.
Если в двух словах - вполне стандартное решение - сделать две зависимые таблицы - одна - ведущая должна содержать данные по накладной (номер,дата, тип документа и пр.) что может быть отнесено к классу документа. По внешнему ключу (идентификатор) таблица связывается с таблицами записей которая содержит все что относится к классу записи накладной (идентификатор записи,идентификатор документа, идентификатор товара, количество и т.д.). Справочник типов документов в простейшем случае содержит идентификатор типа документа(внешний ключ на таблицу накладных) ну и название. Пример 0- приходная накладная, 1- Расходная накладная, 2 - другие ...
Тогда операция расхода/прихода выполняется посути операцией вставки в таблицу документов записи о документе и добавление в связанную таблицу необходимое количество товара. Количество товара на складе - разница между приходом и расходом. Для оптимизации запроса - что бы не лопатить таблицу от начала времен - можно ввести понятие периода и т.д. но это уже оптимизация последнего этапа.
Т.е. что имеем - создается ХП выполняющюю вставку записи о накладной и возврат нового идентификатора - можно обойтись и просто запросом получив максимальный идентити и увеличив его на 1.
Затем по событию на форме товар добавляется одним запросом - без переборов и пр. Если в логике программы есть необходимость провести накладную, а в бухгалтерии это как раз бывает нужно, то по нажатию на кнопку "провести" выполняется апдейт одной записи по ее идентификатору.
И где здесь перебор всех записей? Эта схема в реальной программе может быть значительно улучшена - просто нет времени - и объяснять долго. Читайте книжки.
... Количество товара на складе - разница между приходом и расходом.
Уважаемый kot_,
В Вашем варианте, чтобы знать текущее наличие на "СКЛАДЕ" необходимо "калькулировать" это значение как разницу между приходами и расходами. А как быть с вопросом архивирования БД. Например, при большом товарообороте, чтобы уменьшить "нагрузку" по работе с данными, можно часть "старых по дате" записей перенести в некую архивную таблицу. Как быть в этом случае с подсчётом "приход-расход"?
А если "складов" или "магазинов" несколько?
Я понимаю, что контроль одновременной модификации количества товара
в двух таблицах ( наличие и склад/магазин) "накладнее" чем для одной, но ведь компьютеру всё равно "работать" ;)
У меня на работе программа работает в нескольких магазинах. Данные обновляю по терминалу. Там вообще не нужна бухгалтерия, т.е. "приход-расход", а наличие по магазинам - очень даже необходимо. Я понимаю, что для магазинов можно создавать такую таблицу наличия и добавлять её в пакет обновления. Но и для меня, на рабочем месте бухгалтера наличие такой "постоянной" таблицы удобно в работе. Связывается она с каталогом товара как "master-detail" через индекс, работает быстро. Как-то пробовал связать через запрос SQL - тормоза, так ради чего собственно ....
В Вашем варианте, чтобы знать текущее наличие на "СКЛАДЕ" необходимо "калькулировать" это значение как разницу между приходами и расходами. А как быть с вопросом архивирования БД. Например, при большом товарообороте, чтобы уменьшить "нагрузку" по работе с данными, можно часть "старых по дате" записей перенести в некую архивную таблицу. Как быть в этом случае с подсчётом "приход-расход"?
А если "складов" или "магазинов" несколько?
О том что это делается, я написал. Как делается - уж извините, в конце концов если вы считаете необходимым, пишите ТЗ в личку, проектирование БД - это тоже не малый объем работы и описать все детали - увольте, за бесплатно делать не могу - физически времени не хватает. Простейший вариант - использование в программе такой сущности как периоды. Т.е. коротко - документ который содержит итоговые остатки.
Вопрос о магазинах я вобще не считаю существенным - поверьте это делается гораздо проще чем в вашем варианте. Сущность магазин и склад являются одним из параметров собственно документа.
Я понимаю, что контроль одновременной модификации количества товара
в двух таблицах ( наличие и склад/магазин) "накладнее" чем для одной, но ведь компьютеру всё равно "работать" ;)
вопрос эффективности - это как я тоже писал - вопрос последний для БД. Первоочередная задача - надежность, однозначность и как правило расширяемость.
У меня на работе программа работает в нескольких магазинах. Данные обновляю по терминалу. Там вообще не нужна бухгалтерия, т.е. "приход-расход", а наличие по магазинам - очень даже необходимо. Я понимаю, что для магазинов можно создавать такую таблицу наличия и добавлять её в пакет обновления. Но и для меня, на рабочем месте бухгалтера наличие такой "постоянной" таблицы удобно в работе. Связывается она с каталогом товара как "master-detail" через индекс, работает быстро. Как-то пробовал связать через запрос SQL - тормоза, так ради чего собственно ....
мда. понятно. Собственно удобно - делайте. Это ваша работа. К сожалению времени на объяснение и примеры просто физически нет -
как в принципе что либо доказывать. Все сворачиваюсь - нет времени
выполняем запрос и таблица (поле количество) товаров уменьшается на количество указанное в накладной:
INNER JOIN Naklad
ON Tovar.Id=Naklad.Id
SET Tovar.CountTov = Tovar.CountTov-Naklad.CountTov;
хы... от чего ушли, к тому и пришли :D
Это точно... :D
Тоже самое я был в начале написал :)
Суть в том, что в аксесе такой запрос работает, а в билдере (бде-квери) не хочет...
На данный момент так и реализовано, что перебираются все записи в накладной, и на это значение уменьшается количество на складе... Думал может подскажут как такой запрос реализовать что б заработало с бде. А тут началось...
Всем спасибо!
Думаю лучше закрыть это обсуждение :)