POUWIEL|COM

JeroenPouwiel

PL/SQL thingy for selecting and creating insert PL/SQL thingy

Just like this, sure it can be extended with some checks and other nifty things..:

DECLARE
  counter     number  := 1 ;
  -- declare a varchar variable to contain the
  -- TO_CHAR string, as DATE type is actually 
  -- a number
  v_date2char varchar2(50) ;
  --
  CURSOR c_data_ballage
    IS
    SELECT code
    ,      description
    ,      TO_CHAR(completion, 'YYYY/MM/DD HH24:MI:SS') AS completion
      FROM ballage ;
BEGIN
  DBMS_OUTPUT.ENABLE(1000000) ;
	
  DBMS_OUTPUT.PUT_LINE('DECLARE') ;
  DBMS_OUTPUT.PUT_LINE('  lStart            number := 1 ;') ;
  DBMS_OUTPUT.PUT_LINE('  CODE_ARRAY        dbms_sql.number_table ;') ;
  DBMS_OUTPUT.PUT_LINE('  DESCRIPTION_ARRAY dbms_sql.varchar2_table ;') ;
  DBMS_OUTPUT.PUT_LINE('  COMPLETION_ARRAY  dbms_sql.date_table ;') ;
  DBMS_OUTPUT.PUT_LINE('BEGIN') ;
  DBMS_OUTPUT.PUT_LINE(' ') ;
	
  FOR data_record IN c_data_ballage LOOP
    -- As moment of writing Oracle database considers NULL and empty string ('')
    -- as equal, as show in sample below:
    -- SQL> SELECT NVL(NULL,'This returns NULL') A,NVL('','This will too') B FROM DUAL;  
    -- A                 B  
    -- ----------------- -------------
    -- This returns NULL This will too
		
    IF data_record.completion IS NOT NULL THEN
      v_date2char := 'TO_DATE('''||data_record.completion||''', '''||'YYYY/MM/DD HH24:MI:SS'||''')' ;  
    ELSE
      v_date2char := ''''||data_record.completion||'''' ;
    END IF ;
		
    DBMS_OUTPUT.PUT_LINE('    CODE_ARRAY('||counter||') := '  || data_record.code ||' ;') ;
    DBMS_OUTPUT.PUT_LINE('    DESCRIPTION_ARRAY('||counter||') := '''|| data_record.description ||''' ;') ;
    DBMS_OUTPUT.PUT_LINE('    COMPLETION_ARRAY('||counter||') := '|| v_date2char ||' ;') ;
    counter     := counter + 1 ;
    v_date2char := NULL ;
  END LOOP ;
	
  DBMS_OUTPUT.PUT_LINE('    LOOP') ;
  DBMS_OUTPUT.PUT_LINE('    BEGIN') ;
  DBMS_OUTPUT.PUT_LINE('    	FORALL i IN lStart..CODE_ARRAY.COUNT') ;
  DBMS_OUTPUT.PUT_LINE('    		INSERT INTO ballage VALUES (CODE_ARRAY(i), DESCRIPTION_ARRAY(i), COMPLETION_ARRAY(i) ) ;') ;
  DBMS_OUTPUT.PUT_LINE('    	EXIT ;') ;
  DBMS_OUTPUT.PUT_LINE('    EXCEPTION WHEN OTHERS THEN') ;
  DBMS_OUTPUT.PUT_LINE('    	lStart := lStart + sql%ROWCOUNT + 1 ;') ;
  DBMS_OUTPUT.PUT_LINE('    END ;') ;
  DBMS_OUTPUT.PUT_LINE('  END LOOP ;') ;
  DBMS_OUTPUT.PUT_LINE('END ;') ;
  DBMS_OUTPUT.PUT_LINE('/') ;
END ;
/

This will generate the following output (for my “ballage” table that is):

DECLARE
  lStart            number := 1 ;
  CODE_ARRAY        dbms_sql.number_table ;
  DESCRIPTION_ARRAY dbms_sql.varchar2_table ;
  COMPLETION_ARRAY  dbms_sql.date_table ;
BEGIN

    CODE_ARRAY(1) := 101 ;
    DESCRIPTION_ARRAY(1) := 'WRITING' ;
    COMPLETION_ARRAY(1) := TO_DATE('2017/02/27 14:00:00', 'YYYY/MM/DD HH24:MI:SS') ;
    CODE_ARRAY(2) := 102 ;
    DESCRIPTION_ARRAY(2) := 'PROCESSING' ;
    COMPLETION_ARRAY(2) := TO_DATE('2017/03/14 15:30:00', 'YYYY/MM/DD HH24:MI:SS') ;
    CODE_ARRAY(3) := 103 ;
    DESCRIPTION_ARRAY(3) := 'SEEDING' ;
    COMPLETION_ARRAY(3) := TO_DATE('2017/05/08 11:28:01', 'YYYY/MM/DD HH24:MI:SS') ;
    CODE_ARRAY(4) := 104 ;
    DESCRIPTION_ARRAY(4) := 'TRANSFORMING' ;
    COMPLETION_ARRAY(4) := TO_DATE('2018/07/07 17:30:00', 'YYYY/MM/DD HH24:MI:SS') ;
    CODE_ARRAY(5) := 105 ;
    DESCRIPTION_ARRAY(5) := 'BAWLING' ;
    COMPLETION_ARRAY(5) := '' ;
    LOOP
    BEGIN
        FORALL i IN lStart..CODE_ARRAY.COUNT
                INSERT INTO ballage2 VALUES (CODE_ARRAY(i), DESCRIPTION_ARRAY(i), COMPLETION_ARRAY(i) ) ;
        EXIT ;
    EXCEPTION WHEN OTHERS THEN
        lStart := lStart + sql%ROWCOUNT + 1 ;
    END ;
  END LOOP ;
END ;
/

Compute Statistics

EXEC DBMS_STATS.GATHER_TABLE_STATS(‘<user>’, ‘<table_name>’, estimate_percent => NULL, cascade => TRUE);

Instead of estimating the statistics using a given percentage, this will hit all rows.

GRANT ANY ROLE without granting “GRANT ANY ROLE”

[15:28:03_DBA_ORCL@TSERVER] TST 
SQL> create user sw_owner identified by sw_owner;
SQL>   grant create session, create table to sw_owner;
SQL>   grant create procedure to sw_owner;
SQL>   alter user sw_owner quota 5m on  users;
SQL>   grant grant any role to sw_owner;

SQL> create user sw_admin identified by sw_admin;
SQL>   grant create session to sw_admin;

SQL> create user sw_user1 identified by sw_user1;
SQL>   grant create session to sw_user1;

SQL> create table sw_owner.sw_table1 (a number);
SQL>   insert into sw_owner.sw_table1 (a) values (1);
SQL>   insert into sw_owner.sw_table1 (a) values (2);
SQL>   insert into sw_owner.sw_table1 (a) values (3);
SQL>   commit;

SQL> create role sw_role1;
SQL> grant select on sw_owner.sw_table1 to sw_role1;


SQL> CREATE OR REPLACE PACKAGE sw_owner.sw_package1
  2  IS
  3     PROCEDURE sw_procedure1 (p_grantee varchar2);
  4  END;
  5  /

SQL> CREATE OR REPLACE PACKAGE BODY sw_owner.sw_package1
  2  IS
  3  -- ---------------------------------------------------
  4     PROCEDURE sw_procedure1 (p_grantee  VARCHAR2)
  5     IS
  6     v_query       varchar2(200);
  7     BEGIN
  8       v_query := 'GRANT sw_role1 to '|| p_grantee;
  9       EXECUTE IMMEDIATE v_query;
 10     END;
 11  END;
 12  /
SQL> create public synonym sw_package1 for sw_owner.sw_package1;

SQL> grant execute on sw_owner.sw_package1 to sw_admin;

SQL> conn sw_admin/sw_admin@orcl
SQL> execute sw_package1.sw_procedure1('sw_user1');
SQL> conn sw_user1/sw_user1@orcl
SQL> select * from sw_owner.sw_table1;

         A
----------
         1
         2
         3

Duplicate {data/temp} filenames

With a generous wink to my esteemed colleague Remi Visser, for your (but mostly mine) Ctrl-C / Ctrl-V benefit:

SQL> SELECT SUBSTR ( file_name, INSTR( file_name, '/', -1)) file_name, COUNT(*)
  2  FROM dba_data_files
  3  GROUP BY SUBSTR ( file_name,INSTR( file_name, '/', -1)) 
  4  HAVING COUNT(*) > 1
  5  /

FILE_NAME                               COUNT(*)
------------------------------------- ----------
/****p1i005ds10.dbf                            2
/****p1i005ds11.dbf                            2

SQL>


To retrieve the complete filename, as mentioned in dba_data_files/dba_temp_files:

SQL> SELECT *
  2  FROM dba_data_files
  3  WHERE SUBSTR ( file_name, INSTR( file_name, '/', -1)) IN (
  4     SELECT file_name FROM (
  5        SELECT SUBSTR ( file_name, INSTR( file_name, '/', -1)) file_name, 
  6        COUNT(*)
  7        FROM dba_data_files
  8        GROUP BY SUBSTR ( file_name,INSTR( file_name, '/', -1))
  9        HAVING COUNT(*) > 1 )
 10     )
 11  ORDER BY 3, 1;

FILE_NAME                                                               FILE_ID
---------------------------------------------------------------------- --------
/m021/oradata/********/********p1boff00106.dbf                              153
/m001/oradata/********/********p1boff00106.dbf                              154
/m005/oradata/********/********p1boff00209.dbf                               40
/m002/oradata/********/********p1boff00209.dbf                               39
/m006/oradata/********/********p1boffis08.dbf                                52
/m004/oradata/********/********p1boffis08.dbf                               163

6 rows selected.

To gather any statistics

On any schema, you’d need an any-privilege…
Which so happens to be: ANALYZE ANY DICTIONARY and ANALYZE ANY

So, give these to user you want to call the dbms_stats package and all will be fine…

In this case, I created this tiny script: Read the rest of this entry »

Pretty basic procedure

For the life of me, I can never seem to remember this stuff… Read the rest of this entry »

FGA

Use FGA to simulate a parallel export in Oracle8: Read the rest of this entry »

Unattended Export/Import

For this setup, I create a folder “./out” and a folder “./log” on the OS and the becessary pipes.
In the source database, I create as many users I need to, each of these user has at least the privilege to export the entire database.
If you add (and I did), FGA policies on tables of a specific user, you can simulate a parallel export in database version that do not support this natively. Read the rest of this entry »

# of open cursors

Again, a query for retrieving the number of open cursors per SID for the copy/paste-minded dba’s out there: Read the rest of this entry »

Flagitious, guileful and malignant piece of code

aka Oracle 10g agent

Today we received a sev2 ticket regarding an agent that was down. Don’t know why, seeing as the daylight savings time issue occurred on the 29th of March. Below the transcript of starting the agent: Read the rest of this entry »

Retro histogramming in Excel

When catching up on my L-/RPADding for graphical histograms on the sql*plus prompt, i ran across this link on Tom’s blog.

Should come in handy, when building reports in PHP that query (Oracle) databases and saves the results in Excel. Nice.


Read the rest of this entry »

SQL worst practices in less than 20 minutes

Beware of parsing, beware of I/O, beware of the accent.
Just beware…
Read the rest of this entry »

Interrupt a cold-backup of an archivelog-enabled db

Ran into a offline backup that took too long and went outside of the blackout.
A little querieng against the V$SESSION_LONGOPS told me it would take prox. another 3.8 hrs to finish.

Not something you want to wait for @ 02:00 am.

This is a 9i database (9.2.08) in archivelog mode, mounted an’ all.
All it took was a: “alter database open” and the offline backup transformed into a online version. Read the rest of this entry »

Retrieve background process name in SQL*Plus

I’ve been busy modifying my script which display all sessions in the database. I wanted to have the names of the background processes, not difficult i know. The trick is to get them in every (version of) database displayed correctly. Eventually i had it working: Read the rest of this entry »

Database links

We regularly get the request for a refresh of an OTA database.
Usually, the end-users would like for their settings to survive the refresh.

We use a couple of scripts to save these setting (eg. passwords and such), however, the database links didn’t survive last time.
Probably because the passwords aren’t visible anymore in 10g.
Update!: Not true, just had a peek in SYS.LINK$ ver 10.1.05 and column AUTHPWD still had (unencrypted!) values.
Update2!: Somewhat true, just had a peek in SYS.LINK$ ver 10.2.0.1 & 10.2.0.2 and column PASSWORDX has encrypted values.

It is possible to retrieve the passwords using dbms_metadata.get_ddl.
More after the jump:
Read the rest of this entry »

DDL above DML

I found out this afternoon that a transaction waiting to receive all required latches is subordinate to a ddl statement. Regard the following:

[ZZXJFF@OCP04:W2ZZXJFF02]
SQL> select * from blaat;

A          B
- ----------
b          1
b          2

Read the rest of this entry »

Online Redolog corruption or a bug ?

One of our databases went over the fritz yesterday. We regurarly receive a request from the functional administrators to kill a session (batch-user) in the database. Often the session doesn’t end quick enough to the admin’s likings.
Read the rest of this entry »

Online Redefinition

Got the request to reorder a table’s column order. It was/is a simple enough table: 4 columns where the last two needed to be the first two.
Look after the jump to see how it went down:

Updated! Read the rest of this entry »

RMAN backup & recovery

Just began reading this book, in aid of my (short-term) memory, here are (the first of) a few excerpts from that book, after the jump:
Read the rest of this entry »

Materialized Views

Nasty buggers,

Just came across a mview that didn’t gave results when it should’ve.
Most likely, it was in the wrong refresh_group, below the query to check in which refresh_group the mview is: Read the rest of this entry »

Logminer

To retrieve or correct (mostly user-) data using Logminer:
Read the rest of this entry »

Explain plan

Just a mental note for myself for using explain plan:
Read the rest of this entry »

Query and replace carriage returns:

Just ran into a hidden carriage retun inside the requested data. I wanted to spool to a .csv file and got garbled data.
Fix like this: Read the rest of this entry »

Modify LOB maxextents (8i and above)

To alter the maxextents of a LOB, try the next statement:
ALTER TABLE . MOVE LOB () STORE AS
(STORAGE (MAXEXTENTS UNLIMITED));
Read the rest of this entry »

Pending XA transactions

And how to roll ’em back:

Stop Spine/MQ and query dba_2pc_pending and/or dba_pending_transactions.

As sysdba :

rollback force 'local_tran_id#';
exec dbms_transaction.purge_lost_db_entry('local_tran_id#');
commit;

Et voila…

Sources: Admin_guide DBA_2PC_NEIGHBORS DBA_2PC_PENDING DBA_PENDING_TRANSACTIONS

Export a query from Oracle via PHP to Excel

The easiest thing you will find on the net for spooling a resultset from Oracle to an Excel format via php, will probably be that you need to add: Read the rest of this entry »

Statistics in Oracle

To determine when the statistics have gathered for a certain table:
Note: to speed things up, you’d might consider: Read the rest of this entry »

Connect description

SQL> conn user_name@(description=(ADDRESS=(PROTOCOL=TCP)(HOST=hostname.domain)(PORT=portnumber))(CONNECT_DATA=(SID=sid)))
Enter password: ********
Connected.

pretty straightforward

To change the DBid of an database:

Here’s how:

sql> shutdown immediate
sql> startup mount
sql> exit

Read the rest of this entry »

Alter size next extent

To alter the size of the next extent:

Alter table table_name storage (next 5M);

Trigger naming convention

Below a conventional way of naming triggers:

trigger_name_|B|S|I
|A|R|U
|D

B before
A after
S statement
R row
I insert
U update
D delete

A couple of performance queries

Below a couple of queries to give you an idea about how your database is performing: Read the rest of this entry »

Categories