How to execute query when oracle starting up? - oracle

I have some question.
I want to execute some SQL query when oracle starting up(initialization).
for instance, Linux, Windows, and etc. OS are enable to run program, when computer start up.
anyway, my purpose is executing some query in oracle 11g r1, when oracle starting up.

You could use AFTER STARTUP Triggers.
create or replace trigger
tr_startup_actions
after startup on database
begin
procedure_runing_query(p_arg1);
end;
/
Run the query you need to inside the procedure or within the block if you need it. But, you should decide a way to store the result of the query somewhere. storing it in a table would be better.

here is an example:
CREATE OR REPLACE TRIGGER
manage_service
after startup on database
DECLARE
role VARCHAR(30);
BEGIN
SELECT DATABASE_ROLE INTO role FROM V$DATABASE;
IF role = 'PRIMARY' THEN
DBMS_SERVICE.START_SERVICE('sales_rw');
ELSE
DBMS_SERVICE.START_SERVICE('sales_ro');
END IF;
END;
is this what you need?

Related

Error 38824 : A CREATE OR REPLACE Command May not Change the EDITIONABLE Property of an Existing Object

we are implementing a unit test system of our database production object like package, procedure, trigger & co. To do so, we have a container which create a database from https://github.com/oracle/docker-images/tree/master/OracleDatabase .
Then we execute scripts which are creating schema, users, grant some privileges, create good tablespaces... Then we use Data Pump Oracle to expdp and impdp the schema. These steps are successful.
The problem appear when we try to exec test on our Procedures and Packages. They are not find in schema due to compilation error "ORA-38824 : A CREATE OR REPLACE Command May not Change the EDITIONABLE Property of an Existing Object".
But if we drop the procedure tested, then recreate it, the error does not appear anymore. Things is we do not want to manually drop & re create the procedure.
the only difference between our environment & the container database is that when we create a procedure/package from scratch, Editionable parameter in object detail are at 'N' in container when it is at 'Y' in our env.
It seems that Editionable parameter for objects has to be set at Database level.
But the question is where can it be set ?
We tried to 'ALTER USER X ENABLE EDITIONS;' without success since it is causing 'ORA-38813: editions not supported for schema X'.
Is Impdp & Expdp causing trouble ?
We tried using 'source_edition' & 'target_edition' for our expdp impdp process.
We are clearly missing something or doing something wrong but we are not able to find what.
I have searched on internet, but not too much people have been facing this issue..
Could you please provide us help?
Thanks in advance.
Vincent.
I checked the Oracle Support website (should have done this earlier) and this error is related to a bug in 12c. For example in one such document (Meta Link Document) it is said as follows. So please refer this issue to Oracle by raising an SR and most likely they will come back with a suggestion for an Oracle version upgrade:
Please apply the merge patch Bug 27314007 : MERGE REQUEST ON TOP OF 12.2.0.1.0 FOR BUGS 25557064 26645487
Using these steps for the upgrade:
Stop the current DBUA session.
Download and apply the patch to 12.2 Oracle home.
Restore the 12.1 database.
Re-run the upgrade from 12.1 to 12.2.
Thanks,
I went through this recently, and analyzing it we would not use the EDITIONABLE functionality, so I ran the command below, leaving the NONEDITIONABLE objects, because that way the objects are replaced. And in the DBA_OBJECTS table, the EDITIONABLE column is N, so when it is time to do the imp, there is no problem.
DECLARE
TYPE t_cursor IS REF CURSOR;
TYPE t_string_array IS TABLE OF VARCHAR2(1000) INDEX BY BINARY_INTEGER;
vcursor t_cursor;
varraystring t_string_array;
vstring VARCHAR2(500);
i BINARY_INTEGER;
BEGIN
OPEN vcursor FOR
select 'ALTER ' || do.object_type || ' ' || do.owner || '.' || do.object_name || ' NONEDITIONABLE'
from DBA_OBJECTS do
where do.editionable = 'Y'
and do.owner NOT IN('QS_CB','DIP','PERFSTAT','QS_ADM','PM','SH','HR','OE','ODM_MTR','WKPROXY','ANONYMOUS','OWNER','SYS','SYSTEM','SCOTT','SYSMAN','XDB','DBSNMP','EXFSYS','OLAPSYS','MDSYS','WMSYS','WKSYS','DMSYS','ODM','EXFSYS','CTXSYS','LBACSYS','ORDPLUGINS','SQLTXPLAIN','OUTLN','TSMSYS','XS$NULL','TOAD','STREAM','SPATIAL_CSW_ADMIN','SPATIAL_WFS_ADMIN','SI_INFORMTN_SCHEMA','QS','QS_CBADM','QS_CS','QS_ES','QS_OS','QS_WS','PA_AWR_USER','OWBSYS_AUDIT','OWBSYS','ORDSYS','ORDDATA','ORACLE_OCM','SPATIAL_CSW_ADMIN_USR','SPATIAL_WFS_ADMIN_USR','MGMT_VIEW','MDDATA','FLOWS_FILES','FLASHBACK','AWRUSER','APPQOSSYS','APEX_PUBLIC_USER','DVSYS')
and do.object_type IN ('FUNCTION','LIBRARY','PACKAGE BODY','PACKAGE','PROCEDURE','TRIGGER','TYPE','TYPE BODY','SYNONYM','VIEW');
LOOP
FETCH vcursor BULK COLLECT
INTO varraystring;
EXIT WHEN varraystring.count = 0;
FOR i IN varraystring.first .. varraystring.last LOOP
EXECUTE IMMEDIATE varraystring(i);
END LOOP;
EXIT WHEN vcursor%NOTFOUND;
END LOOP;
CLOSE vcursor;
END;

Oracle 'after create' trigger to grant privileges

I have an 'after create on database' trigger to provide select access on newly created tables within specific schemas to different Oracle roles.
If I execute a create table ... as select statement and then query the new table in the same block of code within TOAD or a different UI I encounter an error, but it works if I run the commands separately:
create table schema1.table1 as select * from schema2.table2 where rownum < 2;
select count(*) from schema1.table1;
If I execute them as one block of code I get:
ORA-01031: insufficient privileges
If I execute them individually, I don't get an error and am able to obtain the correct count.
Sample snippet of AFTER CREATE trigger
CREATE OR REPLACE TRIGGER TGR_DATABASE_AUDIT AFTER
CREATE OR DROP OR ALTER ON Database
DECLARE
vOS_User VARCHAR2(30);
vTerminal VARCHAR2(30);
vMachine VARCHAR2(30);
vSession_User VARCHAR2(30);
vSession_Id INTEGER;
l_jobno NUMBER;
BEGIN
SELECT sys_context('USERENV', 'SESSIONID'),
sys_context('USERENV', 'OS_USER'),
sys_context('USERENV', 'TERMINAL'),
sys_context('USERENV', 'HOST'),
sys_context('USERENV', 'SESSION_USER')
INTO vSession_Id,
vOS_User,
vTerminal,
vMachine,
vSession_User
FROM Dual;
insert into schema3.event_table VALUES (vSession_Id, SYSDATE,
vSession_User, vOS_User, vMachine, vTerminal, ora_sysevent,
ora_dict_obj_type,ora_dict_obj_owner,ora_dict_obj_name);
IF ora_sysevent = 'CREATE' THEN
IF (ora_dict_obj_owner = 'SCHEMA1') THEN
IF DICTIONARY_OBJ_TYPE = 'TABLE' THEN
dbms_job.submit(l_jobno,'sys.execute_app_ddl(''GRANT SELECT
ON '||ora_dict_obj_owner||'.'||ora_dict_obj_name||' TO
Role1,Role2'');');
END IF;
END IF;
END IF;
END;
Jobs are asynchronous. Your code is not.
Ignoring for the moment the fact that if you're dynamically granting privileges that something in the world is creating new tables live in production without going through a change control process (at which point a human reviewer would ensure that appropriate grants were included) which implies that you have a much bigger problem...
When you run the CREATE TABLE statement, the trigger fires and a job is scheduled to run. That job runs in a separate session and can't start until your CREATE TABLE statement issues its final implicit commit and returns control to the first session. Best case, that job runs a second or two after the CREATE TABLE statement completes. But it could be longer depending on how many background jobs are allowed to run simultaneously, what other jobs are running, how busy Oracle is, etc.
The simplest approach would be to add a dbms_lock.sleep call between the CREATE TABLE and the SELECT that waits a reasonable amount of time to give the background job time to run. That's trivial to code (and useful to validate that this is, in fact, the only problem you have) but it's not foolproof. Even if you put in a delay that's "long enough" for testing, you might encounter a longer delay in the future. The more complicated approach would be to query dba_jobs, look to see if there is a job there related to the table you just created, and sleep if there is in a loop.

Select All records from a table using SP in Oracle SQL Developer

I'm using SQL Oracle to build a stored procedure. I'm trying to build a stored procedure of the SQL-query below.And I want to return those data to a C# program.
select * from employee_master
I have tried following. Is this correct?
CREATE OR REPLACE PROCEDURE EMPLOYEE_SELECTALL (p_recordset OUTSYS_REFCURSOR)AS
BEGIN
OPEN p_recordset FOR
SELECT
*
FROM
EMPLOYEE_MASTER;
END EMPLOYEE_SELECTALL;
If you wish to build a stored procedure that return such resultset first of all you should check if you really need to do this. It's incidental and not recommended way for Oracle. But if you really need so, you should use REF CURSOR.
after executing your stored procedure in SQL Developer, it automatically brings back any output for you to view, including one or more ref cursors.
Example code and screenshots here

How to create and drop a table inside Oracle function?

I have the function in which I need to drop and create tables. In the example below I try to create the table but it fails
CREATE OR REPLACE FUNCTION DEVTEST
RETURN NUMBER
IS
COMMAND VARCHAR2(256);
ID VARCHAR2(128);
NAME VARCHAR2(128);
TMP_LIST VARCHAR2(128);
BEGIN
ID := '12345';
NAME := 'ABCdef';
TMP_LIST := 'tmpTest';
command := 'create table ' || TMP_LIST || ' ( USER_ID VARCHAR2(11), USER_NAME VARCHAR2(36))';
DBMS_OUTPUT.PUT_LINE('command = ' || command);
EXECUTE IMMEDIATE command;
return 0;
END;
I call the function:
select NSB_DEVTEST() from dual
And get the error:
ORA-14552: cannot perform a DDL, commit or rollback inside a query or DML ORA-06512: at "DEV1_SERVER.DEVTEST", line 15
How do I correct this to create/drop a table inside a function?
My server details:
Oracle Database 10g Enterprise Edition Release 10.2.0.5.0 - 64bi
PL/SQL Release 10.2.0.5.0 - Production
CORE 10.2.0.5.0 Production
TNS for Solaris: Version 10.2.0.5.0 - Production
NLSRTL Version 10.2.0.5.0 - Production
The problem is not with the function but with it being called from a SQL statement rather than from a pl/sql block.
A SELECT statement in SQL is equivalent to a READ operation that comes with read consistency. It cannot make any changes to the database. The database should always be the same before and after the "READ" operation completed, otherwise it would be a WRITE operation and the entire database consistency would go havoc.
Also, like the error says, DDL operations do a COMMIT behind the scenes before they start. Any read consistent operation should never do any COMMITS and write to the database without the user knowing.
You can instead call the function from pl/sql like this -
DECLARE
l_result NUBMER;
BEGIN
l_result := DEVTEST;
DBMS_OUTPUT.PUT_LINE(l_number);
END;
Still I would prefer writing a procedure for this, so others don't get confused by why this can't be called from SQL. The general rule that I follow for myself is that - Functions "get" things and Procedures "do" things (like DML).
The answer to your question is: don't. Production code, on the whole, shouldn't be creating tables on the fly. If you need a table to hold data temporarily, then create a Global Temporary Table (GTT) once and have your code refer to it.
The reason why you're getting that error (apart from it being self-evident from the error message) is because you're calling the function from within a SQL statement. You can't do that; you'd have to call it directly in PL/SQL.
I'm curious as to why you think this approach is a good, feasible approach, and also what you're going to be doing with the table once you've created it.
Your code is perfect no problem in the code . the problem is while you try to execute
you can only execute a pure function in select statement, which means a function without ddl & dml . ( if you use pragma autonomous_transaction while performing dml inside a function then you can use it in select statement ). When function has DDL command you can never ever execute it in select statement , but instead you can only execute it in PLSQL block like this
declare
a number;
begin
a:= devtest;
end;
/
and you can check your table
select * from tmptest;

Can GRANT be used inside an Oracle Store Procedure?

When trying to place a GRANT statement in an Oracle 11 stored procedure, it reports that GRANT is an unexpected symbol. Does GRANT need to be prefaced by something, or does Oracle simply disallow running GRANTS inside SPs?
It's a bad idea to use DDL (like GRANT) inside stored procedures.
You will have to use dynamic SQL (EXECUTE IMMEDIATE) to do this, but, honestly, I don't see why would you want to do this inside a stored proc.
Here's a PL/SQL stored procedure that grants object privileges (SELECT, UPDATE, etc.) on all tables owned by the current user to another user, e.g. - "appuser".
CREATE OR REPLACE PROCEDURE grant_privs
IS
CURSOR ut_cur IS SELECT table_name from user_tables;
ut_rec ut_cur%rowtype;
BEGIN
FOR ut_rec IN ut_cur
LOOP
EXECUTE IMMEDIATE 'GRANT ALL ON ' || ut_rec.table_name || ' TO appuser';
END LOOP;
END;
/
It was executed automatically after deploying database changes for a web application. The current user owns the database tables. After deploying any database changes, the stored procedure was executed to ensure that "appuser" could run SQL statements on all of the tables. The web application connected as "appuser", which had only limited system privileges, for security reasons.
This is both a solution to the problem and a solid use case for the solution.

Resources