I am trying to define three database tables – USERNAME, USER_SESSIONS, and TOOLBOX_DIRS_REGISTERED. I can define the first two of these without any problems, but the last one is causing me a bit of grief. Ideally I would like to define it as is shown in the code block below, however I believe that sub-queries cannot be used within check constraints?
The code block immediately below shows how I would like to define the table TOOLBOX_DIRS_REGISTERED. The start of the code block also contains some comments which attempt to explain my thoughts about certain constraints which the table definition uses.
-- Constraint : USERNAME_FK
-- ========================
--
-- USERNAME must contain a username which has been added to the table USERNAME.
--
-- Constraint : USER_SESSION_ID_FK
-- ===============================
--
-- USER_SESSION_ID must contain a user session ID which has been added to the table
-- USER_SESSION.
--
-- Constraint : check_user_session_id
-- ==================================
--
-- In addition to the above constraint, USER_SESSION_ID must also belong to the
-- username which is contained within USERNAME.
create table
TOOLBOX_DIRS_REGISTERED
(
DIRNAME varchar2(100) not null,
USERNAME varchar2(32) not null,
USER_SESSION_ID varchar2(32) not null,
AUTO_REGISTER char not null,
constraint
TOOLBOX_DIRS_REGISTERED_PK
primary key (DIRNAME),
constraint
USERNAME_FK
foreign key (USERNAME)
references USERS(USERNAME),
constraint
USER_SESSION_ID_FK
foreign key (USER_SESSION_ID)
references USER_SESSIONS(USER_SESSION_ID),
constraint
check_user_session_id
check
(
USERNAME in
(
select USERNAME from USER_SESSIONS
where USER_SESSIONS(USER_SESSION_ID) = USER_SESSION_ID
)
)
);
Does anyone know of a way around this problem, i.e. the use of the sub-query in the definition of the check constraint ‘check_user_session_id’? I read on Stackoverflow that Materialized views can be used instead of sub-queries in this particular situation. The trouble is, if I use a Materialized view, then I would want to make sure it was up to date at the time the check constraint was being performed. So what I did was implement the Materialized view along with a Trigger which called dbms_mview.refresh on the Materialized view. This is all fine, except that Oracle complains that it cannot COMMIT in a Trigger. Urgh! The exact message it gives me is ;
ERROR at line 2:
ORA-04092: cannot COMMIT in a trigger
ORA-06512: at "SYS.DBMS_SNAPSHOT", line 2760
ORA-06512: at "SYS.DBMS_SNAPSHOT", line 2740
ORA-06512: at "SYSTEM.SIMULAB_MVIEW", line 19
ORA-06512: at "SYSTEM.TRIG_TOOLBOX_DIRS_REGISTERED", line 3
ORA-04088: error during execution of trigger 'SYSTEM.TRIG_TOOLBOX_DIRS_REGISTERED'
I’m assuming that Oracle is attempting to automatically perform a commit after it refreshes the Materialized view and that’s what it is complaining about?
My Trigger is defined as follows ;
create or replace trigger TRIG_TOOLBOX_DIRS_REGISTERED
before insert or update on
TOOLBOX_DIRS_REGISTERED
begin
-- Invoke the PL/SQL Package procedure simulab_mview.refresh_mview
simulab_mview.refresh_mview;
end;
while the PL/SQL Package simulab_mview is defined as follows ;
create or replace
package
simulab_mview
as
procedure
refresh_mview;
end;
/
create or replace package body
simulab_mview
as
procedure
refresh_mview
as
begin
-- I have a strong suspicion that dbms_mview.refresh might cause a commit to
-- be executed. This would make sense, as the RDBMS would need to execute a
-- commit so that other clients could see the result of the refresh.
dbms_mview.refresh('mat_view', 'C');
end;
end;
/
Does anyone have any thoughts on this? Is there an easier way to do what I want to do, should I not be using Materialized views, should I not be using Triggers?
Any help or even thoughts on this would be immensely appreciated. If anyone is indeed able to provide any help or thoughts on this matter, then I would like to thank them in advance for their assistance.
Have a nice day.
If I am understanding this correctly, I don’t think you want
toolbox_dirs_registeredto refer to both theusersand theuser_sessionstables. That isn’t normalized. Only refer to theuser_sessionstable and you already have a reference to theuserstable.The following snippet is untested and has a lot of cut and paste, but I think it gives the idea: