Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Oracle > Вставка записей 1 раз в месяц


Автор: Kbl4AH 7.5.2009, 10:15
Здравствуйте, возник следующий вопрос.
Есть таблица которая хранит данные за месяцы...
При наступлении нового месяца в таблицу должны вставиться записи с данными из предыдущего месяца...
Я делаю так...
При старте программы выполняю это:
Код

insert into table (dt, content) select trunc(sysdate, 'mm'), content from table where dt < trunc(sysdate, 'mm') and dt = (select max(dt) from table);
commit;

Но это совсем криво, т.к. программа может быть запущена за месяц до 1000 раз, а вставка записей осуществится только в самый первый раз...
Зря только БД напрягаться будет...
Возможно ли как-то по-другому решить эту проблему?

Автор: DimW 7.5.2009, 10:22
так проблема в чем?
организовать инсерт только один раз?

Автор: azesmcar 7.5.2009, 10:24
1. Удалять из другой таблицы данные после копирования (или устанавливать флаг и обновлять после копирования)
2. Хранить дату последнего копирования где нибудь (например в регистрах) и не запускать если данные уже скопированы


Цитата(Kbl4AH @  7.5.2009,  10:15 Найти цитируемый пост)
Но это совсем криво

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

Автор: DimW 7.5.2009, 10:34
Цитата(Kbl4AH @  7.5.2009,  10:15 Найти цитируемый пост)
При наступлении нового месяца в таблицу должны вставиться записи с данными из предыдущего месяца...

Код

with t as
  (select add_months(sysdate, -1) dt from dual
   union select add_months(sysdate, -1) - 1 from dual
   union select add_months(sysdate, -1) - 2 from dual  
   union select sysdate from dual --!!!
  )

select dt
  from t
 where dt between trunc(add_months(sysdate, -1), 'month') and trunc(last_day(add_months(sysdate, -1))) 

Автор: Роман 7.5.2009, 10:34
Может имеется ввиду: кроном запускать скрипт раз в месяц?

Автор: Kbl4AH 7.5.2009, 10:38
Цитата(DimW @  7.5.2009,  11:22 Найти цитируемый пост)
так проблема в чем?организовать инсерт только один раз?

да, оптимально организовать инсерт один раз в месяц...
Цитата(azesmcar @  7.5.2009,  11:24 Найти цитируемый пост)
1. Удалять из другой таблицы данные после копирования (или устанавливать флаг и обновлять после копирования)

а где здесь другая таблица? smile 
Цитата(azesmcar @  7.5.2009,  11:24 Найти цитируемый пост)
2. Хранить дату последнего копирования где нибудь (например в регистрах) и не запускать если данные уже скопированы

а в многопользовательском случае?
Цитата(azesmcar @  7.5.2009,  11:24 Найти цитируемый пост)
Ну а вы что хотели, само копирование уже как-то криво  Зачем нужно в базе иметь дубликаты тех же самых записей если не секрет?

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

Автор: DimW 7.5.2009, 10:42
Цитата(Роман @  7.5.2009,  10:34 Найти цитируемый пост)
Может имеется ввиду: кроном запускать скрипт раз в месяц? 


только не кроном а http://download.oracle.com/docs/cd/B19306_01/appdev.102/b14258/d_job.htm

Автор: azesmcar 7.5.2009, 10:44
Цитата(Kbl4AH @  7.5.2009,  10:38 Найти цитируемый пост)
а где здесь другая таблица? smile 

я думал в другую копируется - неверно понял

Цитата(Kbl4AH @  7.5.2009,  10:38 Найти цитируемый пост)
а в многопользовательском случае?

HKEY_CURRENT_USER


Цитата(Kbl4AH @  7.5.2009,  10:38 Найти цитируемый пост)
почему криво?
затем что есть, например, перечень позиций  и цен на месяц...
на новый месяц эти цены тоже нужны и они равны предыдущим, а если несколько цен изменилось, то пользователь их отредактирует...
так что не совсем дубликаты получаются, хотя бы потому, что тот же месяц (и иногда цены; и иногда сам перечень может измениться) - различный... 

Ясно, но я бы установил тригер на UPDATE цен и дублировал во время изменений.

Автор: DimW 7.5.2009, 10:44
Цитата(Kbl4AH @  7.5.2009,  10:38 Найти цитируемый пост)
да, оптимально организовать инсерт один раз в месяц...

см. DBMS_JOB

Автор: Kbl4AH 7.5.2009, 10:44
DimW, не понял к чему твой код :(
Цитата(Роман @  7.5.2009,  11:34 Найти цитируемый пост)
Может имеется ввиду: кроном запускать скрипт раз в месяц?

может... я не знаю, вот и спрашиваю...

Смысл в том, что у меня запрос и коммит будет выполнятся 1000 (сколько раз стартанет прога) раз за месяц, а я хочу чтобы только один раз...
То есть мне нужна, наверное, реализация средствами самой БД, а не моей клиентской программой... то есть наступил новый месяц, данные сами вставились не зависимо от того сколько раз и была ли вообще запущена прога...

Автор: DimW 7.5.2009, 10:46
Цитата(azesmcar @  7.5.2009,  10:44 Найти цитируемый пост)
HKEY_CURRENT_USER

всмысле?

Автор: Kbl4AH 7.5.2009, 10:47
Цитата(azesmcar @  7.5.2009,  11:44 Найти цитируемый пост)
Ясно, но я бы установил тригер на UPDATE цен и дублировал во время изменений.

наверное, недопонимаю, но так не пойдет... какой апдейт, если записей на месяц апдейта еще не существует в таблице?

Автор: azesmcar 7.5.2009, 10:47
DimW

Ну он же спросил как хранить в регистрах если программа используется разными пользователями.

Добавлено через 1 минуту и 36 секунд
Цитата(Kbl4AH @  7.5.2009,  10:47 Найти цитируемый пост)
наверное, недопонимаю, но так не пойдет... какой апдейт, если записей на месяц апдейта еще не существует в таблице? 

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

Автор: DimW 7.5.2009, 10:50
Цитата(Kbl4AH @  7.5.2009,  10:44 Найти цитируемый пост)
То есть мне нужна, наверное, реализация средствами самой БД, а не моей клиентской программой... то есть наступил новый месяц, данные сами вставились не зависимо от того сколько раз и была ли вообще запущена прога... 

я дал ссылку, изучите ее.
Цитата(Kbl4AH @  7.5.2009,  10:44 Найти цитируемый пост)
DimW, не понял к чему твой код :(

просто альтернатива вашим MAX(dt)

Добавлено через 2 минуты и 57 секунд
Цитата(azesmcar @  7.5.2009,  10:47 Найти цитируемый пост)
Ну он же спросил как хранить в регистрах если программа используется разными пользователями.

а, имеется ввиду хранение на клиентской стороне. на мой взгляд тоже не ахти.

Автор: azesmcar 7.5.2009, 11:00
Цитата(DimW @  7.5.2009,  10:50 Найти цитируемый пост)
а, имеется ввиду хранение на клиентской стороне. на мой взгляд тоже не ахти.

 smile 
ну я вообще считаю что в это задаче копирование раз в месяц ни к чему..
Цитата(DimW @  7.5.2009,  10:44 Найти цитируемый пост)
DBMS_JOB 

это конечно гуд, но на мой взгляд использовать это надо в основном для архиваций и других вещей которые не связаны с основным процессом работы программы (могут быть исключения, но это не тот случай). Во всяком случае на данном этапе знакомства с задачей у меня такое мнение smile

Автор: Kbl4AH 7.5.2009, 11:00
Цитата(azesmcar @  7.5.2009,  11:47 Найти цитируемый пост)
Ну он же спросил как хранить в регистрах если программа используется разными пользователями.

так компы разные...
Цитата(azesmcar @  7.5.2009,  11:47 Найти цитируемый пост)
ну так они есть для предыдущего..зачем хранить ту же самую строку в базе? как только она изменится, тогда для истории дублируйте старую, а пока цена неизменна нахрена вам ее дублировать? Может я задачу не полностью представляю, но никак не могу представить ситуацию когда это нужно.

май бананас - 3р
       огурец - 5р
       помидор - 7р

июнь огурец - 5р
          помидор - 8р

июль тыква - 15р

как тут триггер на апдейт использовать?
Цитата(DimW @  7.5.2009,  11:50 Найти цитируемый пост)
я дал ссылку, изучите ее

спасибо, но, наверное, оставлю как есть... я думал может просто есть какой-нибудь элегантный и не сложный способ в БД...
Цитата(DimW @  7.5.2009,  11:50 Найти цитируемый пост)
просто альтернатива вашим MAX(dt)

у меня все даты представляют из себя 1-е числа месяца...

Автор: Zloxa 7.5.2009, 11:04
Цитата(DimW @  7.5.2009,  10:42 Найти цитируемый пост)
 DBMS_JOB 

 smile 
Цитата

The DBMS_JOB package has been superseded by the http://download.oracle.com/docs/cd/B19306_01/appdev.102/b14258/d_sched.htm#CIHHBGGIpackage

Автор: azesmcar 7.5.2009, 11:06
Цитата(Kbl4AH @  7.5.2009,  11:00 Найти цитируемый пост)

май бананас - 3р
       огурец - 5р
       помидор - 7р

июнь огурец - 5р
          помидор - 8р

июль тыква - 15р


Я бы хранил так
Цитата

идентификатор          товар          цена          дата
1                                  Банан         10 р.           01.01.2009
2                                  Помидор     20 р.           01.01.2009

например повысили цены на банан, после этого таблица будет иметь следующий вид
Цитата

идентификатор          товар          цена          дата
1                                  Банан         10 р.           01.01.2009
2                                  Помидор     20 р.           01.01.2009
3                                  Банан         30 р.           01.02.2009

Когда показываем цены - выбираем те, у которых дата больше с помощью группировки. 

Автор: Zloxa 7.5.2009, 11:17
Цитата(Kbl4AH @  7.5.2009,  11:00 Найти цитируемый пост)
я думал может просто есть какой-нибудь элегантный и не сложный способ в БД...


Kbl4AH,  Советую таки потратить время и изучить....  Это и есть "элегантный и не сложный" способ smile) Все остальное - от лукавого

куда уж проще?:


Код

declare job number;
begin
  sys.dbms_job.submit(job => job,
                      what => 'insert into table (dt, content) 
                                     select trunc(sysdate, 'mm')
                                               , content 
                                     from table 
                                     where dt < trunc(sysdate, 'mm') 
                                         and dt = (select max(dt) from table);
                                    commit;',
                      interval => 'add_month(trunc(sysdate,''MM''),1) +1/24');
  commit;
end;

И будет у тебя оно работать первого числа каждого месяца в час ночи.
Только посмотри что у тебя в http://download.oracle.com/docs/cd/B19306_01/server.102/b14237/initparams.htm#REFRN10077 написано

Добавлено через 7 минут и 56 секунд
Блин, сорри... когда увидил цифру 7, не обратил внимание где запятая стоит, думал семерка относится к делфе.....
Не знаю есть ли жоб в семере... Наверняка есть... но так же ли работает... не знаю :((

Автор: Kbl4AH 7.5.2009, 11:46
Zloxa, azesmcar, DimW, Роман, спасибо!

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)