30 Aralık 2011 Cuma

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

When you insert a row to table which have trigger to insert another table in remote db.
You have to care about insert statement in trigger.

for example

if you use this statement for insert to remote table


INSERT INTO appuser.holidays@otherdb SELECT * FROM holidays WHERE HOL_NAME = :New.HOL_NAME;


statement raises an error like below

ORA-04091: table appuser.holidays is mutating, trigger/function may not see it
ORA-02063: preceding line from PRODDB
ORA-02063: preceding 2 lines from OTHERDB
ORA-06512: at "APPUSER.HOLIDAYS_IUD", line 6
ORA-04088: error during execution of trigger 'APPUSER.HOLIDAYS_IUD'


to aviod tihs problem you can use table columns for inserting. like below


INSERT INTO appuser.holidays@otherdb values (:New.HOL_NAME,:New.HOL_START,:New.HOL_END,:New.HOL_TYPE);



--source of trigger


CREATE OR REPLACE TRIGGER APPUSER.HOLIDAYS_IUD
 AFTER
  INSERT OR DELETE OR UPDATE
 ON appuser.holidays
REFERENCING NEW AS NEW OLD AS OLD
 FOR EACH ROW
DECLARE
BEGIN
 IF DELETING then
     DELETE FROM appuser.holidays@otherdb WHERE HOL_NAME =:Old.HOL_NAME;
 ELSIF INSERTING then
     INSERT INTO appuser.holidays@otherdb values (:New.HOL_NAME,:New.HOL_START,:New.HOL_END,:New.HOL_TYPE);
 ELSIF UPDATING then
     DELETE FROM appuser.holidays@otherdb WHERE HOL_NAME = :Old.HOL_NAME;
     --raise error like below
     --INSERT INTO appuser.holidays@otherdb SELECT * FROM holidays WHERE HOL_NAME = :New.HOL_NAME;
     INSERT INTO appuser.holidays@otherdb values (:New.HOL_NAME,:New.HOL_START,:New.HOL_END,:New.HOL_TYPE);
 END IF;
END;
/

29 Aralık 2011 Perşembe

ORA-00054: kaynak meşgul ve NOWAIT ile elde etme belirlendi veya zaman aşımı süresi doldu


ALTER TABLE TABLO1 ADD ( adi VARCHAR2 (20));

line 1: ORA-00054: kaynak meşgul ve NOWAIT ile elde etme belirlendi veya zaman aşımı süresi doldu


Sorunu aşmanın farklı yolları var. Tabloyu kullanan sessionı bulup kill edebilirsiniz.

col object format a30
col username format a20
col sidserial format a12
set linesize 200

SELECT a.SID||','||s.serial# SIDserial, s.last_call_et, s.status,s.sql_hash_value, s.username, s.sql_hash_value, a.owner || '.' || a.OBJECT OBJECT, s.lockwait,s.osuser
  FROM gv$session s, gv$access a
 WHERE s.SID = a.SID
   and s.inst_id = a.inst_id
   AND a.owner != 'SYS'
   --and s.status ='ACTIVE'
   AND UPPER (SUBSTR (a.OBJECT, 1, 2)) != 'V$'
   AND a.OBJECT = upper(trim('&object_name'));


Çok yoğun kullanılan ama sürekli küçük transactionlar olan bir tablo ise 
belirli bir zaman bekleyip yeniden deneyen bir prosedür yazabilirsiniz.(0.1 sn gibi)

11g ile gelen bir parametre ile hata almadan önce bekleyebileceğimiz süreyi session bazında set edebiliyoruz.

alter session set DDL_LOCK_TIMEOUT=60;

böylece hata almadan önce 60sn beklemiş olacaksınız.


oracle reference linki : http://docs.oracle.com/cd/B28359_01/server.111/b28320/initparams068.htm




28 Aralık 2011 Çarşamba

Unixden windowsa çıktı gönderme


Bu işlemi yapabilmek için

1- Windowsda printer paylaşılmş durumda olmalı.
2- Windowsda print spooler servisi çalışıyor durumda olmalı. Firewall varsa tanımlarınızı yapmalısınız. spooler servisi varsayılan olarak 515 portunu dinliyor.

Unixden aşağıdaki şekilde çıktı gönderebiliriz.

/usr/ucb/lpr -P HOST_ADI:PRINTER_ADI -l PRINT_DOSYASI

örnek:
/usr/ucb/lpr -P pcramazan:printer33 -l abc.txt



27 Aralık 2011 Salı

Oracle ODBC driver manual install (11g)

like below you can install Oracle ODBC driver manually.

--Oracle ODBC driver manual install (11g)
1-

Copy ODBC directory to $ORACLE_HOME
Copy sqora32.dll, sqoras32.dll, sqresus.dll, sqresja.dll to $ORACLE_HOME\bin

2-

cd C:\oracle\11.1\bin
C:\oracle\11.1\bin>regsvr32 /s sqora32.dll
C:\oracle\11.1\bin>regsvr32 /s sqoras32.dll
C:\oracle\11.1\bin>regsvr32 /s sqresus.dll
C:\oracle\11.1\bin>regsvr32 /s sqresja.dll
C:\oracle\11.1\ODBC>regsvr32 /s deckan32.dll

3- regedit, go to HKEY_LOCAL_MACHINE/SOFTWARE/ODBC


go to Oracle in OraClient11g_home1

key Driver, value = C:\oracle\11.1\bin\sqora32.dll
key Setup, value = C:\oracle\11.1\bin\sqoras32.dll


you can run below entries with reg file.


[HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBCINST.INI\Oracle in OraClient11g_home1]
"APILevel"="1"
"CPTimeout"="60"
"ConnectFunctions"="YYY"
"Driver"="c:\\oracle\\11.1\\BIN\\SQORA32.DLL"
"DriverODBCVer"="03.51"
"FileUsage"="0"
"Setup"="c:\\oracle\\11.1\\BIN\\SQORAS32.DLL"
"SQLLevel"="1"

[HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBCINST.INI\ODBC Drivers]
"Oracle in OraClient11g_home1"="Installed"





26 Aralık 2011 Pazartesi

DBMS_JOB.next_date for other user

DBMS_JOB ile yetkisi olan her kullanıcı kendi şeması altında job tanımlayabilir. Başka bir şema altında job tanımlamak (legal olarak) mümkün değil. Paketin kullanımı ile ilgili buradan detaylı bilgiyi bulabilirsiniz. Başka kullanıcı altındaki joblara müdahele etmek gibi bir gereklilikte kullanabileceğimiz bir yöntem var. Joblarını değiştirmek istediğimiz kullanıcı altına prosedür oluşturup işlerimi yapabiliriz. Prosedürü farklı yöntemlerle oluşturmak mümkün.

Örneğin sadece bizim gönderdiğimiz bir herhangi komutu execute edecek şekilde prosedür yazmak bunlardan biri.Bu durumda sadece job için değil diğer başka limititasyonları da aşmış olabiliriz. (dmbs_job, database link gibi). Bu linkten bu amaçla yazmış olduğum prosedürü inceleyebilirsiniz.


Aşağıda job için yazlmış bir prosedür var. Bu prosedür ile diğer şema altındaki jobların sonraki çalışma zamanlarını, işin çalışma zaman aralığı kadar sonraya atamış olacağız.

yani  next_date = hesaplanan interval olacak.



create or replace PROCEDURE app_user.job_ilerlet (tarih date)
IS
cmd varchar2(500) := '';
BEGIN
   FOR c IN (SELECT job, last_date, interval
               FROM user_jobs
              WHERE TRUNC (last_date) = TRUNC (tarih))
   LOOP 
      cmd := 'begin dbms_job.next_date('||c.job||', '||c.interval||'); commit; end;';
      dbms_output.put_line(cmd);
      execute immediate cmd;
   END LOOP;
END;
/






Drop Lob Object


If you find lob segments in dictionary but any tables.

OBJECT_NAME                    OBJECT_TYPE
-------------------------      -----------
SYS_LOB0000117461C00044$$      LOB        
SYS_LOB0000117446C00044$$      LOB        
SYS_LOB0000117431C00044$$      LOB        
SYS_LOB0000117547C00044$$      LOB        
SYS_LOB0000117525C00044$$      LOB        
SYS_LOB0000117504C00044$$      LOB        
SYS_LOB0000117483C00044$$      LOB        

You have to purge your user recyclebin.

purge recyclebin;





23 Aralık 2011 Cuma

DBMS_DEBUG error


When debug a procedure if raise an error like below :


ORA-01031: insufficient privileges
ORA-06512: at "SYS.PBSDE", line 78
ORA-06512: at "SYS.DBMS_DEBUG", line 226
ORA-06512: at line 1


User does not have sufficient privileges for debugging PL/SQL
You must grant DEBUG CONNECT SESSION to your user.

--for example
GRANT DEBUG CONNECT SESSION to app_usr;



21 Aralık 2011 Çarşamba

Autonomous transaction ve transaction durumu

Autonomous transaction ve transaction durumu: Oracle' da bir transaction insert,update,delete komutlarıyla başlar ve bir DDL komutu, commit veya rollback ile biter. Commit veya rollback bir procedure/function/package içinden bile çağrılsa transaction devam ettiği için o transactionı sonlandıracaktır.

Bu durumda transactionın sonlanmadan başka bir tabloya yeni bir transaction başlatıp ana transactionının durumunu değiştirmeden sonlandırmamız gerekirse bunun için autonomous transaction kullanılır.

 --aşağıdaki örnek scriptler ile deneyebilirsiniz.


create table emp (id number, ad varchar2(20), soyad varchar2(20));

insert into emp values (1,'RAMAZAN','ÖZTÜRK');
insert into emp values (2,'AHMET','ÖZTÜRK');
insert into emp values (3,'DEDE','ÖZTÜRK');
insert into emp values (4,'BABA','ÖZTÜRK');

alter table emp add sal number;

create table emp_aud (id number,old_sal number,new_sal number,cdate date);

alter table emp_aud add empid number;

create sequence idver ;

create or replace trigger trg_emp 
before delete or update on emp 
for each row
declare 
pragma autonomous_transaction;
begin
  insert into emp_aud values (idver.nextval,:old.sal,:new.sal,sysdate,:old.id);
  commit;
end;

update emp set sal=400 where id=1;


create or replace procedure emp_tmp as
begin
  insert into emp values (idver.nextval,'KEVIN','COSTNER',100);
  rollback;
end;
/


insert into emp values (idver.nextval,'KEVIN'||idver.currval,'COSTNER',200);

insert into emp values (idver.nextval,'KEVIN'||idver.currval,'COSTNER',300);

exec emp_tmp();

insert into emp values (idver.nextval,'KEVIN'||idver.currval,'COSTNER',400);

rollback;



Buradan inceleyebilirsiniz.(Concepts)
http://docs.oracle.com/cd/B28359_01/server.111/b28318/transact.htm#i7733


Increase sequence value

--add 1000 to sequence current value

DECLARE
   i   NUMBER;
   a   NUMBER;
BEGIN
   FOR i IN 1 .. 1000
   LOOP
      SELECT appuser.sq_fisno.NEXTVAL
        INTO a
        FROM DUAL;
   END LOOP;
END;

6 Aralık 2011 Salı

Other user Procedure


Prosedürler sahibi olan kullanıcının hakları ile çalışır.
Bazı limitasyonlar gereği veya başka bir amaçla genel olarak aşağıdaki bir sp kullanılabilir.

CREATE OR REPLACE PROCEDURE app_user.vty_run_command (cmd varchar2)
IS
BEGIN
   EXECUTE IMMEDIATE cmd;
END;
/

Bu durumda bu spyi çağıran herhangi bir user app_user hakları ile istediği işi yaptırabilir.

Örnek olarak şöyle :

--Çalıştıracağımız Prosedür

CREATE OR REPLACE PROCEDURE app_user.vty_ramazan
IS
a number :=0 ;
BEGIN
   for c in (select job from user_jobs)
   loop
   a := c.job;
   dbms_output.put_line(a);     
   end loop;
END;
/

--Prosedürü çağırmak için
set serveroutput on
Begin
  app_user.vty_run_command('begin vty_ramazan; end;');
End;
/

--Sonuç
Normalde select * from user_jobs ile kullanıcı kendi joblarını görebilir.
Bu prosedüre ile o kullanıcı altında tanımlı jobları da görebiliriz.

Bu bize ne kazandırır: DBA veya select any table veya select_catalog_role hakkı olmayan biri de başka bir kullanıcı altındaki nesne tanımlarına erişebilir.