Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Oracle Новый топик    Ответить
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
 Как лучше подчищать ссылки, которые никуда не ссылаются?  [new]
flexed
Member

Откуда:
Сообщений: 115
Есть вот такая структура:
CREATE OR REPLACE TYPE manager_t AS OBJECT (
employee_data REF employee_t,
work_telephones telephones_t,
);
/

CREATE OR REPLACE TYPE managers_t AS TABLE OF REF manager_t;
/

CREATE OR REPLACE TYPE project_t AS OBJECT (
name varchar2(100),
startDate date,
endDate date,
manager REF manager_t,
);
/

Если мы удалим менеджера, но перед этим добавив ссылку в project, то ссылка будет ссылаться в никуда. И произойдёт ошибка при обращении к этой ссылке.

Как можно в данном случае решить проблему? Есть какие-то функции для борьбы с этим?
3 дек 05, 03:10    [2138004]     Ответить | Цитировать Сообщить модератору
 Re: Как лучше подчищать ссылки, которые никуда не ссылаются?  [new]
u_gray
Member

Откуда: Москва
Сообщений: 170
IS DANGLING ?
3 дек 05, 10:44    [2138072]     Ответить | Цитировать Сообщить модератору
 Re: Как лучше подчищать ссылки, которые никуда не ссылаются?  [new]
flexed
Member

Откуда:
Сообщений: 115
u_gray
IS DANGLING ?


Спасибо за ответ.

Решил делать проверку на тригере.

Есть такая структура

CREATE OR REPLACE TYPE employee_t AS OBJECT (
id number, 
first_name varchar2(50),
last_name varchar2(50)
);
/

CREATE OR REPLACE TYPE programmer_t AS OBJECT (
employee_data REF employee_t,
programming_languages prog_languages_t
);
/

CREATE OR REPLACE TYPE programmers_t AS TABLE OF REF programmer_t;
/

CREATE OR REPLACE TYPE manager_t AS OBJECT (
employee_data REF employee_t
);
/

CREATE OR REPLACE TYPE project_t AS OBJECT (
name varchar2(100),
startDate date,
endDate date,
manager REF manager_t,
programmers programmers_t
);
/

Хочу позаботится о таблице project типа project_t. Если я удаляю из таблицы manager менеджера, который принадлежит также и проекту (в проекте есть ссылка), то при попытки доступа к этой ссылке в таблице project, получаю ошибку. Чтобы этого избежать, делаю так.

CREATE TRIGGER MANAGERDANGLING_TRG
AFTER DELETE ON manager
FOR EACH ROW
BEGIN
DELETE FROM project p WHERE p.manager IS DANGLING;
END;
/

Тригер создаётся, и когда я пытаюсь удалить Менеджера в таблице manager получаю:

ORA-04091: table LG022314.MANAGER is mutating, trigger/function may not see it
ORA-06512: at "LG022314.MANAGERDANGLING_TRG", line 2
ORA-04088: error during execution of trigger 'LG022314.MANAGERDANGLING_TRG'
ORA-06512: at line 1

Но тут про DANGLING ничего не сказано, да и думаю что-то не так, я вообще не одно поле manager удалить не могу, которое даже и к проекту не принадлежит. Т.е. удаление менеджеров полностю блокировано.

Если я в тригер добавляю для программистов (коллекция ссылок),

DELETE FROM project p WHERE p.programmers IS DANGLING;

То получаю ошибку компиляции.

В моём случае также не срабатывает ограничение ссылочной целостности.

CREATE TABLE programmer OF programmer_t(employee_data REFERENCES employee)
NESTED TABLE programming_languages STORE AS prog_proglang_nt;

CREATE TABLE manager OF manager_t(employee_data REFERENCES employee);

CREATE TABLE project OF project_t
NESTED TABLE programmers STORE AS proj_prog_nt;

Это здесь:

employee_data REFERENCES employee

В другом случае так,

ALTER TABLE project ADD (SCOPE FOR (manager) IS manager);												  
ALTER TABLE proj_prog_nt ADD (SCOPE FOR (COLUMN_VALUE) IS programmer);	

Без моего тригера, но со ссылочной целостностю удаляю ниже приведённым способом, тогда удаление проходит:

DECLARE rowcnt number;
BEGIN
SELECT COUNT(*) INTO rowcnt FROM manager m WHERE m.employee_data.id=1;
IF rowcnt = 0 THEN 
RAISE_APPLICATION_ERROR(-20906, 'Employee with given ID: was not found.'); " +
ELSE
DELETE FROM manager m WHERE m.employee_data.id=1; 
DELETE FROM employee e WHERE e.id=1;
END IF;
END;

С тригером, ничего не проходит...

Помогите плиз разобраться.
3 дек 05, 12:47    [2138145]     Ответить | Цитировать Сообщить модератору
 Re: Как лучше подчищать ссылки, которые никуда не ссылаются?  [new]
u_gray
Member

Откуда: Москва
Сообщений: 170
С триггером не проходит, т.к.

ORA

ORA-04091: table LG022314.MANAGER is mutating, trigger/function may not see it


А таблица мутирует видимо потому, что, project ссылается на manager (это особенность не только объектных таблиц)

ИМХО: или борьба с мутацией (обсуждалось неоднократно) или делать нужно не в триггере
3 дек 05, 14:34    [2138232]     Ответить | Цитировать Сообщить модератору
 Re: Как лучше подчищать ссылки, которые никуда не ссылаются?  [new]
u_gray
Member

Откуда: Москва
Сообщений: 170
Дело в том, что для обычных таблиц Oracle не даст удалить записи из главной таблицы, если есть записи в подчиненных. А для объектных дает удалять, поэтому в принципе для отслеживания такой ситуации рекомендуется

Чак Кизер Предмет желаний (The Object of Your Desire, by Chuck Kueser)

Чтобы избежать висящих ссылок, можно создать внешний ключ на ref-столбцы. Это наилучший из вариантов (или неоправданная избыточность, в зависимости от точки зрения). Ref-ссылки удобны и эффективны, когда применяются вместе с внешними ключами. Кроме того, когда это требуется, можно использовать индексированные ref-ссылки.



flexed

И произойдёт ошибка при обращении к этой ссылке.


на это отвечает:

Jet Info № 9,10(64,65)/1998 стр.27


UPDATE project
SET manager = NULL
WHERE manager IS DANGLING;

смысл совершаемых действий достаточно очевиден –
«обнулить» висячие ссылки.

3 дек 05, 14:55    [2138260]     Ответить | Цитировать Сообщить модератору
 Re: Как лучше подчищать ссылки, которые никуда не ссылаются?  [new]
flexed
Member

Откуда:
Сообщений: 115
u_gray
Дело в том, что для обычных таблиц Oracle не даст удалить записи из главной таблицы, если есть записи в подчиненных. А для объектных дает удалять, поэтому в принципе для отслеживания такой ситуации рекомендуется



Огромное спасибо за подробное разъяснение!

А как обнулить висячие ссылки в коллекции programmers programmers_t, которые прикреплены к проекту?
3 дек 05, 15:23    [2138289]     Ответить | Цитировать Сообщить модератору
 Re: Как лучше подчищать ссылки, которые никуда не ссылаются?  [new]
flexed
Member

Откуда:
Сообщений: 115
Один программист может быть сразу в двух проектах, т.е. его ссылка может быть в проекте Web-Services и Client-Server

Вот таким запросом я могу вытащить все эти ссылки, в каком проекте программист N3 был замечен

SELECT p.COLUMN_VALUE from project pr, table(pr.programmers) p 
where COLUMN_VALUE = (select ref(pp) from programmer pp where pp.employee_data.id = 3);

COLUMN_VALUE
--------------------------------------------------------------------------------
00002202080703C8EC48D517EBE0440003BA08D82A0703C8EC48BA17EBE0440003BA08D82A
00002202080703C8EC48D517EBE0440003BA08D82A0703C8EC48BA17EBE0440003BA08D82A

Как теперь эти ссылки удалить? Если я их UPDATE'ом обнулю, то в коллекции, как упоминал SY будут пустые ссылки.

Подобный запрос позволяет только в одной таблице, например проекте 'Web-Services' удалить ссылки.

DELETE TABLE(SELECT programmers FROM project WHERE name='Web-Services')
  WHERE column_value = (
                        SELECT  REF(prg)
                          FROM  programmer prg
                          WHERE employee_data = (
                                                 SELECT  REF(e)
                                                   FROM  employee e
                                                   WHERE id = 3
                                                )
                       )
/

Если я убираю WHERE name='Web-Services', то получаю ошибку, т.к. ответ содержит более одного поля. Но как же пройтись по всем проектам и поудалять там ссылки?

В моем примере две одинаковых ссылки, в двух разных проектах.
3 дек 05, 17:10    [2138428]     Ответить | Цитировать Сообщить модератору
 Re: Как лучше подчищать ссылки, которые никуда не ссылаются?  [new]
flexed
Member

Откуда:
Сообщений: 115
flexed


Как теперь эти ссылки удалить? Если я их UPDATE'ом обнулю, то в коллекции, как упоминал SY будут пустые ссылки.



Т.е. проверить сначала, подвисшие ли эти ссылки (IS DANGLING) и потом по всем проектам пройтись и удалить если они подвисшие.
3 дек 05, 17:12    [2138434]     Ответить | Цитировать Сообщить модератору
 Re: Как лучше подчищать ссылки, которые никуда не ссылаются?  [new]
SY
Member

Откуда: Middlebury, CT USA
Сообщений: 10045
You need a lot of RTFM to do. For manager column:

ALTER TABLE project
  MODIFY manager NOT NULL
/
ALTER TABLE project
  ADD CONSTRAINT project_manager
    FOREIGN KEY(manager)
    REFERENCES manager
/

For programmers column:

ALTER TABLE project
  MODIFY programmers NOT NULL
/
ALTER TABLE proj_prog_nt
  ADD SCOPE FOR(column_value) IS programmer
/

and change type programmers_t to:

CREATE OR REPLACE TYPE programmers_t AS TABLE OF REF programmer_t NOT NULL;
/

SY.
3 дек 05, 21:09    [2138688]     Ответить | Цитировать Сообщить модератору
 Re: Как лучше подчищать ссылки, которые никуда не ссылаются?  [new]
flexed
Member

Откуда:
Сообщений: 115
SY
You need a lot of RTFM to do. For manager column:



Thanks for the answer SY.

Yes, you are right, I learned much, but should do and read many things myself.

To the question. I tried this thing

"UPDATE project SET manager = NULL WHERE manager IS DANGLING;"
and it works fine.

I don't know how to do it with collection (in programmers case). Constraints are good, but they won't do the dirty DANGLING job, just block some action the user don't want to have sometimes. I mean if I want to fire programmer, maybe I don't care about the project, and it would be nice to handle this reference as it was with this manager = null update. Maybe it's not a good approach, but it works.

It seems to be difficult with collections. It's really pitty.
3 дек 05, 23:42    [2138872]     Ответить | Цитировать Сообщить модератору
 Re: Как лучше подчищать ссылки, которые никуда не ссылаются?  [new]
flexed
Member

Откуда:
Сообщений: 115
SY
You need a lot of RTFM to do. For manager column:

ALTER TABLE project
  MODIFY manager NOT NULL
/
ALTER TABLE project
  ADD CONSTRAINT project_manager
    FOREIGN KEY(manager)
    REFERENCES manager
/

For programmers column:

ALTER TABLE project
  MODIFY programmers NOT NULL
/
ALTER TABLE proj_prog_nt
  ADD SCOPE FOR(column_value) IS programmer
/

and change type programmers_t to:

CREATE OR REPLACE TYPE programmers_t AS TABLE OF REF programmer_t NOT NULL;
/

SY.


Is there any approach to handle the "danglig" links as it could be in reference (with UPDATE SET manager NULL) case?

Is it possible in Oracle 9 and higher? I suppose that we have to do it always, if we have some collections in our project, isn't it?

The user won't search for a child object's references, if he wants to fire the manager or programmer....
4 дек 05, 19:47    [2139649]     Ответить | Цитировать Сообщить модератору
 Re: Как лучше подчищать ссылки, которые никуда не ссылаются?  [new]
SY
Member

Откуда: Middlebury, CT USA
Сообщений: 10045
flexed
Is there any approach to handle the "danglig" links


What do you mean by handling? I do not understand why do you need DANDLING if you say "I mean if I want to fire programmer, maybe I don't care about the project". Same way, I assume if you fire a programmer you do not care about the project either. So list of programmers for the project will have a REF to fired programmer. If you DEREF it, you will get NULLs for all programmer_t columns. Oracle will not raise an error.

SY.
4 дек 05, 20:25    [2139700]     Ответить | Цитировать Сообщить модератору
 Re: Как лучше подчищать ссылки, которые никуда не ссылаются?  [new]
flexed
Member

Откуда:
Сообщений: 115
SY
flexed
Is there any approach to handle the "danglig" links


What do you mean by handling? I do not understand why do you need DANDLING if you say "I mean if I want to fire programmer, maybe I don't care about the project". Same way, I assume if you fire a programmer you do not care about the project either. So list of programmers for the project will have a REF to fired programmer. If you DEREF it, you will get NULLs for all programmer_t columns. Oracle will not raise an error.

SY.


I wrote a Java program, that works with Oracle.

If I delete programmer, from the table programmer and there is the same programmer in the project table (ref), then, when I try to open the table project, Java gives a lot of red text like this:

Exception occurred during event dispatching:
java.lang.NullPointerException
	at database.DBProg.selectProgrammers(DBProg.java:73)

If I don't delete programmer from the programmers table, I can open the project with the programmer attended to it.

The same situation was with managers, where manager were REF, not collection.

Now when I delete manager from manager table, I do it like this

String query = "DECLARE rowcnt number; " +
"BEGIN " +
"SELECT COUNT(*) INTO rowcnt FROM manager m WHERE m.employee_data.id="+id+"; "+
"IF rowcnt = 0 THEN " +
"RAISE_APPLICATION_ERROR(-20906, 'Employee with given ID: was not found.'); " +
"ELSE " +
"DELETE FROM manager m WHERE m.employee_data.id="+id+"; " +
"DELETE FROM employee e WHERE e.id="+id+"; "+
"UPDATE project SET manager = NULL WHERE manager IS DANGLING; "+
"END IF; " +
"END;";

So, this UPDATE project SET manager = NULL WHERE manager IS DANGLING; helps me to avoid such an error and removes manager from the project table "automatically".

The same thing I want for collection of programmers.

Table structure:

CREATE OR REPLACE TYPE programmers_t AS TABLE OF REF programmer_t;
/

CREATE OR REPLACE TYPE project_t AS OBJECT (
name varchar2(50),
manager REF manager_t,
programmers programmers_t
);
/

Do you understand what I am talking about? Maybe I express myself not so good, if you didn't get it, I'll describe it in more details.

And thank a lot for your help SY.
4 дек 05, 21:25    [2139757]     Ответить | Цитировать Сообщить модератору
 Re: Как лучше подчищать ссылки, которые никуда не ссылаются?  [new]
SY
Member

Откуда: Middlebury, CT USA
Сообщений: 10045
Well, it is no different from any other nested table update. For example:

UPDATE TABLE(SELECT products FROM client)
SET column_value = NULL
WHERE column_value IS DANGLING
/

SY.
4 дек 05, 22:11    [2139781]     Ответить | Цитировать Сообщить модератору
 Re: Как лучше подчищать ссылки, которые никуда не ссылаются?  [new]
flexed
Member

Откуда:
Сообщений: 115
SY
Well, it is no different from any other nested table update. For example:

UPDATE TABLE(SELECT products FROM client)
SET column_value = NULL
WHERE column_value IS DANGLING
/

SY.


Thanks a lot SY! I really appreciate your help. The sample with constraints was also very good, I will look when it is better to use constraints, when triggers or just update.

Have a nice end of the weekend.
4 дек 05, 23:08    [2139816]     Ответить | Цитировать Сообщить модератору
 Re: Как лучше подчищать ссылки, которые никуда не ссылаются?  [new]
flexed
Member

Откуда:
Сообщений: 115
I tried it, and an error occured.

SQL> select programmers from project;

PROGRAMMERS
--------------------------------------------------------------------------------
PROGRAMMERS_T(0000220208071E918EDEEC6664E0440003BA08D82A071E918EDEB86664E0440003
BA08D82A)

PROGRAMMERS_T()

SQL> update table(select programmers from project) set column_value = null where column_value is dangling;
update table(select programmers from project) set column_value = null where column_value is dangling
             *
ERROR at line 1:
ORA-01427: single-row subquery returns more than one row


SQL> 
4 дек 05, 23:33    [2139825]     Ответить | Цитировать Сообщить модератору
 Re: Как лучше подчищать ссылки, которые никуда не ссылаются?  [new]
flexed
Member

Откуда:
Сообщений: 115
I try to change query. Begin so:

SQL> select p.column_value from project pp, table(pp.programmers) p where p.column_value       is dangling;

no rows selected

SQL> delete from programmer p where p.employee_data.id=4;

1 row deleted.

SQL> select p.column_value from project pp, table(pp.programmers) p where p.column_value       is dangling;

COLUMN_VALUE
--------------------------------------------------------------------------------
0000220208071E918EE0776664E0440003BA08D82A071E918EE0346664E0440003BA08D82A

SQL>

Now, put it in UPDATE

UPDATE TABLE(select p.column_value from project pp, table(pp.programmers) p) SET p.column_value = NULL WHERE p.column_value IS DANGLING;

Get an error:


SQL> update table(select p.column_value from project pp, table(pp.programmers) p) set column_value = null where column_value is dangling;
update table(select p.column_value from project pp, table(pp.programmers) p) set column_value = null where column_value is dangling
*
ERROR at line 1:
ORA-22905: cannot access rows from a non-nested table item

And java says so:

java.sql.SQLException: ORA-06550: line 1, column 351:
PLS-00201: identifier 'PP.PROGRAMMERS' must be declared
ORA-06550: line 1, column 293:
PL/SQL: SQL Statement ignored

How can I access row from a non-nested table?
4 дек 05, 23:57    [2139832]     Ответить | Цитировать Сообщить модератору
 Re: Как лучше подчищать ссылки, которые никуда не ссылаются?  [new]
SY
Member

Откуда: Middlebury, CT USA
Сообщений: 10045
flexed
I tried it, and an error occured.


Again, you misunderstand nested tables. And it is my mistake for simplifying SQL to a point it will work only if table project has one row. Syntax

INSERT/UPDATE/DELETE TABLE(SELECT nested_table from main_table)

can insert/update/delete nested table for a single row in main_table, not for all/multiple rows. Same way like you can not insert/update/delete rows in more that one table with a single INSERT/UPDATE/DELETE, you can not insert/update/delete rows in more that one nested table with a single INSERT/UPDATE/DELETE. To insert/update/delete rows in more that one nested table you nust issue UPDATE against main table. So since in general project table contains multiple projects, you either need to loop through each project and issue:

FOR v_rec IN (SELECT name FROM project) LOOP
  UPDATE  TABLE(SELECT products FROM client WHERE name = v_rec.name)
    SET   column_value = NULL
  WHERE column_value IS DANGLING;
END LOOP;

Or issue:

UPDATE  project p1
  SET   programmers = CAST(
                           MULTISET(
                                    SELECT  CASE
                                              WHEN column_value IS DANGLING
                                                THEN NULL
                                              ELSE column_value
                                            END
                                      FROM  project p2,
                                            TABLE(p2.programmers)
                                      WHERE p2.name = p1.name
                                   )
                           AS programmers_t
                          )
/

However, it will update all nested tables programmers in project table which is not too efficient.

SY.
5 дек 05, 01:12    [2139868]     Ответить | Цитировать Сообщить модератору
 Re: Как лучше подчищать ссылки, которые никуда не ссылаются?  [new]
flexed
Member

Откуда:
Сообщений: 115
SY


FOR v_rec IN (SELECT name FROM project) LOOP
  UPDATE  TABLE(SELECT products FROM client WHERE name = v_rec.name)
    SET   column_value = NULL
  WHERE column_value IS DANGLING;
END LOOP;

Or issue:

UPDATE  project p1
  SET   programmers = CAST(
                           MULTISET(
                                    SELECT  CASE
                                              WHEN column_value IS DANGLING
                                                THEN NULL
                                              ELSE column_value
                                            END
                                      FROM  project p2,
                                            TABLE(p2.programmers)
                                      WHERE p2.name = p1.name
                                   )
                           AS programmers_t
                          )
/

However, it will update all nested tables programmers in project table which is not too efficient.

SY.


I see the problem. I tried both samples.

The first one, works without error, I don't know why, there are still programmers in project, with dangling references.

I changed a little the code, but it shouldn't cause a problem.

FOR v_rec IN (SELECT name FROM project) LOOP 
UPDATE TABLE(SELECT programmers FROM project WHERE name = v_rec.name)
SET column_value = NULL WHERE column_value IS DANGLING;
END LOOP;

The second one gives an error, something wrong with a CASE statement.

I don't understand why it doesn't catch the dangling references...
5 дек 05, 01:40    [2139878]     Ответить | Цитировать Сообщить модератору
 Re: Как лучше подчищать ссылки, которые никуда не ссылаются?  [new]
SY
Member

Откуда: Middlebury, CT USA
Сообщений: 10045
SQL> select * from v$version;

BANNER
----------------------------------------------------------------
Oracle8i Enterprise Edition Release 8.1.7.0.0 - Production
PL/SQL Release 8.1.7.0.0 - Production
CORE    8.1.7.0.0       Production
TNS for 32-bit Windows: Version 8.1.7.0.0 - Production
NLSRTL Version 3.4.1.0.0 - Production

SQL> delete programmer;

2 rows deleted.

SQL> select name,programmers from project;

NAME
------------------------------
PROGRAMMERS
----------------------------------------------------------------------------------------------------
Web-Services
PROGRAMMERS_T(00002202082700F3AD3225453B8D7F8E8F6C4EC761E59031CC6D614FD588F9D175120CCDF8, 0000220208
E59031CC6D614FD588F9D175120CCDF8)

Web
PROGRAMMERS_T(00002202082700F3AD3225453B8D7F8E8F6C4EC761E59031CC6D614FD588F9D175120CCDF8, 0000220208
E59031CC6D614FD588F9D175120CCDF8)


SQL> begin
  2  FOR v_rec IN (SELECT name FROM project) LOOP
  3    UPDATE  TABLE(SELECT programmers FROM project WHERE name = v_rec.name)
  4      SET   column_value = NULL
  5    WHERE column_value IS DANGLING;
  6  END LOOP;
  7  end;
  8  /

PL/SQL procedure successfully completed.

SQL> select name,programmers from project;

NAME
------------------------------
PROGRAMMERS
----------------------------------------------------------------------------------------------------
Web-Services
PROGRAMMERS_T(NULL, NULL)

Web
PROGRAMMERS_T(NULL, NULL)


SQL> rollback;

Rollback complete.

SQL> delete programmer;

2 rows deleted.

SQL> select name,programmers from project;

NAME
------------------------------
PROGRAMMERS
----------------------------------------------------------------------------------------------------
Web-Services
PROGRAMMERS_T(00002202082700F3AD3225453B8D7F8E8F6C4EC761E59031CC6D614FD588F9D175120CCDF8, 0000220208
E59031CC6D614FD588F9D175120CCDF8)

Web
PROGRAMMERS_T(00002202082700F3AD3225453B8D7F8E8F6C4EC761E59031CC6D614FD588F9D175120CCDF8, 0000220208
E59031CC6D614FD588F9D175120CCDF8)


SQL> UPDATE  project p1
  2    SET   programmers = CAST(
  3                             MULTISET(
  4                                      SELECT  CASE
  5                                                WHEN column_value IS DANGLING
  6                                                  THEN NULL
  7                                                ELSE column_value
  8                                              END
  9                                        FROM  project p2,
 10                                              TABLE(p2.programmers)
 11                                        WHERE p2.name = p1.name
 12                                     )
 13                             AS programmers_t
 14                            )
 15  /

2 rows updated.

SQL> select name,programmers from project;

NAME
------------------------------
PROGRAMMERS
----------------------------------------------------------------------------------------------------
Web-Services
PROGRAMMERS_T(NULL, NULL)

Web
PROGRAMMERS_T(NULL, NULL)


SQL> 
5 дек 05, 02:46    [2139900]     Ответить | Цитировать Сообщить модератору
 Re: Как лучше подчищать ссылки, которые никуда не ссылаются?  [new]
flexed
Member

Откуда:
Сообщений: 115
SY
SQL> select * from v$version;


SQL> 


Thanks. It works as you wrote. Unfortunately java can't read this structure with nulls. So, I make it so,

begin
    FOR v_rec IN (SELECT name FROM project) LOOP
       DELETE  TABLE(SELECT programmers FROM project WHERE name = v_rec.name)
      WHERE column_value IS DANGLING;
    END LOOP;
    end;
/

And this loop delete all programmers, that are dangling.

So, if nulls in collection, it would be like programmers_t(NULL,NULL) and problem with java. If I NULL manager_t(), where it was REF to manager_t (the whole type) it works then fine.

manager REF manager_t - I update to NULL,
programmer programmers_t() - I just delete.

Well, this operation could be inefficient, if we have a big batch of programmers, but I suppose there is no other way.
5 дек 05, 10:39    [2140390]     Ответить | Цитировать Сообщить модератору
 Re: Как лучше подчищать ссылки, которые никуда не ссылаются?  [new]
flexed
Member

Откуда:
Сообщений: 115
SY
You need a lot of RTFM to do. For manager column:


For programmers column:

[src oracle]ALTER TABLE project
  MODIFY programmers NOT NULL
/
ALTER TABLE proj_prog_nt
  ADD SCOPE FOR(column_value) IS programmer
/

and change type programmers_t to:

CREATE OR REPLACE TYPE programmers_t AS TABLE OF REF programmer_t NOT NULL;
/

SY.


SY, I have a question on constraints. I did as you said. But I can still delete products, and manager stay not updated and I get an error, trying to access the managers table.

CREATE OR REPLACE TYPE products_t AS TABLE OF REF product_t NOT NULL;
/

CREATE OR REPLACE TYPE manager_t AS OBJECT (
employee_data REF employee_t,
work_telephones telephones_t,
products products_t
);
/

CREATE TABLE product OF product_t;

CREATE TABLE manager OF manager_t(employee_data REFERENCES employee)
NESTED TABLE work_telephones STORE AS work_tel_man_nt,
NESTED TABLE products STORE AS prod_man_nt;

ALTER TABLE prod_man_nt ADD (SCOPE FOR (COLUMN_VALUE) IS product);	

ALTER TABLE manager MODIFY products NOT NULL;

I delete product fields quite easy without any select and so on.

DELETE FROM product WHERE name = 'Some' and prod_type = 'Some type' and version_number = '1.0';

Why constraints don't work here?

When can it be, or I am doing something wrong?
5 дек 05, 19:27    [2142844]     Ответить | Цитировать Сообщить модератору
 Re: Как лучше подчищать ссылки, которые никуда не ссылаются?  [new]
mcureenab
Member

Откуда: Murmansk
Сообщений: 5928
flexed


I delete product fields quite easy without any select and so on.

DELETE FROM product WHERE name = 'Some' and prod_type = 'Some type' and version_number = '1.0';

Why constraints don't work here?

When can it be, or I am doing something wrong?


Тут нет ошибки SCOPE REF действительно так работает. Хотя SCOPE REF относится к ограничениям целостности, это скорее даже не ограничение, а тип данных. Объектная ссылка с ограничением SCOPE занимает меньше места в базе данных.
Чтобы исключить висячие ссылки нужно использовать не SCOPE, а REFERENCES, точнее REFERENCES вместе со SCOPE.
5 дек 05, 20:26    [2142908]     Ответить | Цитировать Сообщить модератору
 Re: Как лучше подчищать ссылки, которые никуда не ссылаются?  [new]
mcureenab
Member

Откуда: Murmansk
Сообщений: 5928
Вот нарисовал примерчик.

create type abm_t2 is object(
  n number,
  m number
);
/

create table abm_t3 of abm_t2;

create table abm_t4 (
    l number,
    r ref abm_t2
    constraint abm_t4_r_abm_t3 references abm_t3 on delete set null
);


declare
  rf ref abm_t2;
begin
    insert into abm_t3 o values (abm_t2(1,2))
    returning ref(o) into rf;
    insert into abm_t4 values(3, rf);
end;
/
col r format a40
select * from abm_t3;
select * from abm_t4;

delete abm_t3;
select * from abm_t4;

drop table abm_t4;
drop table abm_t3;
drop type abm_t2;



...
PL/SQL procedure successfully completed.

SQL> col r format a40
SQL> select * from abm_t3;

N M
--------- ---------
1 2

SQL> select * from abm_t4;

L R
--------- ----------------------------------------
3 00002202080731527326A80057E0440003BA0336
450731527326A50057E0440003BA033645


SQL>
SQL>
SQL>
SQL> delete abm_t3;

1 row deleted.

SQL> select * from abm_t4;

L R
--------- ----------------------------------------
3

SQL>

Т.е. ограничение целостности references abm_t3 с опцией on delete set null очищает висячую ссылку автоматически без проблем.
При наличии ограничения references, scope применяется неявно.
5 дек 05, 20:42    [2142926]     Ответить | Цитировать Сообщить модератору
 Re: Как лучше подчищать ссылки, которые никуда не ссылаются?  [new]
flexed
Member

Откуда:
Сообщений: 115
mcureenab
[quot flexed]

Чтобы исключить висячие ссылки нужно использовать не SCOPE, а REFERENCES, точнее REFERENCES вместе со SCOPE.


А как можно использовать REFERENCES на коллекцию?

Если делаю так,
CREATE TABLE manager OF manager_t(employee_data REFERENCES employee,
 products REFERENCES products_t)
NESTED TABLE work_telephones STORE AS work_tel_man_nt,
NESTED TABLE products STORE AS prod_man_nt;

то получаю ошибку.


CREATE TABLE manager OF manager_t(employee_data REFERENCES employee, products REFERENCES products_t)
     *
ERROR at line 1:
ORA-02444: Cannot resolve referenced object in referential constraints

И ещё, если делаю ограничение на REF
CREATE TABLE manager OF manager_t(employee_data REFERENCES employee)
NESTED TABLE work_telephones STORE AS work_tel_man_nt,
NESTED TABLE products STORE AS prod_man_nt;

А затем так:

ALTER TABLE manager ADD (SCOPE FOR (employee_data) IS employee);	

То ошибка:

ALTER TABLE manager ADD (SCOPE FOR (employee_data) IS employee)
                         *
ERROR at line 1:
ORA-30727: duplicate referential constraint for a REF column

В чём проблема?
5 дек 05, 20:47    [2142934]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
Все форумы / Oracle Ответить