26 August 2006

On NULL Values

Simply, NULL values are meaningless expressions. You can not do any comparison on NULL values. Be careful when dealing NULL values. I demonstrate a simple example on Oracle to show how NULL values effect on queries program blocks.

NULL değerler hiçbirşey ifade etmeyen ifadelerdir. 1 ve 0 oalarak da karşılığı belirlenemezler. O nedenle yazılan kodlarda ve sorgularda bu duruma dikkat etmek gerekir. Oracle ile yaptığım örnekte bu durumu göstermeye çalıştım:

create table n(i number, n varchar2(5));
BEGIN
INSERT INTO n VALUES (1, NULL);
INSERT INTO n VALUES (2, '');
INSERT INTO n VALUES (3, 's');
END;

commit;

SELECT * FROM n

SELECT COUNT(*) FROM n WHERE n.n IS NULL
--2
SELECT COUNT(*) FROM n WHERE n.n = NULL
--0
SELECT COUNT(*) FROM n WHERE n.n = ''
--0


Another example is a program block:

DECLARE
a VARCHAR2(5) := NULL;
b VARCHAR2(5) := NULL;
BEGIN
IF a IS NULL
THEN
dbms_output.put_line('a is NULL');
END IF;

IF b IS NULL
THEN
dbms_output.put_line('b is NULL');
END IF;

IF a = b
THEN
dbms_output.put_line('a = b is TRUE');
ELSE
dbms_output.put_line('a = b is FALSE');
END IF;

IF a != b
THEN
dbms_output.put_line('a != b is TRUE');
ELSE
dbms_output.put_line('a != b is FALSE');
END IF;

END;


Output is

a is NULL
b is NULL
a = b is FALSE
a != b is FALSE



Another is:

SELECT COUNT(*) FROM co
--34474
SELECT COUNT(*) FROM co WHERE ma = 'X'
--29617
SELECT COUNT(*) FROM co WHERE ma <> 'X'
--0
SELECT COUNT(*) FROM co WHERE ma IS NULL
--4857





Be careful!

Gathering Database Metadata On Oracle and Microsoft SQL Server

Sometimes you need the metadata of your database such tables, databases or columns via SQL. The DBMSs support to give this information. I described how to getmetadata of your databases via SQL:

Kimi zaman veritabanının metadatasına ihtiyaç duyabilrsiniz. Bu işlemi Oracle ve MSSQLServer ile nasıl yapılacağını aşağıdaki SQL cümleleri ile belirtmeye çalıştım:

On Microsoft SQL Server:
--List Databases
exec sp_databases

USE Pubs
--List Tables
SELECT *
FROM INFORMATION_SCHEMA.Tables
WHERE TABLE_NAME = 'authors'


--List Columns
SELECT *
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'authors'


On Oracle
--List Tables
SELECT *
FROM   ALL_TABLES a_t
WHERE  a_t.owner = 'HR'

--List Columns
SELECT *
FROM   ALL_TAB_COLUMNS atc
WHERE  atc.owner = 'HR' AND
           atc.TABLE_NAME = 'JOBS'
ORDER  BY atc.TABLE_NAME, atc.COLUMN_ID



Oracle gives database metadata more detailly. There is also a supplied package called DBMS_METADATA to give full functionality to deal with metada.

24 August 2006

In One Minute Three Entry On Forums.Oracle.Com

Thread: Running the same procedure by two different users  :
https://forums.oracle.com/forums/thread.jspa?threadID=416333

23 August 2006

Sample Deadlock Scenario On Oracle

create table a( x number )
INSERT INTO  a(x) VALUES (10)

create table b( x number )
INSERT INTO b (x) VALUES (100)

commit


--Session1
UPDATE a SET x = 5
--exclusive lock on table a

--Session2
UPDATE b SET x = 1000
--exclusive lock on table b

UPDATE a SET x = 50
--waits Session1 to commit or rollback

--Session1
UPDATE b SET x = 500
--waits Session2 to commit or rollback
--DEADLOCK!!!!

16 August 2006

Oracle Export Import Utilities

Oracle has powerful utilities such as export and import for transferring data between different hardware/software platfroms. In $ORACLE_HOME/BIN directory exp and imp utilities are used for this fashion.
Oracle içinde verilerin başka platformlara taşınması için export ve import kullanılmaktadır. Bu sayede veriler gerek yazılım gerek donanım açısından farklı sistemler arasında taşınabilmektedir. ORACLE_HOME dizini içindeki BIN dizinde exp ve imp adlı programcıklar bu işlemler için kullanılmaktadır.


Transfer operation has done via files which called dump. Dump files are created with exp and can be loaded via emp utilities. The important thing is that transferring of dump files must be done via binary mode ftp. Otherwise dump file can be corrupted. For ASCII files you are able to use SQL*Loader utility.
Taşınma işlemi binary formatında dump adı verilen dosyalar ile yapılmaktadır. Bu dosyalar exp ile oluşturulup imp ile istenen yere yüklenebilecek şekildedir. Oluşturulan dump dosyası ftp aracılığı ile taşınıyor ise, bu taşımayı binary ftp modu ile yapmak gerekmektedir. Aksi takdirde dosyanın bozulmasına neden olunabilinir. Buna dikkat edilmelidir. ASCII formatında taşıma için SQL*Loader kullanılmaktadır.


With export the object and all of its dependent objects are taken. You can backup your database via export/import whereas it is not recommended. For backup issues utilities such as RMAN might be used.
Export ile alacağınız nesne ile birlikte ona bağlı bütün neseneler de alınır. Java kaynak dosyalarını export ile almak mümkün değildir. Full bir export ile veritabanının bir nevi backup alınmış olsa da bu tavsiye edilen bir yol değildir. Büyük veritabanları için RMAN gibi özelleşmiş araçlar kullanılmalıdır.


You can detect any of corruption data with export.
Veritabanı içindeki verilerin okunamaması(data corruption) gibi bir durumun tespit edilebilmesi için de export kullanılabilir.


Transferring data with SCN or time with setting FLASHBACK_SCN, FLASHBACK_TIME parameters.
Export ile belirli bir SCN’e veya zamana göre de taşıma yapılabilmektedir. Bunun için gerekli parametrelerin uygun bir şekilde çağırılması gerekir.(FLASHBACK_SCN, FLASHBACK_TIME)


Not only full table, data based on condition can be exported.
Sadece belirli bir tablonun değil, tablo içinde belirli kritere bağlı kayıtların da gelmesi sağlanabilmektedir.(QUERY)

You can increase performance of export/import via defining COMMIT and ANALYZE parameters.
Export edilirken commit edilip edilmemesini veya ilgili nesnelerin analiz edilip edilmemesi belirlenebilmektedir.(COMMIT, ANALYZE) Bu kimi zaman performans arttrıcı olarak kullanılabilmektedir.


I described how to export a table from Microsoft system to Unix system below:
Aşağıda Microsoft tabanlı bir sistemden bulunan bir tablonun belirli kayıtlarının export edilip Unix tabanlı bir sisteme nasıl import edildiği belirtilmiştir.


On Windows side a table is created
Windows tarafında bir tablo oluşturulur:


create table hr.sample_emp as select * from hr.employees


Parameter file(exp_params.txt) is cretaed
Export ile kullanılacak parametre dosyası(exp_params.txt) hazırlanır.

FILE=dept50_emp.dmp
LOG=dept50_emp_exp.log
QUERY='where department_id = 50'
TABLES=hr.sample_emp
ROWS=y
COMPRESS=y

With this file
Bu dosya ile

select * from hr.sample_emp 'where department_id = 50

query result taken from hr schema and exported to dept50_emp.dmp file.
sorgusu ile gelecek kayıtları ve hr.sample_emp tablo yapısı ile birlikte dept50_emp.dmp dosyasına export edileceği belirtilmektedir.

With command prompt needed calls are done
Command prompt açılır ve gerekli çağırımlar yapılarak işlemin yapılması sağlanır:

E:\oracle\product\10.2.0\db_2\BIN>exp 'sys/orcl@ORCL as SYSDBA' PARFILE=exp_params.txt

Export: Release 10.2.0.1.0 - Production on Wed Aug 16 14:21:38 2006

Copyright (c) 1982, 2005, Oracle. All rights reserved.


Connected to: Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
With the Partitioning, OLAP and Data Mining options
Export done in WE8MSWIN1252 character set and AL16UTF16 NCHAR character set

About to export specified tables via Conventional Path ...
Current user changed to HR
. . exporting table SAMPLE_EMP 45 rows exported
Export terminated successfully without warnings.

E:\oracle\product\10.2.0\db_2\BIN>


exp 'sys/orcl@ORCL as SYSDBA' PARFILE=exp_params.txt

line does export operation
satırı export işlemini yapmaktadır.


dept50_emp_exp.log and dept50_emp.dmp files are created via this command.
Bu komut ile dept50_emp_exp.log ve dept50_emp.dmp adlı dosyalar oluşmaktadır.


For import, dept50_emp.dmp file is transferred via binary mode ftp.
Import için dept50_emp.dmp dosyası Unix ortamına binary modda ftp ile atılır.


Parameter file(imp_params.txt) is created for import.
İmport işlemi için kullanılacak parametre dosyası(imp_params.txt) hazırlanır.


FILE=dept50_emp.dmp
SHOW=n
IGNORE=n
GRANTS=y
FROMUSER=hr
TOUSER=sys
TABLES=sample_emp
ANALYZE=n
LOG=dept50_emp_imp.log

Via this file, sample_emp table from hr schema imported to sys schema.
Bu dosya ile hr şemasından alınan sample_emp adlı tablonun sys şeması altına alınacağı belirtilmiştir.

On Unix environment needed sheel calls are done
Unix ortamından açılan bir shell ile gerekli komutllar çağırılır:

oracle@zerg_shp01> imp \'sys/general@general as sysdba\' PARFILE=imp_params.txt

Import: Release 10.1.0.2.0 - Production on Wed Aug 16 14:16:43 2006

Copyright (c) 1982, 2004, Oracle. All rights reserved.


Connected to: Oracle Database 10g Enterprise Edition Release 10.1.0.2.0 - Production
With the Partitioning, OLAP and Data Mining options

Export file created by EXPORT:V10.02.01 via conventional path
import done in WE8ISO8859P9 character set and AL16UTF16 NCHAR character set
import server uses WE8ISO8859P1 character set (possible charset conversion)
export client uses WE8MSWIN1252 character set (possible charset conversion)
IMP-00008: unrecognized statement in the export file:
. . importing table "SAMPLE_EMP" 45 rows imported
Import terminated successfully with warnings.
oracle@zerg_shp01>


imp \'sys/sys@general as sysdba\' PARFILE=imp_params.txt


import has been done via this command
komutu ile import işlemi yapılmıştır.


With a query you can check the process.
Veritabanından bir sorgu ile işlemin doğru yapılıp yapılmadığı kontrol edilebilir:


select * from sys.sample_emp





For more information please visit
http://download-uk.oracle.com/docs/cd/B19306_01/server.102/b14215/exp_imp.htm 

11 August 2006

RMI Call via PL/SQL

Oracle has a JVM which called OracleJVM. You can load java classes or java source directly on Oracle. I need an RMI call within Oracle. So I implement it. I describe how to call RMI within PL/SQL below




The interface that will be used from RmiServer and RmiClient is written. The function which will be invoked must be declared in the intreface.
(Server ve client in ortak kullnacağı interface yazılır. Bu intreface içinde RMI ile invoke edilecek fonksiyon belirtilir)

package rmi;

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface IServer extends Remote {

    public String getTipOfTheDay() throws RemoteException;
}


A class is writen for parameters.
(Parametreler için de bir class yazılır)

package rmi;

public class Parameter {

    public static int portNumber       = 2005;
    public static String objectName    = "//127.0.0.1:2005/RmiServer”;
    public static String host      = "//127.0.0.1:2005/RmiServer";
   
    public Parameter() {
    }
   
}


Java files for RmiServer is writen:
(Server için java dosyaları yazılır)

package rmi;

import java.rmi.Naming;
import java.rmi.RMISecurityManager;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.server.UnicastRemoteObject;


public class RmiServer extends UnicastRemoteObject implements IServer {

    private Parameter configurationParameters;
   
    public RmiServer() throws RemoteException {
        alert("Server Created...");
        configurationParameters  = new Parameter();
    }

    public static void main(String[] args) {       
        try {       
            RmiServer rmiServer = new RmiServer();
            rmiServer.changeState("start");
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public void changeState( String state ) {
        if( state == "start" ){
            start();
        }else if( state == "stop" ){
            stop();
        }
    }
   
    private static void alert( String message ){
        System.out.println( message );
    }
   
    private void start( ) {
        System.setSecurityManager(new RMISecurityManager());
        try {
            LocateRegistry.createRegistry(Parameter.portNumber);
           
            Naming.rebind(Parameter.objectName, this );
            alert( "Server is ready to handle request.......");
        } catch (Exception ex) {
            alert( "Error occured...........");
            ex.printStackTrace();
        }
    }

    private void stop() {
        try {
            Naming.unbind(Parameter.objectName);
            alert( "Server CANNOT handle requests anymore.......");
        } catch (Exception e) {
            alert( "Error occured...........");
            e.printStackTrace();
        }
    }

    public String getTipOfTheDay() throws RemoteException {
        alert("getTipOfTheDay Method Invoked....");
        String tip = "Imagination is more important than knowledge. Knowledge is limited; imagination encircles the world.";
       
        return tip;
    }
}

Also for RmiClient java source files are created within Oracle.
(Client için java kaynak dosyaları Oracle içine yazılır)


create or replace and compile java source named rmi as

package rmi;

import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.Naming;

public class Parameter {

    public static int portNumber       = 2005;
    public static String objectName    = "//127.0.0.1:2005/RmiServer”;
    public static String host      = "//127.0.0.1:2005/RmiServer";
   
    public Parameter() {
    }
   
}


    private static IServer getServer() throws Exception {
        Parameter configurationParameters = new Parameter();
        IServer server = (IServer) Naming.lookup( configurationParameters.objectName);

        return server;
    }

}

public class RmiClient {
   
    public RmiClient(){
    }
   
    public static String getTipOfTheDay(){
        String result = "";
        try {
            IServer server = getServer();
            result = server.getTipOfTheDay();   
        } catch (Exception ex) {
            result = ex.getStackTrace().toString();
        }
        return result;
       
    }

/

Compilation is done
(Compile işlemi yapılır)


C:\projects\RmiSample\classes\rmi>del *.*

C:\projects\RmiSample\src\rmi>javac -classpath classes *
C:\projects\RmiSample\src\rmi>move *.class ../../classes/rmi


rmic compilation is done. Stub file(RmiServer_Stub.class) is created( With JDK 1.5 Skel file is nor created with rmic)
(rmic ile derleme işlemi yapılır. Stub dosyası oluşturulur( JDK 1.5 ile Skel oluşmamaktadır))

C:\projects\RmiSample\classes>rmic -classpath . rmi.RmiServer

Policy.file is created:
(Policy.file oluşturulur)

grant {
    //All Permissions Given!
    permission java.security.AllPermission;
  };


For RmiServer, runRmiServer.bat file is cretaed
(Server’in çalıştıracak runRmiServer.bat dosyası oluşturulur)

set CLASSPATH=.;classes
java -Djava.security.manager -Djava.security.policy=policy.file  rmi.RmiServer

If you want to start RmiServer on unix environment, runRmiServer.sh  is created.
(RmiServer unix ortamında çalıştırılacak ise runRmiServer.sh oluşturulur)

#!/bin/ksh

CLASSPATH=classes
export CLASSPATH
java -classpath $CLASSPATH -Djava.security.manager -Djava.security.policy=policy.file  rmi.RmiServer

policy.file and runRmiServer.(bat/sh) files are put the same directory.
(policy.file ve runRmiServer.bat dosyası aynı yere konur)

C:\projects\RmiSample>dir
 Volume in drive C is Cronus
 Volume Serial Number is 8CC9-D0FD

 Directory of C:\projects\RmiSample

08.08.2006  15:28   
          .
08.08.2006  15:28   
          ..
04.08.2006  16:05             3.913 build.xml
08.08.2006  15:34   
          classes
08.08.2006  13:52                15 params.txt
03.08.2006  15:08                92 policy.file
03.08.2006  12:01               549 RmiSample.iml
03.08.2006  12:08            10.540 RmiSample.ipr
03.08.2006  12:38            28.139 RmiSample.iws
03.08.2006  16:30             4.611 RmiSample.jpr
03.08.2006  13:54               105 runRmiServer.bat
04.08.2006  16:05               151 runRmiServer.sh
08.08.2006  14:11   
          src
               9 File(s)         48.115 bytes
               4 Dir(s)   2.516.996.096 bytes free


runRmiServer.(bat/sh) is executed.
(Bir command penceresinden runRmiServer.bat çalıştırılır)

C:\projects\RmiSample>runRmiServer.bat

C:\projects\RmiSample>set CLASSPATH=.;classes

C:\projects\RmiSample>java -Djava.security.manager -Djava.security.policy=policy.file  rmi.RmiServer
Server Created...
Server is ready to handle request.......

RmiServer_Stub.class is loaded OracleJVM via loadjava utility.
(RmiServer_Stub.class, loadjava ile OracleJVM içine yüklenir)

E:\oracle\product\10.2.0\db_2\BIN>loadjava -resolve C:\projects\RmiSample\classes\rmi\RmiServer_Stub.class

PL/SQL wrapper function is created
(PL/SQL çağırıcı fonksiyon yazılır)

CREATE OR REPLACE FUNCTION rmi_call_plsql
   RETURN VARCHAR2 IS
   LANGUAGE JAVA
   NAME 'rmi.RmiClient.getTipOfTheDay() return java.lang.String';
/

rmi_call_plsql function is called via PL/SQL
(rmi_call_plsql fonksiyonu PL/SQL içinden çağırılır)

DECLARE
  res VARCHAR2(1000);
BEGIN
  dbms_output.put_line('Result is ' || rmi_call_plsql);
END;

Output checked
(Çıktı kontrol edilir)

Result is Imagination is more important than knowledge. Knowledge is limited; imagination encircles the world.


Be sure RmiServer invoked
(Server açık olduğu command penceresine bakılır)

C:\projects\RmiSample>java -Djava.security.manager -Djava.security.policy=policy
.file  rmi.RmiServer
Server Created...
Server is ready to handle request.......
getTipOfTheDay Method Invoked....