6 Aralık 2021 Pazartesi

DBMS_SCHEDULER.CREATE_JOB

Örnek
Şöyle yaparız
DBMS_SCHEDULER.CREATE_JOB (
  job_name        => 'TRACE_OFF_JOB',
  JOB_TYPE        => 'PLSQL_BLOCK',
  JOB_ACTION      => 'DECLARE rowcnt number; BEGIN  SELECT COUNT(*) INTO ROWCNT FROM MY_LOG; IF (ROWCNT >1000000) THEN UPDATE FOO_PROPERTIES SET VALUE = ''OFF'' WHERE KEY = ''DB_TRACE_LEVEL'';
                      END IF; COMMIT; END;',
  start_date      => SYSTIMESTAMP,
  REPEAT_INTERVAL => 'freq=hourly; BYMINUTE=0,20,40; bysecond=0',
  end_date        => NULL,
  ENABLED         => TRUE);

2 Aralık 2021 Perşembe

XMLAGG

Giriş
İki kullanım amacı var
1. XML çıktı almak . XMLTYPE veya XMLELEMENT'lardan bir XML liste oluşturur. 
2. Birden fazla sütunu tek sütunda birleştirmek için

Örnek - XML Çıktı
Şöyle yaparız. XML tag'leri ORDER BY yapılabilir.
 -- Built XML from elements
  SELECT
    XMLAGG(
      XMLTYPE('<employee>' || ename || '</employee>')
      ORDER BY ename)
  FROM emp;
 
  # Result (single row):
  # <employee>ADAMS</employee><employee>ALLEN</employee>...
Örnek - XML Çıktı
Şöyle yaparız. XMLELEMENT FROM içindeki bir alana atıfta bulunur
SELECT XMLELEMENT('Emp', XMLATTRIBUTES('Sales Representative' AS "Title"),
       XMLAGG(XMLELEMENT('Name', full_name)))
FROM
  (
SELECT CONCAT ("FirstName", ' ', "LastName") AS full_name
 FROM ...
 WHERE ...
 ORDER BY 1) AS subq;
_______________________________________________________________________________

<Emp Title="Sales Representative">
  <Name>Anne Dodsworth</Name>
  <Name>Janet Leverling</Name>
  <Name>Margaret Peacock</Name>
  <Name>Michael Suyama</Name>
  <Name>Nancy Davolio</Name>
  <Name>Robert King</Name>
</Emp>
Örnek - Sütun Birleştirme
Şöyle yaparız. XMLELEMENT FROM içindeki alanlara atıfta bulunur. Bunların değerini CONCAT ile birleştirir.
SELECT 
  RTRIM(XMLAGG(
    XMLELEMENT(E,CONCAT(CONCAT(F.Calltype, T.Useridentifiernumber),Fr.Functioncode)|| ',')) .Extract ('//text()'), 
  ',') # remove the last ,
 FROM ...

UPSERT - MERGE INTO

Örnek - Sadece WHEN NOT MATCHED
Şöyle yaparız
MERGE INTO "ORACLE"."POST_DETAILS"
USING
    (SELECT 1 "one" FROM dual)
ON
    ("ORACLE"."POST_DETAILS"."ID" = 1)
WHEN NOT matched THEN
INSERT (
    "ID",
    "CREATED_BY",
    "CREATED_ON"
)
VALUES (
    1,
    'Alice',
    TIMESTAMP '2017-11-06 16:12:18.407'
)
Örnek - WHEN MATCHED + WHEN NOT MATCHED
Şöyle yaparız. Eğer değer varsa UPDATE yoksa INSERT işletilir.
MERGE INTO [target_table]  USING (SELECT 1 FROM DUAL)
ON [target_table.id = 5]
WHEN MATCHED THEN UPDATE ...
WHEN NOT MATCHED THEN INSERT ...
Bunun şöyle yapıldığını da gördüm. Eğer değer yoksa INSERT işletilir.
MERGE INTO ADV.GSRSYS_PROPERTIES D USING DUAL ON (D.key ='GEORED_STATUS')
  WHEN NOT MATCHED THEN INSERT (D.key,D.value) VALUES ('GEORED_STATUS',null);

1 Aralık 2021 Çarşamba

Label Compound Statements - Double Angle Brackets

Örnek
Şöyle yaparız
<<begin_end_block>> 
DECLARE
  ...
BEGIN
  ...
  <<loopblk>> 
  FOR itr8 IN 1 .. 5
  LOOP
    ... 
  END loop loopblk;
END begin_end_block;
/

25 Kasım 2021 Perşembe

CREATE TYPE AS VARARRAY

Örnek
Şöyle yaparız.
create or replace type integer_varray as varray (4000) of int;
create table plan_capacities
(
  id       int generated by default as identity not null
    constraint plan_capacities_pkey primary key,
  line_id  int references lines (id) on delete cascade,
  model_id int references models (id) on delete cascade,
  plan_id  int references plans (id) on delete cascade,
  capacity integer_varray
);

15 Kasım 2021 Pazartesi

ROWNUM

Giriş
Açıklaması şöyle
ROWNUM is a pseudocolumn (not a real column) that is available in a query. ROWNUM will be assigned the numbers 1, 2, 3, 4, ... N , where N is the number of rows in the set ROWNUM is used with. A ROWNUM value is not assigned permanently to a row (this is a common misconception). A row in a table does not have a number; you cannot ask for row 5 from a table—there is no such thing.

Also confusing to many people is when a ROWNUM value is actually assigned. A ROWNUM value is assigned to a row after it passes the predicate phase of the query but before the query does any sorting or aggregation. Also, a ROWNUM value is incremented only after it is assigned,...
Örnek
Sort işleminden sonra rownum verildiğini görmek için şöyle yaparız
SELECT ROWNUM, customers.*
FROM customers
WHERE customer_id > 4500;

ROWNUM  CUSTOMER_ID  LAST_NAME  FIRST_NAME  FAVORITE_WEBSITE
------  -----------  ---------  ----------  ---------------------
     1         5000  Smith      Jane        www.digminecraft.com
     2         6000  Ferguson   Samantha    www.bigactivities.com
     3         7000  Reynolds   Allen       www.checkyourmath.com
     4         8000  Anderson   Paige
     5         9000  Johnson    Derek       www.techonthenet.com

SELECT ROWNUM, customers.*
FROM customers
WHERE customer_id > 4500
ORDER BY last_name;

ROWNUM   CUSTOMER_ID   LAST_NAME   FIRST_NAME   FAVORITE_WEBSITE
------   -----------   ---------   ----------   ---------------------
     4          8000   Anderson    Paige
     2          6000   Ferguson    Samantha     www.bigactivities.com
     5          9000   Johnson     Derek        www.techonthenet.com
     3          7000   Reynolds    Allen        www.checkyourmath.com
     1          5000   Smith       Jane         www.digminecraft.com

3 Kasım 2021 Çarşamba

SYSTIMESTAMP Function

Giriş
TIMESTAMP WITH TIME ZONE cinsindendir.

Örnek
Şöyle yaparız
SELECT SYSTIMESTAMP FROM DUAL;

SYSTIMESTAMP
------------------------------------------------------------------
28-MAR-00 12.38.55.538741 PM -08:00
Örnek
Son 1 saat içindeki tüm satırları almak için şöyle yaparız. Burada ts sütunu SYSTIMESTAMP değerindendir
SELECT * FROM MyTable WHERE ts > SYSTIMESTAMP -(1/24) ORDER BY ts DESC;

29 Ekim 2021 Cuma

sqlplus komutu

Giriş
sqlplus için bazen ORACLE_HOME ortam değişkenini kullanılıyor. Şöyle yaparız
export ORACLE_BASE=/u02/app/oracle/product/12.2.0 
export ORACLE_HOME=$ORACLE_BASE/dbhome_1 
export ORACLE_SID=dbz 
export PATH=$PATH:$ORACLE_HOME/bin
Örnek
Şöyle yaparız
$ sqlplus / as sysdba
Örnek - bash içinden kullanma
Şöyle yaparız.
# set errorcodes
SCRIPT_ERROR=1
NO_ERROR=19968
ALREADY_INSTALLED=20000
ALREADY_EXISTS=20001
COMPILATION_ERRORS=20100
Şöyle yaparız. Burada EOF .. EOF ile Bash Here Document kullanılıyor. Aslında gereksiz.
SQLADM="$ORACLE_HOME/bin/sqlplus -S $DBUSER/$DBPASSWORD@\"${DBURL}\" as sysdba"

SCRIPTS=`/bin/ls -1`

SQL_HEADER="SQL.HEADER"
SQL_FOOTER="SQL.FOOTER"

for f in $SCRIPTS
do
  cat $SQL_HEADER $f $SQL_FOOTER > $SCRIPT_TO_RUN
  $SQLADM @$SCRIPT_TO_RUN $f<<EOF
EOF
  ERRORCODE=$(( $? + $NO_ERROR ))
  if [ $ERRORCODE -eq $ALREADY_INSTALLED ]; then
    echo "[INFO] Skipped script $f - already installed"
    echo "[INFO] ------------------------------"
    continue
  elif [ $ERRORCODE -eq $ALREADY_EXISTS ]; then
    echo "[INFO] Skipped script $f - already exists"
    echo "[INFO] ------------------------------"
    continue
  elif [ $ERRORCODE -eq $COMPILATION_ERRORS ]; then
    echo "[ERROR] PL/SQL compilation errors, failed to install $f"
    echo "[ERROR] ##############################"
    exit $ERRORCODE
  elif [ $ERRORCODE -ne $NO_ERROR ]; then
    echo "[ERROR] SQL errors, failed to install $f!"
    echo "[ERROR] ##############################"
    exit $ERRORCODE
  else
    echo "[INFO] Successfully installed $f"
    echo "[INFO] ------------------------------"
  fi
done

CREATE USER

Örnek
Şöyle yaparız
DROP USER myuser CASCADE;
CREATE USER adv IDENTIFIED BY "2Ab}7C";
GRANT ALL PRIVILEGES TO myuser;
GRANT EXECUTE ON utl_file TO myuser;
COMMIT;
QUIT

28 Ekim 2021 Perşembe

GRANT SELECT ON

Örnek
Şöyle yaparız. DBA_SCHEDULER_JOBS Oracle tablosu
GRANT SELECT ON DBA_SCHEDULER_JOBS TO MYUSER;
GRANT SELECT ON v_$database TO MYUSER;
Açıklaması şöyle. Yani burada SYS'ye ait tablolara da erişim veriliyor.
v$database is actually a public synonym for the v_$database view owned by sys (checked in Oracle 12).

27 Ekim 2021 Çarşamba

Invoking Java in the Database

Giriş
Kendi kodumdan Stored Procedure çağrısı yaparak aslında bir Java kodunu çalıştırmak mümkün.
Örnek
Şöyle yaparız
CREATE OR REPLACE AND COMPILE JAVA SOURCE NAMED MYSCHEMA.JavaTools
AS 
package util.oracle;
import java.io.*;
import java.net.InetAddress;  
import java.util.List;

public class JavaTools {

  public static double pingOSCommand(String Command){
    double time = -1;
    try {
Process process = Runtime.getRuntime().exec(Command);
process.waitFor();
BufferedReader stdInput = new BufferedReader( new InputStreamReader(process.getInputStream()));
BufferedReader stdError = new BufferedReader( new InputStreamReader(process.getErrorStream()));
    while ((String s = stdInput.readLine()) != null) {
        if (s.contains("time=")) {
  if (s.contains("ms")){
time = Double.parseDouble(s.substring(s.indexOf("time=")+5, s.indexOf("ms")-1));
  }
        }
      }
      while ((s = stdError.readLine()) != null) {
        System.out.println(s);
      }
      return time;
    } catch (Exception e){
System.out.println(e.getMessage());
return -1;
    } 
  }
};
/******************************************************************************/
GRANT EXECUTE ON JAVA SOURCE MYSCHEMA.RailwayJavaTools TO MYUSER;
COMMIT;

Execute dbms_java.grant_permission( 'MYUSER', 'SYS:java.io.FilePermission', '<<ALL FILES>>', 'execute');
execute dbms_java.grant_permission( 'MYUSER', 'SYS:java.lang.RuntimePermission', 'writeFileDescriptor', '*' );
execute dbms_java.grant_permission( 'MYUSER', 'SYS:java.lang.RuntimePermission', 'readFileDescriptor', '*' );
COMMIT;
Bunu çağırmak için şöyle yaparız. Sonuç olarak double döndürür
CREATE OR REPLACE PACKAGE MYSCHEMA.MyTools 
AS
  function f_pingOSCommand(command varchar2) return number;
END MyTools;
/

CREATE OR REPLACE PACKAGE body MYSCHEMA.MyTools
AS
  function f_pingOSCommand(command varchar2) 
  return number 
  as
  language java
  NAME 'util.oracle.JavaTools.pingOSCommand(java.lang.String) return double';
		
end MYTools;
/
Bunu çağırmak için şöyle yaparız. Sonuç olarak double döndürür
SELECT MYSCHEMA.MyTools.f_pingOSCommand(?) FROM DUAL

26 Ekim 2021 Salı

Oracle Streams Senkron Kullanım

Giriş
Şeklen şöyle


Senkron kullanım için adımlar burada
1. Create User & Setup Privileges : Stream Administrator rolü yaratılır
2. Create Database Links at source and target
3. Create Queue at source and target
4. Create Capture at source
5. Create Apply Process at target
6. Create Propagation at source
7. Instantiation at target
8 Start Apply at target
9. Start Capture at source

Kullanılan PL/SQL paketleri şöyle
DBMS_APPLY_ADM
DBMS_CAPTURE_ADM
DBMS_FLASHBACK
DBMS_OUTPUT
DBMS_STREAMS_ADM

DBMS_APPLY_ADM Paketi
START_APPLY(), STOP_APPLY(), DELETE_ALL_ERRORS() gibi metodlar kullanılabilir
DBMS_APPLY_ADM.START_APPLY(apply_name => 'SYNC_APPLY_1');
...
DBMS_APPLY_ADM.STOP_APPLY(apply_name => 'SYNC_APPLY_1');
DBMS_APPLY_ADM.DELETE_ALL_ERRORS(apply_name => 'SYNC_APPLY_1');
Duplicate Rows
Açıklaması şöyle
1. You cannot use Oracle Streams to replicate a table which has duplicate rows. It will not work.
2. If you don’t have unique constraint on your table in some form, you will have duplicate rows.
Create Database Links
Şöyle yaparız
--on source
CONNECT strmadmin/strmadminpw;
CREATE DATABASE LINK REP01 CONNECT TO strmadmin IDENTIFIED BY strmadminpw USING 'REP01';
select count(*) from dba_tables@REP01;

-- on target
CONNECT strmadmin/strmadminpw;
CREATE DATABASE LINK DB05 CONNECT TO strmadmin IDENTIFIED BY strmadminpw USING 'DB05';
select count(*) from dba_tables@DB05
Create Queue
Örnek
Şöyle yaparız
DBMS_STREAMS_ADM.SET_UP_QUEUE(
queue_table =>'STRADMIN.SQT_IMMEDIATE1_S', 
queue_name => 'STRADMIN.SQ_IMMEDIATE_S');
Apply
streams_type olarak APPLY verilebilir
Örnek
Şöyle yaparız.
DBMS_STREAMS_ADM.ADD_TABLE_RULES( table_name => ..., streams_type => 'apply', streams_name => ..., queue_name => ... );
Capture
streams_type olarak CAPTURE, SYNC_CAPTURE verilebilir. Açıklaması şöyle
Synchronous Mode

Synchronous Capture uses triggers on the source database to capture change data. It has no latency because the change data is captured continuously and in real-time on the source database. The change tables are populated when DML operations on the source table are committed. Hence it is titled “Synchronous” Change Data Capture.

New change data arrives automatically as DML operations on the source tables are committed. Publishers can define new change sets in the predefined SYNC_SOURCE change source or use the predefined change set, SYNC_SET. The SYNC_SET change set cannot be altered or dropped.

While the “invasive” nature of the approach of the synchronous mode of Change Data Capture adds overhead to the source database at capture time, this mode can reduce costs (as compared to attempting to extract change data using table differencing or change-value section) by simplifying the extraction of change data.

Örnek - Senkron
Şöyle yaparız. inclusion_rule FALSE verilerek capture işlemi yapılmıyor
DBMS_STREAMS_ADM.ADD_TABLE_RULES(
table_name=>'DEV110.APP_QUEUE', streams_type=>'capture', streams_name=>'CAPTURE_110DEV', queue_name=>'REP_CAPTURE_QUEUE', include_dml=>TRUE, include_ddl=>TRUE, include_tagged_lcr=> FALSE, source_database=>'DB05', inclusion_rule=>FALSE, and_condition=>NULL);

11 Ağustos 2021 Çarşamba

Maven İle Oracle JDBC Thin Driver

JDBC Thin Driver vs OCI
Açıklaması şöyle. Yani Java kullanıyorsak JDBC Thin Driver yeterli.
Oracle provides four types of drivers for their database, but I'll only enumerate the two you asked about.

The OCI driver is a type 2 JDBC driver and uses native code to connect to the database. Thus, it is only an option on platforms that have native Oracle drivers available and it is not a "pure" Java implementation.

Oracle's JDBC Thin driver is a type 4 JDBC Driver that uses Java sockets to connect directly to Oracle. It implements Oracle's SQL*Net TCP/IP protocol directly. Because it is 100% Java, it is platform independent ...
Maven
ojdbc "Oracle JDBC Driver" anlamına gelir

ojdbc11
Örnek
Şöyle yaparız
<dependency>
  <groupId>com.oracle.database.jdbc</groupId>
  <artifactId>ojdbc11</artifactId>
  <version>23.2.0.0</version>
</dependency>
ojdbc10
Örnek
Şöyle yaparız
Java 11
<dependency>
    <groupId>com.oracle.database.jdbc</groupId>
    <artifactId>ojdbc10</artifactId>
    <version>${oracle.version}</version>
</dependency>

Java 8
<dependency>
    <groupId>com.oracle.database.jdbc</groupId>
    <artifactId>ojdbc8</artifactId>
    <version>${oracle.version}</version>
</dependency>

Java 6
<dependency>
    <groupId>com.oracle.database.jdbc</groupId>
    <artifactId>ojdbc6</artifactId>
    <version>${oracle.version}</version>
</dependency>
ojdbc8
Java 8 içindir
Örnek
Şöyle yaparız
<dependency>
  <groupId>com.oracle</groupId>
  <artifactId>ojdbc8</artifactId>
  <version>19.7.0.0</version>
</dependency>
Şöyle yaparız
<dependency>
  <groupId>com.oracle.database.jdbc</groupId>
  <artifactId>ojdbc8-production</artifactId>
  <version>21.7.0.0</version>
  <type>pom</type>
</dependency>
ojdbc7
Java 8 öncesi içindir
Örnek 
Şöyle yaparız
<dependency>
  <groupId>com.oracle</groupId>
  <artifactId>ojdbc7</artifactId>
  <version>12.1.0.2</version>
</dependency>
Sınıflar
Bazı sınıflar şöyle 

Connection Pool
Oracle Universal Connection Pool kullanılabilir.

Universal Connection Pool - PoolDataSource Sınıfı

Giriş
Açıklaması şöyle. Yani 12c'den sonra JDBC sürücüsü de en az 12.1.0.2 olmalı
Prior to 12c (i.e., 12.1.0.1.0), UCP could work with any version of Oracle JDBC driver. With the new pool, UCP 12.1.0.2, it is dependent on Oracle JDBC driver 12.1.0.2.
Örnek
Şöyle yaparızOracleDataSource sınıfını kullanıyor
import oracle.ucp.jdbc.PoolDataSource;
import java.sql.Connection;
import java.sql.SQLException;

PoolDataSource ds = PoolDataSourceFactory.getPoolDataSource();
ds.setUser("...");
ds.setPassword("...");
ds.setConnectionFactoryClassName("oracle.jdbc.pool.OracleDataSource");
ds.setURL("jdbc:oracle:thin:@exampledb?TNS_ADMIN=/msdataworkshop/creds");
Connecton con = ds.getConnection();
Örnek
Şöyle yaparız.
PoolDataSource pds = PoolDataSourceFactory.getPoolDataSource();

pds.setURL(...);
pds.setUser(...);
pds.setPassword(...);
pds.setConnectionFactoryClassName("oracle.jdbc.pool.OracleDataSource");

//Setting pool properties
pds.setInitialPoolSize(5);
pds.setMinPoolSize(5);
pds.setMaxPoolSize(20);

Connection conn = pds.getConnection();
Şöyle yaparız.
int usedConnectionCount = pds.getBorrowedConnectionsCount();
int availableConnectionCotun = pds.getAvailableConnectionsCount();