Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Oracle Новый топик    Ответить
 Помогите с написанием функции.  [new]
Ukki
Guest
Задача: Имеется таблица с двумя столбцами: имя и приоритет
Например:
Name Prior
Kate 1
Sarah 2
Olivie 3
Floid 5
Michel 8
Robert 9
Luc 11
Необходимо сделать так, чтоб если добавлять Имя с уже существующим приоритетом, то имя с совпадающим приоритетом
приобретало приоритет на 1 больше и все нижние сдигались тоже.

Например вставляет:
Mike 2

И должно получиться:

Kate 1
Mike 2
Sarah 2 ->3
Olivie 3 ->4
Floid 5
Michel 8
Robert 9
Luc 11


Как это можно реализовать с помощью функции?
Сама чего то написала, но не работает...
12 авг 07, 19:48    [4513837]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с написанием функции.  [new]
alex-ls
Member

Откуда: Иркутская обл - Пенза - Москва
Сообщений: 6911
Как я понял, это некое распределение номеров будет производится функцией? Все-таки такие вещи делать не очень хорошо:
1. Используем сиквенсы, тогда получаем пропуски
2. Используем серилизацию, тогда получаем узкое место по производительности.
3. Используем MAX и можем получить дублирование приоритетов.
Лучше опишите задачу, как ее Вам поставили...
12 авг 07, 20:04    [4513850]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с написанием функции.  [new]
Ukki
Guest
alex-ls
Как я понял, это некое распределение номеров будет производится функцией? Все-таки такие вещи делать не очень хорошо:
1. Используем сиквенсы, тогда получаем пропуски
2. Используем серилизацию, тогда получаем узкое место по производительности.
3. Используем MAX и можем получить дублирование приоритетов.
Лучше опишите задачу, как ее Вам поставили...



задачу мне поставили примерно так как я и написала, просто нарисовали табличку и написали insert_f('AL', 3)
update_f('fhk', 3)
и нарисовали другую табличку с результатом.
12 авг 07, 20:12    [4513855]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с написанием функции.  [new]
SY
Member

Откуда: Middlebury, CT USA
Сообщений: 10042
SQL> CREATE TABLE UKKI(
  2                    NAME  VARCHAR2(10),
  3                    PRIORITY NUMBER
  4                   )
  5  /

Table created.

SQL> INSERT
  2    INTO UKKI
  3    SELECT  'Kate', 1 FROM DUAL UNION ALL
  4    SELECT  'Sarah', 2 FROM DUAL UNION ALL
  5    SELECT  'Olivie', 3 FROM DUAL UNION ALL
  6    SELECT  'Floid', 5 FROM DUAL UNION ALL
  7    SELECT  'Michel', 8 FROM DUAL UNION ALL
  8    SELECT  'Robert', 9 FROM DUAL UNION ALL
  9    SELECT  'Luc', 11 FROM DUAL
 10  /

7 rows created.

SQL> MERGE
  2    INTO UKKI U
  3    USING (
  4            SELECT 'Mike' NAME,
  5                    2 PRIORITY,
  6                    ' ' RID
  7              FROM  DUAL
  8           UNION ALL
  9            SELECT  NAME,
 10                    PRIORITY + 1 PRIORITY,
 11                    ROWIDTOCHAR(ROWID) RID
 12              FROM  UKKI
 13              WHERE PRIORITY >= 2
 14          ) M
 15    ON (M.RID = ROWIDTOCHAR(U.ROWID))
 16    WHEN MATCHED THEN UPDATE SET U.PRIORITY = M.PRIORITY
 17    WHEN NOT MATCHED THEN INSERT VALUES(M.NAME,M.PRIORITY)
 18  /

7 rows merged.

SQL> SELECT  *
  2    FROM  UKKI
  3    ORDER BY PRIORITY
  4  /

NAME         PRIORITY
---------- ----------
Kate                1
Mike                2
Sarah               3
Olivie              4
Floid               6
Michel              9
Robert             10
Luc                12

8 rows selected.

SQL> 

SY.
12 авг 07, 20:33    [4513868]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с написанием функции.  [new]
alex-ls
Member

Откуда: Иркутская обл - Пенза - Москва
Сообщений: 6911
SY
SY.

а если два или больше юзеров одновременно вызовут функцию?
12 авг 07, 20:52    [4513880]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с написанием функции.  [new]
ukki
Guest
SY
SQL> CREATE TABLE UKKI(
  2                    NAME  VARCHAR2(10),
  3                    PRIORITY NUMBER
  4                   )
  5  /

Table created.

SQL> INSERT
  2    INTO UKKI
  3    SELECT  'Kate', 1 FROM DUAL UNION ALL
  4    SELECT  'Sarah', 2 FROM DUAL UNION ALL
  5    SELECT  'Olivie', 3 FROM DUAL UNION ALL
  6    SELECT  'Floid', 5 FROM DUAL UNION ALL
  7    SELECT  'Michel', 8 FROM DUAL UNION ALL
  8    SELECT  'Robert', 9 FROM DUAL UNION ALL
  9    SELECT  'Luc', 11 FROM DUAL
 10  /

7 rows created.

SQL> MERGE
  2    INTO UKKI U
  3    USING (
  4            SELECT 'Mike' NAME,
  5                    2 PRIORITY,
  6                    ' ' RID
  7              FROM  DUAL
  8           UNION ALL
  9            SELECT  NAME,
 10                    PRIORITY + 1 PRIORITY,
 11                    ROWIDTOCHAR(ROWID) RID
 12              FROM  UKKI
 13              WHERE PRIORITY >= 2
 14          ) M
 15    ON (M.RID = ROWIDTOCHAR(U.ROWID))
 16    WHEN MATCHED THEN UPDATE SET U.PRIORITY = M.PRIORITY
 17    WHEN NOT MATCHED THEN INSERT VALUES(M.NAME,M.PRIORITY)
 18  /

7 rows merged.

SQL> SELECT  *
  2    FROM  UKKI
  3    ORDER BY PRIORITY
  4  /

NAME         PRIORITY
---------- ----------
Kate                1
Mike                2
Sarah               3
Olivie              4
Floid               6
Michel              9
Robert             10
Luc                12

8 rows selected.

SQL> 

SY.



спасибо большое, только можно несколько вопросов(может и глуппых)
1. нельзя ли вместо
INSERT
2 INTO UKKI
3 SELECT 'Kate', 1 FROM DUAL UNION ALL

написать просто insert into ukki values('Kate', 1)
2. и также в этом случае
USING (
4 SELECT 'Mike' NAME,
5 2 PRIORITY,
6 ' ' RID
7 FROM DUAL
8 UNION ALL

без select ... from dual

3.зачем используется UNION ALL
12 авг 07, 21:07    [4513900]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с написанием функции.  [new]
SY
Member

Откуда: Middlebury, CT USA
Сообщений: 10042
ukki
спасибо большое, только можно несколько вопросов(может и глуппых)
1. нельзя ли вместо
INSERT
2 INTO UKKI
3 SELECT 'Kate', 1 FROM DUAL UNION ALL

написать просто insert into ukki values('Kate', 1)
2. и также в этом случае
USING (
4 SELECT 'Mike' NAME,
5 2 PRIORITY,
6 ' ' RID
7 FROM DUAL
8 UNION ALL

без select ... from dual

3.зачем используется UNION ALL


Well:

1) INSERT INTO UKKI SELECT... is used simply to populate table with initial data (data you supplied). So it is completely irrelevant how table is populated.

2) We need to construct driver table providing info on rows to be inserted and updated. Rows we need to update are rows in table UKKI with priority >= 2. Row we need to insert is Mike, 2. We use UNION ALL to construct such a table. And since we match on ROWID we add ' ' to Mike, 2 - ' ' can never match any ROWID (which is exactly what we want).

SY.
12 авг 07, 21:22    [4513922]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с написанием функции.  [new]
__vvp_
Member

Откуда: Санкт-Петербург
Сообщений: 1158
SY

NAME PRIORITY
---------- ----------
Kate 1
Mike 2
Sarah 3
Olivie 4

Floid 6
Michel 9
Robert 10
Luc 12


8 rows selected.

SY.


Выделенные красным строки не должны быть изменены.

Мой вариант с определением непрерывного диапазона PRIORITY:

MERGE
INTO UKKI U
USING (
       SELECT 'Mike' NAME,
              2 PRIORITY,
              null RID
       FROM  DUAL

       UNION ALL
-- --------------------------------------------------------------------
       select t.NAME,
              t.PRIORITY + 1,
              ROWIDTOCHAR(t.ROWID) RID
       from ukki t,
-- Определить непрерывный диапазон PRIORITY для обновления
            (select min_PRIORITY, max_PRIORITY
             from (
                   select min(PRIORITY) min_PRIORITY,
                          max(PRIORITY) max_PRIORITY
                   from ukki
                   where PRIORITY >= 2
                   group by PRIORITY - rownum - 1
                   order by 1
                  )
             where rownum = 1) rng
       where t.PRIORITY between rng.min_PRIORITY and rng.max_PRIORITY
-- --------------------------------------------------------------------
      ) M
ON (M.RID = ROWIDTOCHAR(U.ROWID))
WHEN MATCHED THEN UPDATE SET U.PRIORITY = M.PRIORITY
WHEN NOT MATCHED THEN INSERT VALUES(M.NAME, M.PRIORITY);
12 авг 07, 21:39    [4513947]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с написанием функции.  [new]
Ukki
Guest
SY
ukki
спасибо большое, только можно несколько вопросов(может и глуппых)
1. нельзя ли вместо
INSERT
2 INTO UKKI
3 SELECT 'Kate', 1 FROM DUAL UNION ALL

написать просто insert into ukki values('Kate', 1)
2. и также в этом случае
USING (
4 SELECT 'Mike' NAME,
5 2 PRIORITY,
6 ' ' RID
7 FROM DUAL
8 UNION ALL

без select ... from dual

3.зачем используется UNION ALL


Well:

1) INSERT INTO UKKI SELECT... is used simply to populate table with initial data (data you supplied). So it is completely irrelevant how table is populated.

2) We need to construct driver table providing info on rows to be inserted and updated. Rows we need to update are rows in table UKKI with priority >= 2. Row we need to insert is Mike, 2. We use UNION ALL to construct such a table. And since we match on ROWID we add ' ' to Mike, 2 - ' ' can never match any ROWID (which is exactly what we want).

SY.


thank you!
12 авг 07, 21:40    [4513951]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с написанием функции.  [new]
Volder
Member

Откуда: Москва
Сообщений: 474
__vvp_
Мой вариант с определением непрерывного диапазона PRIORITY:
а с иерархией не проще было бы?
...connect by prior priority+1=priority
     start with priority=2
12 авг 07, 22:03    [4514000]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с написанием функции.  [new]
SY
Member

Откуда: Middlebury, CT USA
Сообщений: 10042
alex-ls
SY
SY.

а если два или больше юзеров одновременно вызовут функцию?


And how is it different from function (btw MERGE presents less issues)? As you said, Лучше опишите задачу, как ее Вам поставили.

SY.
12 авг 07, 22:03    [4514004]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с написанием функции.  [new]
alex-ls
Member

Откуда: Иркутская обл - Пенза - Москва
Сообщений: 6911
SY
alex-ls
SY
SY.

а если два или больше юзеров одновременно вызовут функцию?


And how is it different from function (btw MERGE presents less issues)? As you said, Лучше опишите задачу, как ее Вам поставили.

SY.

Задача явно напоминает генерацию номеров приоритетов во время вставки. Два юзера одновременно запускают механизм и будет беда... Если это просто лаба, тогда другое дело. Мой комментарий относится больше не к конкретному решению, а вообщем...
12 авг 07, 22:09    [4514010]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с написанием функции.  [new]
__vvp_
Member

Откуда: Санкт-Петербург
Сообщений: 1158
Volder
__vvp_
Мой вариант с определением непрерывного диапазона PRIORITY:
а с иерархией не проще было бы?
...connect by prior priority+1=priority
     start with priority=2


Да, в этом случае можно, т.к. только один диапазон нужен.

MERGE
INTO UKKI U
USING (
       SELECT 'Mike' NAME,
              2 PRIORITY,
              null RID
       FROM  DUAL

       UNION ALL
-- Определить непрерывный диапазон PRIORITY для обновления
       select NAME,
              PRIORITY + 1,
              ROWIDTOCHAR(ROWID)
       from ukki
       start with priority = 2
       connect by prior priority + 1 = priority
-- --------------------------------------------------------------------
      ) M
ON (M.RID = ROWIDTOCHAR(U.ROWID))
WHEN MATCHED THEN UPDATE SET U.PRIORITY = M.PRIORITY
WHEN NOT MATCHED THEN INSERT VALUES(M.NAME, M.PRIORITY);

select * from ukki;

NAME PRIORITY
---------- ----------
Kate 1
Sarah 3
Olivie 4

Floid 5
Michel 8
Robert 9
Luc 11
Mike 2

8 rows selected.
13 авг 07, 08:08    [4514389]     Ответить | Цитировать Сообщить модератору
Все форумы / Oracle Ответить