Гость
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Как правильно произвести Insert / 25 сообщений из 26, страница 1 из 2
13.03.2017, 11:27
    #39417920
akrush
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как правильно произвести Insert
Добрый день, всем.
Подскажите как правильно отработать такую задачу.

Есть такая таблица (система тарифов)

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
CREATE TABLE TARIF (
    DATA_TR    DATE NOT NULL,
    DATA_E     DATE,
    DATA_R     DATE NOT NULL,
    MARK       SMALLINT,
    NUMB       SMALLINT,
    TARN       SMALLINT,
    COD_POSL   SMALLINT,
    COD_RIZN   SMALLINT,
    NORM_US    NUMERIC(5,2),
    NORM_USD   NUMERIC(5,2),
    CODE_NN    SMALLINT,
    CODE_NDN   SMALLINT,
    CODE_UNIT  SMALLINT,
    COST_UNIT  NUMERIC(10,5),
    COST_UN1   NUMERIC(10,5),
    COST_UN2   NUMERIC(10,5),
    NORM       NUMERIC(10,5),
    NORM_DOP   NUMERIC(10,5),
    NORM_MAX   NUMERIC(10,5),
    VOL_UN0    NUMERIC(7,2),
    VOL_UN1    NUMERIC(7,2),
    OPAL_TIP   SMALLINT,
    CODE_FROG  SMALLINT
);
CREATE INDEX TR_KEY_DATA ON TARIF (NUMB, TARN, DATA_E, COD_POSL, COD_RIZN);
CREATE INDEX TR_KEY_TAR ON TARIF (TARN, NUMB, DATA_E, COD_POSL, COD_RIZN);




Это таблица тарифов на жилищно-коммунальные услуги.
По ключевым полям: DATA_TR, DATA_E, DATA_R, NUMB, TARN может быть десятки строк.
У текущей, действующей, системы тарифов DATA_E is null.

Нужно добавить новые тарифы.
В целом задача сводится к тому что нужно сделать копию ВСЕХ строчек действующей системы тарифов (DATA_E is null) с установкой новой DATA_TR (указывается пользователем) и DATA_R равную СЕГОДНЯ. У "старой" системы тарифов нужно установить DATA_E=(текущая дата-1).

Порядок моих действий:
1. У действующей системы нужно установить DATA_E=текущая дата-1, предварительно сохранив в переменные DATA_TR, DATA_R, NUMB, TARN.
2. Теперь делаю insert record ... from select ... where (data_tr=:data_tr)and(data_r=:data_r)and(numb=:numb)and(tarn=:tarn). Делаю это без выборки поля DATA_E, чтобы ему прописался NULL
3. После добавления мне нужно изменить DATA_TR и DATA_R.

Правильный ли порядок действий. И возможно ли объединить п.2 и п.3, например делая инсерт в хранимой процедуре с заменой необходимых дат. Или еще лучше - все пункты объединить в ХП
Такое возможно????

Я не прошу писать ХП. Если это возможно - я сам напишу и покажу ХП для получения советов.

--------------------------
Firebird 3.0.1.32609;
IBExpert 2017.2.7.1;
Windows 10 32-bit;
4Gb RAM;
SSD 512Mb + HDD 1 Tb;
Настройки по умолчанию
...
Рейтинг: 0 / 0
13.03.2017, 12:17
    #39417970
KreatorXXI
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как правильно произвести Insert
akrush,

Можно написать триггер на Insert. В этом триггере отработать нужные изменения.
...
Рейтинг: 0 / 0
13.03.2017, 12:22
    #39417977
akrush
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как правильно произвести Insert
KreatorXXI,
А в тригер можно передать, в данном случае, даты которые нужно установить?
...
Рейтинг: 0 / 0
13.03.2017, 12:32
    #39417993
wadman
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как правильно произвести Insert
akrushА в тригер можно передать, в данном случае, даты которые нужно установить?
Триггер при вставке и изменении строки имеет доступ к новым и старым данным.
...
Рейтинг: 0 / 0
13.03.2017, 12:53
    #39418011
akrush
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как правильно произвести Insert
wadman,
Это хорошо, но мне нужно установить DATA_TR ту которую ввел пользователь.
...
Рейтинг: 0 / 0
13.03.2017, 13:01
    #39418021
wadman
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как правильно произвести Insert
akrushЭто хорошо, но мне нужно установить DATA_TR ту которую ввел пользователь.
Эта дата будет в новых данных. https://firebirdsql.org/refdocs/langrefupd21-ddl-trigger.html
см new.* и old.*
...
Рейтинг: 0 / 0
13.03.2017, 13:10
    #39418032
hvlad
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как правильно произвести Insert
akrush,

В одной тр-ции:
Код: sql
1.
2.
3.
4.
5.
6.
7.
update tarif set data_e = current_date - 1
 where data_e is null;

insert into tarif (data_tr, data_r, data_e, остальные_поля)
select current_date, :data_user, null, остальные_поля
  from tarif 
 where data_e = current_date - 1
...
Рейтинг: 0 / 0
13.03.2017, 13:13
    #39418036
akrush
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как правильно произвести Insert
wadman,
Если делать инсерт уже с нужными датами, то и тригер мне писать не нужно.

Суть вопроса была в чем.
По отдельности я могу выполнить все пункты поочереди.
Возможно ли их объединить, например в ХП?
Пробую писать ХП - не получается.
Делаю так:


Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
create or alter procedure TARIF_ADD (
    I_DATA_TR date,
    I_DATA_R date,
    I_DATA_E date,
    I_NUMB integer,
    I_TARN integer)
as
declare variable IN_DATA_TR date;
declare variable IN_DATA_E date;
declare variable IN_DATA_R date;
declare variable IN_NUMB smallint;
declare variable IN_TARN smallint;
declare variable DATA_TR date;
declare variable DATA_E date;
declare variable DATA_R date;
declare variable MARK smallint;
declare variable NUMB smallint;
declare variable TARN smallint;
declare variable COD_POSL smallint;
declare variable COD_RIZN smallint;
declare variable NORM_US numeric(5,2);
declare variable NORM_USD numeric(5,2);
declare variable CODE_NN smallint;
declare variable CODE_NDN smallint;
declare variable CODE_UNIT smallint;
declare variable COST_UNIT numeric(10,5);
declare variable COST_UN1 numeric(10,5);
declare variable COST_UN2 numeric(10,5);
declare variable NORM numeric(10,5);
declare variable NORM_DOP numeric(10,5);
declare variable NORM_MAX numeric(10,5);
declare variable VOL_UN0 numeric(7,2);
declare variable VOL_UN1 numeric(7,2);
declare variable OPAL_TIP smallint;
declare variable CODE_FROG smallint;
begin
  /* Procedure Text */
  in_data_e=i_data_e;
  in_data_r=i_data_r;
  in_data_tr=i_data_tr;
  in_tarn=i_tarn;
  in_numb=i_numb;
  for select DATA_TR, data_e,   MARK, NUMB, TARN, COD_POSL, COD_RIZN,
             NORM_US, NORM_USD, CODE_NN, CODE_NDN, CODE_UNIT, COST_UNIT,
             COST_UN1, COST_UN2, NORM, NORM_DOP, NORM_MAX, VOL_UN0, VOL_UN1,
             OPAL_TIP, CODE_FROG
             from TARIF
             where (data_e is null)
      into :DATA_TR,  :Data_e,   :DATA_R,   :MARK,      :NUMB,
           :TARN,     :COD_POSL, :COD_RIZN,  :NORM_US,   :NORM_USD,
           :CODE_NN,  :CODE_NDN, :CODE_UNIT, :COST_UNIT, :COST_UN1,
           :COST_UN2, :NORM,     :NORM_DOP,  :NORM_MAX,  :VOL_UN0,
           :VOL_UN1,  :OPAL_TIP, :CODE_FROG
      do
        begin
          --data_e=in_data_e;
          update tarif set data_e=in_data_e
              where (data_tr=data_tr)and(data_r=data_r)and(numb=numb)
                    and(tarn=tarn);
          insert into TARIF (DATA_TR,  DATA_R,    MARK,      NUMB,     TARN,
                             COD_POSL, COD_RIZN,  NORM_US,   NORM_USD, CODE_NN,
                             CODE_NDN, CODE_UNIT, COST_UNIT, COST_UN1, COST_UN2,
                             NORM,     NORM_DOP,  NORM_MAX,  VOL_UN0,  VOL_UN1,
                             OPAL_TIP, CODE_FROG)
              values (In_DATA_TR, in_data_r,  MARK,      In_NUMB,   in_TARN,
                      COD_POSL,  COD_RIZN,  NORM_US,   NORM_USD, CODE_NN,
                      CODE_NDN,  CODE_UNIT, COST_UNIT, COST_UN1, COST_UN2,
                      NORM,      NORM_DOP,  NORM_MAX,  VOL_UN0,  VOL_UN1,
                      OPAL_TIP,  CODE_FROG);
        end
end




Ругается что "неизвестная колонка in_data_e".
Что делаю неправильно? Если вообще подобное можно уместить в ХП.
...
Рейтинг: 0 / 0
13.03.2017, 13:14
    #39418037
hvlad
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как правильно произвести Insert
akrushРугается что "неизвестная колонка in_data_e".
Что делаю неправильно?Двоеточие забыл
...
Рейтинг: 0 / 0
13.03.2017, 13:57
    #39418092
wadman
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как правильно произвести Insert
akrushЕсли делать инсерт уже с нужными датами, то и тригер мне писать не нужно.
Нужно, просто ты не понимаешь, о чем я. :)

1. Делаешь вставку с новым тарифом.
2. Триггер перед вставкой закрывает текущий тариф.
...
Рейтинг: 0 / 0
13.03.2017, 14:50
    #39418148
akrush
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как правильно произвести Insert
Сделал через ХП

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
create or alter procedure TARIF_ADD (
    I_DATA_TR date,
    I_DATA_R date,
    I_DATA_E date,
    I_NUMB integer,
    I_TARN integer)
AS
declare variable DATA_TR date;
--declare variable DATA_E date;
declare variable DATA_R date;
declare variable MARK smallint;
declare variable NUMB smallint;
declare variable TARN smallint;
declare variable COD_POSL smallint;
declare variable COD_RIZN smallint;
declare variable NORM_US numeric(5,2);
declare variable NORM_USD numeric(5,2);
declare variable CODE_NN smallint;
declare variable CODE_NDN smallint;
declare variable CODE_UNIT smallint;
declare variable COST_UNIT numeric(10,5);
declare variable COST_UN1 numeric(10,5);
declare variable COST_UN2 numeric(10,5);
declare variable NORM numeric(10,5);
declare variable NORM_DOP numeric(10,5);
declare variable NORM_MAX numeric(10,5);
declare variable VOL_UN0 numeric(7,2);
declare variable VOL_UN1 numeric(7,2);
declare variable OPAL_TIP smallint;
declare variable CODE_FROG smallint;
begin
  /* Procedure Text */
  for select DATA_TR, DATA_R,   MARK, NUMB, TARN, COD_POSL, COD_RIZN,
             NORM_US, NORM_USD, CODE_NN, CODE_NDN, CODE_UNIT, COST_UNIT,
             COST_UN1, COST_UN2, NORM, NORM_DOP, NORM_MAX, VOL_UN0, VOL_UN1,
             OPAL_TIP, CODE_FROG
             from TARIF
             where (data_e is null)and(tarn=:i_tarn)and(numb=:i_numb)
      into :DATA_TR,  :DATA_R,   :MARK,      :NUMB,
           :TARN,     :COD_POSL, :COD_RIZN,  :NORM_US,   :NORM_USD,
           :CODE_NN,  :CODE_NDN, :CODE_UNIT, :COST_UNIT, :COST_UN1,
           :COST_UN2, :NORM,     :NORM_DOP,  :NORM_MAX,  :VOL_UN0,
           :VOL_UN1,  :OPAL_TIP, :CODE_FROG
      do
        begin
          update tarif set data_e=:i_data_e
              where (data_tr=:data_tr)and(data_r=:data_r)and(numb=:numb)
                    and(tarn=:tarn);
          :data_tr=i_data_tr;
          :data_r=i_data_r;
          :numb=i_numb;
          :tarn=i_tarn;
          insert into TARIF (DATA_TR,  DATA_R,    MARK,      NUMB,     TARN,
                             COD_POSL, COD_RIZN,  NORM_US,   NORM_USD, CODE_NN,
                             CODE_NDN, CODE_UNIT, COST_UNIT, COST_UN1, COST_UN2,
                             NORM,     NORM_DOP,  NORM_MAX,  VOL_UN0,  VOL_UN1,
                             OPAL_TIP, CODE_FROG)
               values(:DATA_TR,   :data_r,    :MARK,      :NUMB,     :TARN,
                      :COD_POSL,  :COD_RIZN,  :NORM_US,   :NORM_USD, :CODE_NN,
                      :CODE_NDN,  :CODE_UNIT, :COST_UNIT, :COST_UN1, :COST_UN2,
                      :NORM,      :NORM_DOP,  :NORM_MAX,  :VOL_UN0,  :VOL_UN1,
                      :OPAL_TIP,  :CODE_FROG);
        end
end




502 строчки изменяется/добавляется за 3-5 сек.
...
Рейтинг: 0 / 0
13.03.2017, 14:55
    #39418156
Гаджимурадов Рустам
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как правильно произвести Insert
Долго.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
13.03.2017, 14:58
    #39418157
Симонов Денис
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как правильно произвести Insert
akrush502 строчки изменяется/добавляется за 3-5 сек.

это медлено
...
Рейтинг: 0 / 0
13.03.2017, 15:10
    #39418171
akrush
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как правильно произвести Insert
Симонов Денис,
т.е. 502 строчки прописать дату_е
и 502 строчки добавить за 3-5 сек. долго?
Суммарно, редактируется/добавляется, 1004 строки.

А как можно ускорить.
Тут советовали через тригер, но я увы пока не могу понять как это правильно реализовать.
Перебирать через делфи 502 строки и гнать запрос на добавление (с параметрами) и еще тригером у старой строки менять дату_е.
Мне кажется будет дольше, т.к. 502 строки в данном случае должны уйти сначала на клиента, а потом назад.

Или я совсем запутался :(
...
Рейтинг: 0 / 0
13.03.2017, 15:46
    #39418200
KreatorXXI
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как правильно произвести Insert
akrush,

А чего непонятного. Пишешь запрос "insert into ... select ...". А в триггере пишешь свой код для update. Переменные с двоеточиями будут только с префиксом new. В принципе должно получиться компактней. На скорость, скорее всего, мало повлияет. Посмотри анализ запроса, возможно индекса какого не хватает (отдельно по селекту и отдельно по апдейту).
...
Рейтинг: 0 / 0
13.03.2017, 16:30
    #39418243
Гаджимурадов Рустам
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как правильно произвести Insert
akrush> т.е. 502 строчки прописать дату_е
> и 502 строчки добавить за 3-5 сек. долго?

Конечно. Очень долго.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
13.03.2017, 16:33
    #39418245
Гаджимурадов Рустам
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как правильно произвести Insert
Собсно, ты же сам недавно 2 ляма за 20 минут
импортил с обработкой - даже эта медленная
скорость кратно выше, чем 500 записей за 5 сек.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
13.03.2017, 17:10
    #39418280
m7m
m7m
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как правильно произвести Insert
akrush....А как можно ускорить.....
прочитай внимательно что hvlad написал 20289252
(при желании можешь и в процедуру это вкатать, вместо того что ты там написал)

зы. и так, занудства ради
в структуре таблицы нет ни первичного ключа ни уникального индекса (что может быть аукнется впоследствии в самый неподходящий момент)
или ты их экономии ради не показал здесь
......
...
Рейтинг: 0 / 0
13.03.2017, 17:23
    #39418285
akrush
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как правильно произвести Insert
m7m,
Их пока нет.
То что я привел - это то что существует.
Можно сделать и уникальный индекс, но он получится по полям:
DATA_TR DATE NOT NULL,
DATA_E DATE,
DATA_R DATE NOT NULL,
NUMB SMALLINT,
TARN SMALLINT,
COD_POSL SMALLINT,
COD_RIZN SMALLINT,

Не много для индекса?

А сообщение Влада только понял что он имел ввиду.
Днем голова сильно "бо-бо" наверное сразу не понял что Влад имел ввиду.
Сейчас попробую.
...
Рейтинг: 0 / 0
13.03.2017, 17:30
    #39418292
Симонов Денис
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как правильно произвести Insert
akrush,

ну тогда не удивительно, что у тебя медленно работает
...
Рейтинг: 0 / 0
13.03.2017, 18:26
    #39418342
akrush
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как правильно произвести Insert
Симонов Денисakrush,

ну тогда не удивительно, что у тебя медленно работает
Денис, индекса еще нет.
только те которые в первом посте.
Какой индекс посоветуете создать.
Приведенные выше поля - в совокупности дают уникальную запись
...
Рейтинг: 0 / 0
13.03.2017, 18:27
    #39418343
akrush
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как правильно произвести Insert
Влад, огромное спасибо.
Благодаря подсказке время обработки тех же 502+502 строчки - 0сек.
...
Рейтинг: 0 / 0
13.03.2017, 18:40
    #39418354
Гаджимурадов Рустам
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как правильно произвести Insert
akrush> Приведенные выше поля - в совокупности дают уникальную запись

Почитай про искусственные (суррогатные) ключи.
Про это есть куча статей и обсуждений.
Большинство разработчиков при создании таблицы
указывают первое поле Id уже чисто автоматически.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
13.03.2017, 18:41
    #39418356
Гаджимурадов Рустам
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как правильно произвести Insert
akrush> Благодаря подсказке время обработки тех же 502+502 строчки - 0сек.

Всё равно даже с той ХП - очень медленно.
Надо смотреть почему, индексов нет или т.п.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
13.03.2017, 18:44
    #39418358
akrush
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как правильно произвести Insert
Гаджимурадов Рустам,
какие-то индексы есть.
Приведены в первом посте.
Эти индексы в текущей, ДОС, программе работют.
насчет новых индексов и ограничений я еще не думал.
...
Рейтинг: 0 / 0
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Как правильно произвести Insert / 25 сообщений из 26, страница 1 из 2
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]