Monday, March 29, 2010

File Transfering From Unix to Windows

Recently I've been given a task of finding errors in some script files.Hence I need to transfer the files to my pc.(i.e Unix to Windows). So as easy way to use the filezilla and just drag and dropping you could FTP. but I wanted to try by the command line too. The following are the commands.

open the command prompt in windows.

C:\job_file>ftp
ftp> open 169.226.1.101
Connected to 169.226.1.101.
220 169.226.1.101 FTP server (Version 4.1 Tue May 15 16:38:46 CDT 2001) ready.
User (169.226.1.101:(none)): test
331 Password required for test.
Password:*****
230 User test logged in.
ftp> pwd
257 "/home/job" is current directory.
ftp> get testjob.job
200 PORT command successful.
150 Opening data connection for testjob.job
688 bytes).226 Transfer complete.
ftp: 727 bytes received in 0.00Seconds 727000.00Kbytes/sec.
ftp>

Now the file has been tranferred and it exists at C:\job_file\

For more Reference: http://www.albany.edu/its/quickstarts/qs-ftp.html

Monday, January 25, 2010

How to Call a C program in PL/SQL?

For the DB installed in Linux platform
Compiled the C code and generated .so file
gcc -o calc_tax.so -shared calc_tax.c

Step1: Conn scott/tiger@orcl

Step2: CREATE OR REPLACE LIBRARY c_lib
AS
'/tmp/calc_tax.so';

Note : You should have CREATE LIBRARY privelege

Step3: CREATE OR REPLACE FUNCTION tax_amt(x BINARY_INTEGER)
RETURN BINARY_INTEGER
AS LANGUAGE C
LIBRARY c_lib
NAME "calc_tax";

calc_tax.c is given below
-----------------------------------------------------
calc_tax(n)

int n;

{

int tax;

tax = (n*8)/100;

return(tax);

}



main()

{

int tot_ord;

printf("Enter the Order Total ");

scanf("%d",&tot_ord);

printf("\n%d", calc_tax(tot_ord));

printf("\n\n");

}



Step4: SELECT tax_amt(10000)
FROM DUAL;

Saturday, January 2, 2010

Fine Grained Access Control in Oracle 10g

Fine-Grained Access is also known as a virtual private database (VPD) because it implements row-level security, essentially giving user access to his or her own private database. Fine-grained means at the individual row level.

SYS_CONTEXT

SELECT sys_context('', '');
FROM dual;

System defined:
Eg:
Attribute_Name Attribute_Value
USERENV IP_ADDRESS
USERENV SESSION_USER
USERENV CURRENT_SCHEMA
USERENV DB_NAME
USERENV TERMINAL

To View:
SELECT sys_context(‘USER_ENV’,’IP_ADDRESS’)
FROM dual;

Create your own context by

CREATE OR REPLACE CONTEXT name_of_context
USING package_name;

Eg:
CREATE CONTEXT my_context
USING my_pack;

• At the time of the creation of the context, it is not necessary to exist the package.
• You should have the CREATE ANY CONTEXTprivilege.
• To view your context use, dba_context



Set the context using

DBMS_SESSION.SET_CONTEXT(‘context_name’,’attribute_name’,’attribute_value’);

Note: This has to be in a package body.

CREATE OR REPLACE PACKAGE my_pack
IS

procedure set_application_context;

END;

CREATE OR REPLACE PACKAGE BODY my_pack
IS

procedure set_application_context
IS
BEGIN
DBMS_SESSION.SET_CONTEXT('my_context','name','GR10’);
END;

END;

You may get “ORA-01031: insufficient privileges” error while running the above.
You should:
SQL> conn sys as sysdba
SQL> grant execute on dbms_session to imran;


And log in as

SQL> CONN imran/imran@orcl
SQL> execute my_pack.set_application_context;

SQL> SELECT sys_context(‘my_context’,’name’)
FROM dual;

SYS_CONTEXT('MY_CONTEXT','NAME')
-------------------------------------------
GR10

Real Scenario of implementing Fine Grained Access

Steps to be followed:
1. Set up a driving context.
2. Create the package associated with the context you defined in the step1. In the package:
a. Set the context.
b. Define the predicate.
3. Define the policy.
4. Set up a logon trigger to call the package at logon time and set the context.
5. Test the policy.



1. Set up a driving context.

CREATE CONTEXT user_group_context
USING emp_group_pack;

2. Create the package

CREATE OR REPLACE PACKAGE emp_group_pack
IS

procedure show_app_context;
procedure set_application_context;
Function the_predicate (p_schema Varchar2,p_name Varchar2)
Return varchar2;
END;



CREATE OR REPLACE PACKAGE BODY IMRAN.emp_group_pack
IS
vc_context_name CONSTANT varchar2(30) := 'USER_GROUP_CONTEXT';
vc_attribute_name CONSTANT varchar2(30) := 'GROUP_ID';

procedure set_application_context
IS
vc_user VARCHAR2(50);
BEGIN
SELECT user INTO vc_user
FROM dual;

DBMS_SESSION.SET_CONTEXT(vc_context_name,vc_attribute_name,user);
END;

procedure show_app_context
IS
BEGIN
DBMS_OUTPUT.PUT_LINE(' Context Name:'||vc_context_name||' Context attribute:'||vc_attribute_name||
' Attribute Value:'||sys_context(vc_context_name,vc_attribute_name));

END;


Function the_predicate (p_schema Varchar2,p_name Varchar2)
Return varchar2
IS
vc_restriction VARCHAR2(100);
vc_context Varchar2(30) := SYS_CONTEXT(vc_context_name,vc_attribute_name);
BEGIN

IF vc_context like 'USER%' THEN
vc_restriction := ' GROUP_ID = '||SUBSTR(vc_context,5);
END IF;

RETURN vc_restriction;

END;

END;
/



3. Define the policy.

DBMS_RLS.ADD_POLICY( Object_schema IN VARCHAR2 := NULL,
Object_name IN VARCHAR2,
Policy_Name IN VARCHAR2,
Function_Schema IN VARCHAR2,
Policy_Function IN VARCHAR2,
Statement_Types IN VARCHAR2 := NULL,
Update_check IN BOOLEAN := FALSE,
Enable IN BOOLEAN := TRUE );


SQL> conn sys as sysdba
Enter password: ***
Connected.
SQL> BEGIN
2 DBMS_RLS.ADD_POLICY
3 ( 'IMRAN',
4 'EMP',
5 'GROUP_ID_POLICY',
6 'IMRAN',
7 'EMP_GROUP_PACK.THE_PREDICATE',
8 'SELECT,UPDATE,DELETE',
9 TRUE,
10 TRUE);
11 END;
12 /

To Drop the policy:

BEGIN
DBMS_RLS.DROP_POLICY
( 'IMRAN',
'EMP',
'GROUP_ID_POLICY'
);
END;


SQL> create user USER3
2 identified by USER3;

User created.

SQL> grant connect,resource to user3;

Grant succeeded.


SQL> conn sys/sys as sysdba
Connected.
SQL> create or replace trigger set_id_on_logon
2 after logon on database
3 BEGIN
4 imran.EMP_GROUP_PACK.set_application_context;
5 END;
6 /

Trigger created.

SQL> conn user1/user1

SQL> select *
2 from imran.emp;

EMP_ID NAME SAL GROUP_ID
---------- ------------------------------ ---------- ----------
200 aaa 5000 1
100 King 24000 1
101 Dehan 17000 1
110 Stepens 20500 1

Wednesday, October 28, 2009

How to use UNICODE characters in PL/SQL?

We had a requirement to write a pl/sql function to return strings in sinhala/tamil characters. So just copying and pasting the sinhala/tamil characters in the function body don't work. Hence we need to use unicode characters for this. just using unicode characters not sufficient. Should use the
UNISTR function.
Eg:
UNISTR('\0DB1\0DDC:') returns අංක: (Sinhala)
UNISTR('\0B87\0BB2:') returns இல: (Tamil)

Although the stored unicode characters values be taken as
ASCIISTR(column_name)

Tuesday, September 1, 2009

Virtual Columns in Oracle 11g

Very exiting feature of Virtual columns are introduced in Oracle 11g. Have a look. Click Here

Friday, August 14, 2009

On Looping, First, and Last Choose the best approach to prevent a VALUE_ERROR exception.

by steven feuerstein
if I try to use a FOR loop to iterate from FIRST to LAST and my collection is empty, PL/SQL
raises a VALUE_ERROR exception. What’s the best way to avoid raising this error? First, the raising of VALUE_ERROR has nothing to do with your collection. The PL/SQL runtime engine will raise a VALUE_ERROR exception whenever it tries to execute a numeric FOR loop and
either the low or high expression in the loop’s header evaluates to NULL. To avoid this exception, you must ensure that neither the low nor the high expression evaluates to NULL.
When you’re working with collections, there are several ways to accomplish this, most of which should be avoided because of their drawbacks. I will first show you each of them and then offer
my views on which should be used and which should be avoided. Each approach example is an implementation of the show_names procedure defined in this package specification:
PACKAGE employees_mgr
IS
TYPE names_t IS TABLE OF
employees.last_name%TYPE
INDEX BY PLS_INTEGER;
PROCEDURE show_names
(names_in IN names_t);
END employees_mgr;

Approach 1. Use NVL to ensure that the FOR loop header’s low and high expressions
never return NULL.
PROCEDURE show_names
(names_in IN names_t)
IS
BEGIN
FOR indx IN NVL (names_in.FIRST, 0) .. NVL (names_in.LAST, -1)
LOOP
DBMS_OUTPUT.PUT_LINE
(names_in(indx));
END LOOP;
END show_names;

Approach 2. Execute the loop only if at least one element is defined in the collection.
PROCEDURE show_names
(names_in IN names_t)
IS
BEGIN
IF names_in.COUNT > 0 THEN
FOR indx IN names_in.FIRST .. names_in.LAST LOOP
DBMS_OUTPUT.PUT_LINE (names_in(indx));
END LOOP;
END IF;
END show_names;
Approach 3. Execute the FOR loop with 1 for the low value and COUNT for the high value.
PROCEDURE show_names
names_in IN names_t) IS
BEGIN
FOR indx IN 1 .. names_in.COUNT LOOP
DBMS_OUTPUT.PUT_LINE(names_in(indx));
END LOOP;
END show_names;
Approach 4. Use a WHILE loop and the FIRST and NEXT collection methods.
PROCEDURE show_names
(names_in IN names_t) IS
l_index PLS_INTEGER;
BEGIN
l_index := names_in.FIRST;
WHILE (l_index IS NOT NULL) LOOP
DBMS_OUTPUT.PUT_LINE (names_in(l_index));
l_index := names_in.NEXT(l_index);
END LOOP;
END show_names;
All four approaches achieve the desired effect: VALUE_ERROR will not be raised, even if the number of elements in the names_in collection is 0. Yet I will argue that the first approach should never be used and that the other three techniques should be chosen only when
certain conditions are met.The first approach, using NVL, is a classic example of a programmer’s trying to be too clever by half and ending up with code that is hard to understand and maintain.
Consider the header of the FOR loop:
FOR indx IN NVL (names_in.FIRST, 0) .. NVL (names_in.LAST, -1)
If I had not written this block originally and now had to maintain it, I would have to study this code to determine what exactly the point of it is. Whenever a developer must analyze and interpret code to uncover its intention, there is a chance of misinterpretation and then the
introduction of a bug.I suggest that, as a general rule, developersavoid being clever and instead write code that explains itself. Which brings me to the second approach:
use the COUNT method to ensure that the FOR loop is executed only when there is something in the collection. Here is the relevant code:
IF names_in.COUNT > 0 THEN
FOR indx IN names_in.FIRST .. names_in.LAST
I believe this code speaks for itself. It says: “If the collection contains at least
one element, iterate from the lowest to the highest index value and take the specified action. If the collection is empty, skip the FOR loop entirely.” This is a vast improvement over the
first approach, yet I cannot recommend it under all circumstances. The problem is that if the actual collection passed to the names_in parameter is sparse (that is, at least one index value between FIRST and LAST is not defined), the FOR loop will raise a NO_DATA_FOUND exception:
SQL> DECLARE
2 names_in employees_mgr.names_t;
3 BEGIN
4 names_in (1) := ‘Kirk’;
5 names_in (5) := ‘Spock’;
6 employees_mgr.show_names(names_in);
7 END;
8 /
DECLARE
* ERROR at line 1:ORA-01403: no data found
This happens because the FOR loop is instructed to display the name found in names_in(1) through names_in(5). When the PL/SQL runtime engine tries to read the contents of names_in(2), it finds that there is no element defined at index value 2 and it raises NO_DATA_FOUND.
Thus, I recommend this second technique only when you know without any doubt that the collection through which you are iterating is either empty or densely filled (all index values between FIRST and LAST are defined). You can be sure of this whenever you populate
the collection with a BULK COLLECT query or with the result of a nested table MULTISET operation (UNION, UNION ALL, INTERSECT, or EXCEPT). The third technique iterates from 1 to the COUNT of elements in the collection:
FOR indx IN 1 .. names_in.COUNT
This technique has the advantage of avoiding the clutter of an IF statement to ensure that the FOR loop executes only when the collection is not empty. If the collection is empty, COUNT will return 0 (not NULL) and the FOR loop body will not execute, because 0 is less than 1.It is concise and readable, but it has the same drawback as the previous technique: it assumes that the collection is either empty or densely filled. It also assumes that the lowest defined index value is 1. If you are not absolutely certain that the collection will always be filled, starting with index value 1, you should not use this technique. Which brings us to the fourth and last approach: don’t use a FOR loop at all.
Instead use a WHILE loop and the NEXT method:
l_index := names_in.FIRST;
WHILE (l_index IS NOT NULL) LOOP
DBMS_OUTPUT.PUT_LINE(names_in(l_index));
l_index := names_in.NEXT(l_index);
END LOOP;
This approach makes no assumptions about the contents of the collection. The names_in collection can be empty,densely filled, or sparse, and the program will still “do the right thing.” The key to this technique’s flexibility is the use of the NEXT method. This method returns
the next (highest) index value after the specified index value that is defined, ignoring (or, at least conceptually, skipping over) all undefined index values.You might then expect that I would
recommend that you always use this technique if you want to iterate through all the elements of a collection. Yet that is not the case. Suppose that when I wrote the show_names procedure, it was intended to be used to display the contents of a collection that was populated with a BULK
COLLECT statement. In such a case, the collection is always empty or sequentially
filled, starting from index value 1. The show_names procedure works properly and the code goes into production. Now suppose further that a year later, another developer is instructed to make a change to one of the programs that calls employees_mgr.show_names. The developer makes a mistake and deletes several of the elements in the collection that is passed to show_names. The collection is now sparsely filled, but it should not be. Still, show_names does its job without raising any errors. The net result is that show_names has, in effect,covered up an error.The bottom line is that if you are writing code to iterate through a collection and you know for certain that this collection should be sequentially filled,you should use
FOR indx IN 1 .. .COUNT
if you also know that the collection is
always filled from index value 1 (as with
BULK COLLECT and MULTISET), or use
IF .COUNT > 0 THEN
FOR indx IN .FIRST ...LAST
if the lowest index value might be a value other than 1.

Source : Oracle Magazine September/October 2009