Very good
Piotr Jarmuz, September 26, 2002 - 4:28 am UTC
Thanx! Especially for external tables tip.
It was timed in miliseconds and it was INSTANTANEOUS :-).
I agree. The benefits from shifting tuning efforts from developer's shoulders to some Oracle savvy seem to compensate for this 5-10% overhead at least in OLTP applications.
If you never used Perl you perhaps should have a try.
I'm sure you'd love it ;-).
To me Perl, Oracle and Apache are just made one for another.
It would be nice if next Oracle version (10i ???) could have Perl Virtual Machine embedded in it. The Oracle-Perl world out there would most appreciate it.
September 26, 2002 - 7:59 am UTC
I've looked at perl.
To me, If I cannot read a language without digging through a ton of manuals, I don't want to touch it ;)
I'll stick with
sql
plsql
java
c
(and sed,awk,grep of course...)
A reader, September 26, 2002 - 10:34 am UTC
Piotr Jarmuz:
Could you please explain / point us to some websites that has more info, on "Pearl virtual machine" - never heard of it before.
PVM
Piotr Jarmuz, September 27, 2002 - 5:38 am UTC
A reader, September 27, 2002 - 9:56 am UTC
Thank you verymuch.
Delimited By more than one character
Sri, April 03, 2003 - 3:06 pm UTC
Dear Tom,
I want to use more than one character as my "delimited by". Say, I want to use a @ and a NewLine as delimiter. I tried giving
records delimited by 0x'400a'
where 40 is the hex for @ and 0a is the one for Newline. I have the .dat file as follows -
1|John|Marketing@
2|Blake|Logistics@
3|Smith|Personnel And
Human Resources@
4|Harry|Finance@
and the external table definition is as follows: -
CREATE TABLE Emp_Ext
(Emp_No Number(3),
EName Varchar2(50),
Dept Varchar2(100)
)
ORGANIZATION EXTERNAL
( TYPE ORACLE_LOADER
DEFAULT DIRECTORY MyData_Dir
ACCESS PARAMETERS
( RECORDS DELIMITED BY 0x'400a'
FIELDS TERMINATED BY '|'
MISSING FIELD VALUES ARE NULL )
LOCATION ('Emp.dat')
)
/
The select * from Emp_Ext is returning only one row. Please help me in solving this. Thank you.
April 03, 2003 - 3:26 pm UTC
ops$tkyte@ORA920> !cat /tmp/Emp.dat
1|John|Marketing@
2|Blake|Logistics@
3|Smith|Personnel And
Human Resources@
4|Harry|Finance@
ops$tkyte@ORA920>
ops$tkyte@ORA920> create or replace directory mydata_dir as '/tmp'
2 /
Directory created.
ops$tkyte@ORA920>
ops$tkyte@ORA920> CREATE TABLE Emp_Ext
2 (Emp_No Number(3),
3 EName Varchar2(50),
4 Dept Varchar2(100)
5 )
6 ORGANIZATION EXTERNAL
7 ( TYPE ORACLE_LOADER
8 DEFAULT DIRECTORY MyData_Dir
9 ACCESS PARAMETERS
10 ( RECORDS DELIMITED BY 0x'400a'
11 FIELDS TERMINATED BY '|'
12 MISSING FIELD VALUES ARE NULL )
13 LOCATION ('Emp.dat')
14 )
15 /
Table created.
ops$tkyte@ORA920> column ename format a20
ops$tkyte@ORA920> column dept format a30
ops$tkyte@ORA920> select * from emp_ext;
EMP_NO ENAME DEPT
---------- -------------------- ------------------------------
1 John Marketing
2 Blake Logistics
3 Smith Personnel And
Human Resources
4 Harry Finance
works for me...
tried it in:
9012
9201
9203
you might have your data in the wrong directory or something -- in anycase, review the logs that go with external tables.
Still not working...
Sri, April 03, 2003 - 4:11 pm UTC
Dear Tom,
Thank you for your quick response.
But when I ran the same query, I am getting the following result: -
EMP_NO ENAME DEPT
---------- -------------------- ------------------------------
1 John Marketing@
2
My Emp.Log file is as follows: -
LOG file opened at 04/03/03 16:00:42
Field Definitions for table EMP_EXT
Record format DELIMITED, delimited by 400a
Data in file has same endianness as the platform
Fields in Data Source:
EMP_NO CHAR (255)
Terminated by "|"
Trim whitespace same as SQL Loader
ENAME CHAR (255)
Terminated by "|"
Trim whitespace same as SQL Loader
DEPT CHAR (255)
Terminated by "|"
Trim whitespace same as SQL Loader
Really can't understand why it is not working for me. I am using Oracle 9i (9.0.1.1.1). Is there any knows issues for external tables for this particular version Tom?
By the way, I was wondering why that 1 line space is there in between 3rd and 4th record in your output.
Thank you.
April 03, 2003 - 9:12 pm UTC
just due to sqlplus formatting -- the data is OK:
ops$tkyte@ORA9I> column ename format a20
ops$tkyte@ORA9I> column dept format a30
ops$tkyte@ORA9I> select '"' || emp_no || '"'empno, '"' || ename || '"'ename, '"' || dept || '"'dept from emp_ext
2 /
EMPNO ENAME DEPT
---------------------- -------------------- ------------------------------
"1" "John" "Marketing"
"2" "Blake" "Logistics"
"3" "Smith" "Personnel And
Human Resources"
"4" "Harry" "Finance"
I used 9.0.1.2 -- I don't have 9.0.1.1 -- don't know of anything as specific as this being a problem.
A reader, April 03, 2003 - 5:22 pm UTC
could you please explain why you "firmly believe the best java programs are those that have ZERO "selects/inserts/updates/deletes" in them."?
April 03, 2003 - 9:17 pm UTC
because PLSQL should have it all....
because then I can fix it without having to dig into the java code.
because then we can tune it.
because then we can figure out what uses what.
because then we can have people who understand databases do the database stuff.
because we can make them use bind variables for the sql (just have to force them to use binds for the stored procedure calls)
and so on...
PERL is nice , but ...
pasko, April 04, 2003 - 2:28 am UTC
Hi Tom and Piotr...
Thanks for a great thread above...
I am also using PERL sometimes to interface Oracle with some Web GUI clients and i have to always use REF cursors as we can not pass PL/SQL Tables..
Perl is also very good for Pattern matching stuff...
I have also observed that although all Package 'IN' parameters should be seen as BIND Variables in v$sql view ,
that's not the case when using PERL ...
I was surprized the other Day when i looked at this view and saw no BIND values ( :b1 , :b2 etc.. ) at all from all pERL WEB client programs...
i see :
BEGIN :curResult :=
my_package.ret_ref_cur_function('real value1' ,
'real value 2' ); END;
instead of :
BEGIN :curResult := my_package.ret_ref_cur_function( :my_bind1 , :my_bind2 ); END;
I know it's messing up our shared pool...
Has anyone any idea how come perl does not use BIND variables even when using stored subprograms in a Package ?
Thanks in advance.
Nothing wrong with Perl bind variables!
Piotr Jarmuz, April 14, 2003 - 11:30 am UTC
Hello,
I checked at my site and it all works great:
For example I look at library cache:
select sql_text from v$sql where upper(sql_text) like '%JOEYS%'
And I see in one of the rows something like this:
begin joeys.touch_message(:p1,:p2); end;
It DOES use bind variables. And the Perl code for this call is as follows:
$query="begin joeys.touch_message(?,?); end;";
eval {
$sth=$dbh_proddb->prepare_cached($query);
$sth->bind_param(1,$usr_id);
$sth->bind_param(2,$msg_id);
$sth->execute();
$sth->finish();
$dbh_proddb->commit();
}; if $@ {
$dbh_proddb->rollback();
handle_error();
...
}
Note:
It uses client side caching so I only do at most one hard parse and some soft parses in all the Apache processes next requests use cached handle so no parse at all.
More exactly if there are N Apache children and each does M requests on average, this aproach gives:
i) 1 hard parse
ii) N-1 soft parses
iii)(M-1)*N no parse at all!
Not bad as for a "stateless" environment ;)
Beside look like I don't use autocommit "feature" and control commits and rollbacks explicitly
As for the versions, we use:
1. Oracle 9iR2 EE client and server
2. Oracle DBD 1.06
3. Perl DBI 1.34
The only problematic issue I know about Perl Oracle DBD is that it is slow when working with ref cursors returned from stored procedures due to not prefetching on such refcursors. Might be fixed in the latest release. I got a newsletter recently about that but I did not have much time to explore it yet...
Best regards
Perl Vs. Java
A reader, August 20, 2003 - 2:01 pm UTC
Hi Tom,
Now that there is Java in the database
would you suggest to still continue be using perl.
:) Thank you
August 21, 2003 - 5:05 pm UTC
if you got perl
if you know perl
if you like perl
if perl is satisfying your needs
seems like you should be using perl (i wouldn't, i don't have it, know it, like it)...
but the same could be said of java
or vb
or C
or even plsql
Thanks :)
A reader, August 21, 2003 - 6:54 pm UTC
Perl vs. Java
Piotr Jarmuz, September 06, 2003 - 11:44 pm UTC
Paraphrasing W. Churchil words:
There are too many companies with too many programers that have invested too much money in such a CRAPPY implementation! While Perl is Open Source...
But hey! Linux is too!
Java as language is coherent, complete but the implementation... it sucks! Oracle's Autora is little different but still...
I think it sucks...
Think of Perl as SCRIPTED "C"... It's no more no less but a scripted C.
I might even set out to rewrite the JVM... soon...
BTW...
My Perl-Oracle integration is done...
Your book EO1O1 page: 1044 made me sure: there IS 1:1
UGA to extproc agent...
Regards.
September 07, 2003 - 6:05 pm UTC
(you probably don't want to know how much i shudder when I see perl code, i like java better then perl)....
so, it seems to be a matter of preference...
Arrange a meeting...
Piotr Jarmuz, September 07, 2003 - 12:22 am UTC
Oracle vs. Perl
Larry vs. Larry
Larry Ellison - Larry Wall ;)
Regards.
GRID IS COMMING...
awk like function using PL/SQL
A reader, March 16, 2005 - 7:50 am UTC
Hi
I have this function which acts like AWK print $1, $2 etc
CREATE OR REPLACE FUNCTION AWK(P_STRING VARCHAR2, P_POSITION NUMBER, P_DELIMIT VARCHAR2)
RETURN VARCHAR2
AS
type array is table of VARCHAR2(1000);
l_array array := array();
l_string VARCHAR2(1000) := p_string;
l_pos NUMBER;
l_count NUMBER;
BEGIN
LOOP
EXIT WHEN l_string is null;
l_pos := instr(l_string, p_delimit);
l_array.extend;
l_array(l_array.count) := trim(substr(l_string, 1, l_pos - 1));
l_string := substr(l_string, l_pos + 1);
END LOOP;
l_string := l_array(p_position);
RETURN l_string;
END AWK;
/
it works happily when I pass
AWK('1#2#3#', 2, '#')
however it goes to infinite loop if I pass
AWK('1#2#3', 2, '#')
Is there a away to overcome this?
March 16, 2005 - 8:36 am UTC
when parsing a delimited string, I typically process:
l_string long := p_string || p_delimit;
to ensure there is always a "last" delimiter. else you have to make the logic to find the next l_pos to be
l_pos := instr(l_string,p_delimit);
if ( nvl(l_pos,0) = 0 ) then l_pos := length(l_string)+1; end if;
I did it
A reader, March 16, 2005 - 9:23 am UTC
I modify and added an IF it works now cheers
CREATE OR REPLACE FUNCTION AWK(P_STRING VARCHAR2, P_POSITION NUMBER, P_DELIMIT VARCHAR2)
RETURN VARCHAR2
AS
type array is table of VARCHAR2(1000);
l_array array := array();
l_string VARCHAR2(1000) := p_string;
l_pos NUMBER;
l_count NUMBER;
BEGIN
LOOP
EXIT WHEN l_string is null;
l_pos := instr(l_string, p_delimit);
l_array.extend;
IF ( l_pos > 0 )
THEN
l_array(l_array.count) := trim(substr(l_string, 1, l_pos - 1));
l_string := substr(l_string, l_pos + 1);
ELSE
l_array(l_array.count) := trim(substr(l_string, 1));
l_string := NULL;
END IF;
END LOOP;
l_string := l_array(p_position);
RETURN l_string;
EXCEPTION
WHEN SUBSCRIPT_BEYOND_COUNT
THEN
RAISE_APPLICATION_ERROR(-20001, 'There arent ' || p_position || ' fields');
END AWK;
/
use l_string long := p_string || p_delimit; may be a bug?
A reader, March 17, 2005 - 12:09 pm UTC
Hi
if we use
l_string long := p_string || p_delimit;
then when we loop we will have a extra loop therefore an extra element which may be a bug correct?
External table
Srinath N, May 13, 2005 - 8:39 am UTC
i have created external file table and copied the data file in the server. while select the following error displays.
SQL> select * from emp_ext t;
select * from emp_ext t
ORA-29913: error in executing ODCIEXTTABLEOPEN callout
ORA-29400: data cartridge error
KUP-00554: error encountered while parsing access parameters
KUP-01005: syntax error: found "minussign": expecting one of: "enclosed, exit, (, ltrim, lrtrim, ldrtrim, missing, notrim, optionally, rtrim, reject"
KUP-01007: at line 3 column 1
ORA-06512: at "SYS.ORACLE_LOADER", line 14
ORA-06512: at line 1
pls clarify this
May 13, 2005 - 10:35 am UTC
your create table has a syntax error in the external table part.
awk like function
Adrian, May 26, 2005 - 2:30 pm UTC
Unless you're trying to exercise your PL/SQL table skills, there's no reason to use them for strings. Here's another version:
FUNCTION awk( p_string varchar2, p_position number, p_delimit varchar2 ) RETURN VARCHAR2 AS
l_string varchar2(1000);
l_count integer;
l_left integer;
l_right integer;
e_range exception;
BEGIN
-- find out how many items are in the list
l_count := length(p_string) - length(replace(p_string,p_delimit)) + 1;
-- validate position
if p_position < 1
or p_position > l_count then
raise e_range;
end if;
-- extract the item at the specified position
if p_position = 1 then
-- first item
l_right := instr( p_string, p_delimit );
l_string := substr( p_string, 1, l_right - 1 );
--
elsif p_position = l_count then
-- last item
l_left := instr( p_string, p_delimit, -1 );
l_string := substr( p_string, l_left + 1 );
--
else
-- somewhere in between
l_left := instr( p_string, p_delimit, 1, (p_position - 1) );
l_right := instr( p_string, p_delimit, l_left + 1 );
l_string := substr( p_string, l_left + 1, l_right - l_left - 1 );
end if;
--
RETURN l_string;
--
EXCEPTION WHEN e_range THEN
RAISE_APPLICATION_ERROR(-20001, 'Position '||p_position||' is out of range [1..'||l_count||']');
END AWK;
OK
Rajesh, June 20, 2007 - 7:53 am UTC
Hi Tom,
I tried using awk for setting a field separator which exists as "," to ":".
But this is not working.
Please let me know how to make this work.
Test$ : cat > a.txt
10,20,30,40
50,60,70,80
^Z[1] + Stopped (SIGTSTP) cat > a.txt
Test$ :
Test$ : cat a.txt
10,20,30,40
50,60,70,80
Test$ : awk ' BEGIN { FS = ":" } ; { print $0 } ' a.txt > aa.txt
Test$ : cat aa.txt
10,20,30,40
50,60,70,80
Test$ : awk ' BEGIN { FS == ":" } ; { print $0 } ' a.txt > aa.txt
Test$ : cat aa.txt
10,20,30,40
50,60,70,80
Test$ : awk ' BEGIN { FS == ":" } END { print $0 } ' a.txt > aa.txt
Test$ : cat aa.txt
Test$ :
A reader, December 26, 2008 - 4:12 am UTC
Hi Tom
I have a perl script which does the following
It first counts the rows of a table(say realtor this one has over million records) and dumps that
value into another table (say abc)
Then it starts doing an insert into a table(say test)(direct insert from this table realtor)
Can you please suggest me a way how I can do these things simultaneously ? that is while the
insertion is going on I want the counting to happen too using perl?
Any help will be greatly Appreciated
Thanks
December 29, 2008 - 3:31 pm UTC
sigh
look at the other place you asked this same exact question.
perl
A reader, December 29, 2008 - 11:20 pm UTC
Don't post samething twice or more
Parthiban Nagarajan, December 30, 2008 - 7:22 am UTC
Phrasebook Design Pattern or SQL::Library
Parthiban Nagarajan, May 23, 2012 - 6:06 am UTC
May 23, 2012 - 10:13 am UTC
well the introduction for phrasebook sounded like an advertisement for stored procedures:
Why is this "a problem"? It looks like nice code, doesn't it? Actually, if you look at the code above, you will see two languages: Perl and SQL. This makes the code not that readable. Besides, SQL statements that are only slightly different may appear in several places, and this will make it more difficult to maintain. In addition, suppose you have an SQL expert who should optimize your SQL calls. How do you let him work on the SQL; should he look through your Perl code for it? And what if that guy is so ignorant that he doesn't even know Perl?I'm sorry, but that concept (phrasebook) underwhelmed me.
sql-library even more so. I felt like I was transported back to 1990 and I was writing windows 3.0 code again (.ini files?)
If you wanted to satisfy the goal set up by phrasebook, it seems like you really really really want stored procedures.
you get the separation they desire.
you get the ability to have different people work on sql versus <whatever 3gl you want>
you get the benefit of the security aspects of stored procedures (programs do not need select/insert/update/delete access - just execute on a transaction)
you get the benefit of the dependency mechanism. "hey - what processes use this table over here" - a simple query answers that.
you get the benefit of reduced parsing (stored procedures cache open statements in a wonderful way!)
you get the benefit of knowing your SQL uses binds correctly (although you have to make sure the developers still bind to the stored procedure call!)
and so on.
and I wouldn't see the need to use either to store plsql calls. to me:
$statement = $sql->get("RUN_MY_PROCEDURE",
{ description => "administrator of manuals",
id => 77 });
isn't really different from
$sth = $dbh->prepare($statement) ;
bind/bind/bind
$rc=$sth->execute();
and I'm sure you could write a routine that would do the prepare/bind/bind for you in a single call if you wanted.