0 / 0 / 0
Регистрация: 01.05.2016
Сообщений: 5
1

Процедура, которая перемешает дни в датах регистрации

01.05.2016, 22:09. Показов 1061. Ответов 9
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Здравствуйте! Что-то совсем не могу разобраться. есть таблица, из которой надо вытащить 500 записей об обществах, затем в созданную таблицу добавить колонку new_date. Создать таблицу для протоколирования работы процедуры. Написать процедуру, которая перемешает дни в датах(формат дд.мм.гг) регистрации(есть даты с null) в датах регистрации обществ и запишет полученный результат в new_date. Процедура должна фиксировать в таблицу логирования уникальный номер записи, дату и время выполнения операции замены, изначальную дату регистрации и ее новое значение.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
01.05.2016, 22:09
Ответы с готовыми решениями:

Процедура регистрации пользователя
Нужно написать процедуру, которая будет регистрировать пользователя по никнейму и паролю и...

Написать программу, которая запрашивает дни рождения трех человек
Написать программу, которая запрашивает дни рождения трех человек, родившихся в марте 1981 г., и...

Создать функцию которая считает дни до конца года от заданной даты
Подсчитать кол-во дней от начала года до заданной даты. Создать функцию которая считает дни до...

Отфильтровать информацию о товарах, поставленных в четные дни и найти все товары поставленные в выходные дни
Помогите плиззз с заданием. 1)Используя расширенный фильтр, отфильтровать информацию о товарах,...

9
763 / 664 / 194
Регистрация: 24.11.2015
Сообщений: 2,158
01.05.2016, 22:22 2
Цитата Сообщение от minist Посмотреть сообщение
Написать процедуру, которая перемешает дни в датах
Что это значит? Пожалуйста подробнее, и желательно с примером. Мешать можно по-разному.
0
0 / 0 / 0
Регистрация: 01.05.2016
Сообщений: 5
01.05.2016, 23:48  [ТС] 3
как сказали, есть
19.02.14
25.11.63
06.09.13
11.12.89
а после перемешивания должно получиться, например
25.02.14
11.11.63
19.09.13
06.12.89
0
763 / 664 / 194
Регистрация: 24.11.2015
Сообщений: 2,158
02.05.2016, 12:02 4
Цитата Сообщение от minist Посмотреть сообщение
должно получиться, например
Сформулирую так: в отобранных 500 строках дни в датах должны перемешаться случайным образом.
Тогда еще два уточняющих вопроса.
1) В число 500 отобранных входят ли строки, где дата is null, или такие строки отбирать запрещено?
2) По каким правилам перемешиваются дни из пустой даты с днями из непустой даты? Проблема в том, что в Oracle нельзя создать дату, где только дни были бы пустыми. Дата либо вся пустая, либо вся непустая, да еще с правильными днями и месяцами, иначе Oracle такую неправильную дату не примет.
0
0 / 0 / 0
Регистрация: 01.05.2016
Сообщений: 5
02.05.2016, 15:11  [ТС] 5
1) входят любые 500 строк, в т.ч. с null
2) определенных комментариев по перемешиванию пустых дат нет, может их в exception как value_error можно как-то записать
0
763 / 664 / 194
Регистрация: 24.11.2015
Сообщений: 2,158
02.05.2016, 15:25 6
Цитата Сообщение от minist Посмотреть сообщение
может их в exception как value_error можно как-то записать
Тогда давайте так. Отбираются первые попавшиеся 500 записей, в том числе с null. затем дни случайным образом перемешиваются. Если вдруг конкретная замена невозможна (null или 31июня), то она пропускается, и дальше делается следующая замена. С null некоторая проблема, но если нет конкретных пожеланий, то сделаю, как получится.
0
0 / 0 / 0
Регистрация: 01.05.2016
Сообщений: 5
02.05.2016, 16:01  [ТС] 7
да, тогда получается так
0
763 / 664 / 194
Регистрация: 24.11.2015
Сообщений: 2,158
06.05.2016, 16:05 8
Для начала отвираем из базовой таблицы 500 записей и добавляем колонку. Делаем это операцией create table:
Кликните здесь для просмотра всего текста
SQL
1
2
3
4
CREATE TABLE mytest AS
SELECT id_rec,  reg_date,  reg_date  new_date
FROM base_table
WHERE rownum <=500;

Можно добавить любые колонки из базовой таблицы, если хочется. Дальше делаем замену дат (дней) в таблице mytest.
Теперь создадим объекты для логирования и выполнения создания процедуры.
Кликните здесь для просмотра всего текста
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
CREATE SEQUENCE test_seq
  INCREMENT BY 1
  START WITH 1
  MINVALUE 1
  MAXVALUE 9999999999999999999999999999
  NOCYCLE
  ORDER
  NOCACHE
;
CREATE OR REPLACE 
TYPE number_table IS TABLE OF NUMBER
;
CREATE TABLE mylog
(id         NUMBER,
 id_rec     NUMBER,
 op_date    TIMESTAMP,
 old_date   DATE,
 new_date   DATE,
 comments   varchar2(4000)
)
;
CREATE UNIQUE INDEX i1_mylog ON mylog
  (
    id      ASC,
    op_date ASC 
  )
;
CREATE OR REPLACE TRIGGER mylog_TBI
 BEFORE INSERT 
 ON mylog
 REFERENCING OLD AS OLD NEW AS NEW
 FOR EACH ROW
BEGIN
    SELECT test_seq.NEXTVAL, localtimestamp INTO :NEW.id, :NEW.op_date FROM dual;
END;

Я написал не процедуру, а анонимный блок. Понятно, что анонимный блок превращается в процедуру без параметрова легким движением руки.
Кликните здесь для просмотра всего текста
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
72
73
74
DECLARE
    TYPE numtab IS TABLE OF NUMBER INDEX BY binary_integer;
    numt    number_table;
    TYPE dattab IS TABLE OF DATE INDEX BY binary_integer;
    datt    dattab;
    high    NUMBER;
    cc1     varchar2(10);
    cc2     varchar2(10);
    sss     varchar2(1000);
    datex   DATE;
    datim   DATE;
    v_rec   NUMBER;
BEGIN
    INSERT INTO mylog(comments)
    VALUES('Начало работы');
    datt.delete;
    numt := number_table();
    --
    SELECT COUNT(reg_date) INTO high        -- определяем количество записей, где reg_date is not null
    FROM mytest;
    --
    FOR i IN 1.. 5*high
    LOOP
        numt.extend;
        numt(numt.count) := round(dbms_random.value(1,high));        --  создаем массив случайных чисел
    END LOOP;
    INSERT INTO mylog(comments)
    VALUES('Массив случайных чисел создан');
    --
    FOR  vv IN  (SELECT reg_date, rownum nn
                 FROM mytest  
                 WHERE reg_date IS NOT NULL    )
    loop
        datt(vv.nn) := vv.reg_date; --  создаем массив для перемешивания
    END loop;                       
    --
    FOR i IN 1.. 5*high 
    loop
        datex := datt(MOD(i, high)+1);
        datt(MOD(i, high)+1) := datt(numt(i));
        datt(numt(i)) := datex;                 --  перемешиваем даты в массиве
    END loop;                       
    INSERT INTO mylog(comments)
    VALUES('Перемешиваеие в массиве завершено');
    --
    FOR vv IN   (SELECT id_rec, reg_date, rowid id, rownum nn
                 FROM mytest  
                 WHERE reg_date IS NOT NULL    )
    LOOP
        v_rec := vv.id_rec;
        cc1 := to_char(last_day(vv.reg_date),'dd');
        cc2 := to_char(datt(vv.nn),'dd');
        datex:= vv.reg_date;
        IF to_number(cc2) > to_number(cc1) THEN 
            cc2 := cc1;
        END IF;
        datim := to_date(cc2||'.'||to_char(datex,'mm.yyyy'),'dd.mm.yyyy');
        UPDATE mytest 
           SET new_date = datim
        WHERE rowid= vv.id;
        INSERT INTO mylog(id_rec, old_date, new_date, comments)
        VALUES(vv.id_rec, datex, datim, 'Произведена штатная замена. Использована дата '||to_char(datt(vv.nn),'dd.mm.yyyy'));
    END loop;
    INSERT INTO mylog(comments)
    VALUES('Работа завершена');
    COMMIT;
exception
    WHEN others THEN
        sss := SQLERRM;
        INSERT INTO mylog(id_rec, old_date, new_date, comments)
        VALUES(v_rec, datex, datim, 'Err: '||sss);
        COMMIT;
        raise;
END;

Для лучшего перемешивания массив случайных чисел создается пятикратно избыточным. Перемешивание производится путем перестановки текущей даты со случайно выбранной датой. Просмотреть данные и таблицу логирования можно, например, так:
Кликните здесь для просмотра всего текста
SQL
1
2
3
4
5
6
SELECT id_rec, reg_date, new_date
FROM mytest;
 
SELECT id, op_date, old_date, new_date, comments
FROM mylog
ORDER BY id;


Добавлено через 4 минуты
Надо сказать, что записи, где дата пустая, не мудрствуя лукаво, пропускаются. Кроме того, в таблице логирования я использовал тип timestsamp и функцию localtimestamp вместо обычно используемого типа date и функции sysdate, поскольку все действо происходит за доли секунды.
1
0 / 0 / 0
Регистрация: 01.05.2016
Сообщений: 5
08.05.2016, 11:40  [ТС] 9
Спасибо. Можно еще несколько вопросов, правильно я понимаю что процедура должна выглядеть так:
create or replace procedure proc1
is
begin
<код> ?
И как можно ее запустить, чтобы увидеть как работает?
0
763 / 664 / 194
Регистрация: 24.11.2015
Сообщений: 2,158
08.05.2016, 12:20 10
Цитата Сообщение от minist Посмотреть сообщение
И как можно ее запустить, чтобы увидеть как работает?
То есть, просто запустить последние селекты и увидеть результат Вас не устраивает? Вы хотите видеть промежуточные этапы?
Если у Вас есть средство разработки с дебаггером, Вы можете им воспользоваться. Если нет, то можно вставить промежуточный серверный вывод и увидеть его на экране.
Сперва сделаем процедуру. Обратите внимание! Я вставил в нее пример серверного вывода в спул
Кликните здесь для просмотра всего текста
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
72
73
74
75
76
CREATE OR REPLACE PROCEDURE proc1  IS
    TYPE numtab IS TABLE OF NUMBER INDEX BY binary_integer;
    numt    number_table;
    TYPE dattab IS TABLE OF DATE INDEX BY binary_integer;
    datt    dattab;
    high    NUMBER;
    cc1     varchar2(10);
    cc2     varchar2(10);
    sss     varchar2(1000);
    datex   DATE;
    datim   DATE;
    v_rec   NUMBER;
BEGIN
    INSERT INTO mylog(comments)
    VALUES('Начало работы');
    datt.DELETE;
    numt := number_table();
    --
    SELECT COUNT(reg_date) INTO high        -- определяем количество записей, где reg_date is not null
    FROM mytest;
    --
    FOR i IN 1.. 5*high
    LOOP
        numt.extend;
        numt(numt.COUNT) := round(dbms_random.VALUE(1,high));        --  создаем массив случайных чисел
    END LOOP;
    INSERT INTO mylog(comments)
    VALUES('Массив случайных чисел создан');
    --
    FOR  vv IN  (SELECT reg_date, rownum nn
                 FROM mytest  
                 WHERE reg_date IS NOT NULL    )
    loop
        dbms_output.put_line('n='||vv.nn||'  date='||vv.reg_date);        -- пример серверного вывода в спул
        datt(vv.nn) := vv.reg_date; --  создаем массив для перемешивания
    END loop;                       
    --
    FOR i IN 1.. 5*high 
    loop
        datex := datt(MOD(i, high)+1);
        datt(MOD(i, high)+1) := datt(numt(i));
        dbms_output.put_line('i='||i||' n='||numt(i)||'  date_i='||datex||' date_n='||datt(numt(i)) );        -- второй пример серверного вывода в спул
        datt(numt(i)) := datex;                 --  перемешиваем даты в массиве
    END loop;                       
    INSERT INTO mylog(comments)
    VALUES('Перемешиваеие в массиве завершено');
    --
    FOR vv IN   (SELECT id_rec, reg_date, rowid id, rownum nn
                 FROM mytest  
                 WHERE reg_date IS NOT NULL    )
    LOOP
        v_rec := vv.id_rec;
        cc1 := to_char(last_day(vv.reg_date),'dd');
        cc2 := to_char(datt(vv.nn),'dd');
        datex:= vv.reg_date;
        IF to_number(cc2) > to_number(cc1) THEN 
            cc2 := cc1;
        END IF;
        datim := to_date(cc2||'.'||to_char(datex,'mm.yyyy'),'dd.mm.yyyy');
        UPDATE mytest 
           SET new_date = datim
        WHERE rowid= vv.id;
        INSERT INTO mylog(id_rec, old_date, new_date, comments)
        VALUES(vv.id_rec, datex, datim, 'Произведена штатная замена. Использована дата '||to_char(datt(vv.nn),'dd.mm.yyyy'));
    END loop;
    INSERT INTO mylog(comments)
    VALUES('Работа завершена');
    COMMIT;
exception
    WHEN others THEN
        sss := SQLERRM;
        INSERT INTO mylog(id_rec, old_date, new_date, comments)
        VALUES(v_rec, datex, datim, 'Err: '||sss);
        COMMIT;
        raise;
END;

Затем подаем команду на включение серверного вывода
SQL
1
SET SERVEROUTPUT ON SIZE UNLIMITED;
Если надо, серверный вывод можно отключить
SQL
1
SET SERVEROUTPUT OFF;
Наконец, запускаем процедуру
SQL
1
2
3
BEGIN
    proc1;
END;
Ну и можно посмотреть результат работы теми селектами, которые я приводил раньше

Добавлено через 4 минуты
Кстати, серверный вывод можно увидеть и при работе анонимного блока. Как раз лучше в анонимном блоке во время отладки смотреть, а потом в теле процедуры убирать (комментировать), чтобы не было лишней нагрузки на сервер
0
08.05.2016, 12:20
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
08.05.2016, 12:20
Помогаю со студенческими работами здесь

Напишите программу, которая сравнивает дни рождения двух человек и определяет кто их них старше
Напишите программу,которая сравнивает дни рождения 2-х человек и определяет кто их них старше....

Нужно посчитать суммы за предыдущие дни в ячейке, которая каждый день будет сдвигаться вправо
В файле екселя добавляются данные каждый день. Нужно посчитать средствами VBA или формулами суммы...

Напишите программу, которая запрашивает у пользователя 2 даты в формате дд.мм.гггг. Дни, месяцы и года следует присвоить
Напишите программу, которая запрашивает у пользователя 2 даты в формате дд.мм.гггг. Дни, месяцы и...

Процедура которая вызывает функцию
Здравствуйте! Помогите с заданием, мне нужно как то эту процедуру сделать так что бы он вызывал...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
10
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru