레이블이 === DBMS ===인 게시물을 표시합니다. 모든 게시물 표시
레이블이 === DBMS ===인 게시물을 표시합니다. 모든 게시물 표시

2010년 4월 16일 금요일

Automatic Shared Memory Management

http://www.oracle.com/technology/pub/articles/10gdba/week17_10gdba.html 

 

Automatic Shared Memory Management

Frustrated by trying to allocate the precise amount of memory required for different pools? Automatic Shared Memory Management makes it possible to allocate memory where it's needed most, automatically.

Whether you're a new or veteran DBA, you've almost certainly seen an error similar to this one at least once:

ORA-04031: unable to allocate 2216 bytes of shared memory ("shared pool"... ...
or this one:
ORA-04031: unable to allocate XXXX bytes of shared memory 
("large pool","unknown object","session heap","frame") 
or perhaps this one:
ORA-04031: unable to allocate bytes of shared memory ("shared pool",
 "unknown object","joxlod: init h", "JOX: ioc_allocate_pal")
The cause of the first error is obvious: the memory allocated to the shared pool is insufficient for answering the user request. (In some cases the cause may not be the size of the pool itself, but rather the fragmentation that results from excessive parsing due to non-usage of bind variables—a favorite topic of mine; but let's stay focused on the issue at hand right now.) The other errors derive from inadequate space in the large pool and Java pool respectively. You need to resolve these error conditions without any application-related changes. What are your options? The question is how to divide available memory among all the pools required by the Oracle instance. How Do You Split the Pie? The System Global Area (SGA) of an Oracle instance, as you know, comprises several memory areas, including the buffer cache, shared pool, Java pool, large pool, and redo log buffers. These pools occupy fixed amounts of memory in the operating system's memory space; their sizes are specified by the DBA in the initialization parameter file. The four pools—db block buffer cache, shared pool, Java pool, and large pool—occupy almost all the space inside the SGA. (Relative to the other areas, the redo log buffer does not occupy much space and is inconsequential to our discussion here.) You, as the DBA, must ensure that their respective memory allocations are sufficient. Suppose you decide that the values of these pools should be 2GB, 1GB, 1GB, and 1GB respectively. You would set the following initialization parameters to mandate the sizes of the pools for the database instance.
db_cache_size = 2g
shared_pool_size = 1g
large_pool_size = 1g
java_pool_size = 1g
Now, take a close look at these parameters. Honestly, are these values accurate? I'm sure you have your doubts. In real life, no one can specify these pools to an exact science—they depend too heavily on the processing inside the database and the nature of processing changes from time to time. Here's an example scenario. Say you have a typical, "mostly" OLTP database and have dedicated less memory for the buffer cache than you would have for a purely OLTP one (few of which exist anymore). One day, your users turn loose some very large full table scans for end-of-the-day reporting. Oracle9i Database gives you the ability to change the allocation online, but because the total physical memory available is limited, you decide to pull something away from the large pool and the Java pool:
alter system set db_cache_size = 3g scope=memory;
alter system set large_pool_size = 512m scope=memory;
alter system set java_pool_size = 512m scope=memory;
This solution works fine for a while, but then the nightly RMAN jobs—which use the large pool—begin and the pool immediately falls short. Again, you come to the rescue by supplementing the large pool with some memory from the db cache. The RMAN jobs complete, but then a batch program that uses Java extensively fires up, and consequently, you start to see Java pool-related errors. So, you reallocate the pools (again) to accommodate the demands on the Java pool and db cache:
alter system set db_cache_size = 2G scope=memory;
alter system set large_pool_size = 512M scope=memory;
alter system set java_pool_size = 1.5G scope=memory;
The next morning, the OLTP jobs come back online and the cycle repeats all over again! One alternative to this vicious cycle is to set the maximum requirements of each pool permanently. By doing that, however, you may allocate a total SGA more than the available memory—thereby increasing the risk of swapping and paging when the allocation is less than adequate for each pool. The manual reallocation method, although impractical, looks pretty good right now. Another alternative is to set the values to acceptable minimums. However, when demand goes up and memory is not available, performance will suffer. Note that in all these examples the total memory allocated to SGA remained the same, while the allocation among the pools changed based on immediate requirements. Wouldn't it be nice if the RDBMS were to automatically sense the demand from users and redistribute memory allocations accordingly? The Automatic Shared Memory Management feature in Oracle Database 10g does exactly that. You can decide the total size of the SGA and then set a parameter named SGA_TARGET that decides the total size of the SGA. The individual pools within the SGA will be dynamically configured based on the workload. A non-zero value of the parameter SGA_TARGET is all that is needed to enable the automatic memory allocation. Setting up Automatic Shared Memory Management Let's see how this works. First, determine the total size of the SGA. You can estimate this value by determining how much memory is allocated right now.
SQL> select sum(value)/1024/1024 from v$sga;

SUM(VALUE)/1024/1024
--------------------
                 500
The current total size of the SGA right now is approximately 500MB, which will become the value of SGA_TARGET. Next, issue the statement:
alter system set sga_target = 500M scope=both;
This approach obviates the need to set individual values for the pools; thus, you'll need to make their values zero in the parameter file or remove them completely.
shared_pool_size = 0
large_pool_size = 0
java_pool_size = 0
db_cache_size = 0     
Recycle the database to make the values take effect. This manual process can also be implemented via Enterprise Manager 10g. From the database home page, choose the "Administration" tab and then "Memory Parameters." For manually configured memory parameters, the button marked "Enable" will be displayed, along with the values of all manually configured pools. Click the "Enable" button to turn Automatic Shared Memory Management on. Enterprise Manager does the rest. After the automatic memory allocations are configured, you can check their sizes with the following:
SQL> select current_size from v$buffer_pool;

CURRENT_SIZE
------------
         340

SQL> select pool, sum(bytes)/1024/1024 Mbytes from v$sgastat group by pool;

POOL             MBYTES
------------ ----------
java pool             4
large pool            4
shared pool         148
As you can see, all the pools were automatically configured from the total target size of 500MB. (See Figure 1.) The buffer cache size is 340MB, Java pool is 4MB, large pool is 4MB, and shared pool is 148MB. Together they total (340+4+4+148=) 496MB, approximately the same size as the target SGA of 500MB.
 
Figure 1: Initial allocation pools

Now suppose the host memory available to Oracle is reduced from 500MB to 300MB, meaning we have to reduce the size of the total SGA. We can reflect that change by reducing the target SGA size.

alter system set sga_target = 300M scope=both;
Checking the pools now, we can see that:
SQL> select current_size from v$buffer_pool;

CURRENT_SIZE
------------
         244

SQL> select pool, sum(bytes)/1024/1024 Mbytes from v$sgastat group by pool;

POOL             MBYTES
------------ ----------
java pool             4
large pool            4
shared pool          44
The total size occupied is 240+4+4+44 = 296MB, close to the target of 300MB. Notice how the pools were automatically reallocated when the SGA_TARGET was changed, as shown in Figure 2.
 
Figure 2: Reallocation of pools after reducing SGA size to 300MB

The size of the pools is dynamic. Based on the workload, the pools will expand to accommodate the increase in demand or shrink to accommodate the expansion in another pool. This expansion or contraction occurs automatically without the DBA's intervention, unlike the example in the opening of this article. Returning to that scenario for a moment, assume that after the initial allocation the RMAN job starts, indicating the need for a larger large pool; the large pool will expand from 4MB to 40MB to accommodate the demand. This additional 36MB will be carved out of the db buffers and the db block buffers will shrink, as shown in Figure 3.

 
Figure 3: Reallocated pools after demand for large pool increases

The changed sizes of the pools are based on the workload on the system, so the pools needn't be sized for the worst-case scenario—they will automatically adjust to the growth in demand. Furthermore, the total size of the SGA is always within the maximum value specified by SGA_TARGET, so there is no risk of blowing the memory requirement out of proportion (which will lead to paging and swapping). You can dynamically increase the SGA_TARGET to the absolute maximum specified by adjusting the parameter SGA_MAX_SIZE. Which Pools are Not Affected? Some pools in SGA are not subject to dynamic resizing, and must be specified explicitly. Notable among them are the buffer pools for nonstandard block sizes and the non-default ones for KEEP or RECYCLE. If your database has a block size of 8K, and you want to configure 2K, 4K, 16K, and 32K block-size pools, you must set them manually. Their sizes will remain constant; they will not shrink or expand based on load. You should consider this factor when using multiple-size buffer, KEEP, and RECYCLE pools. In addition, log buffer is not subject to the memory adjustment—the value set in the parameter log_buffer is constant, regardless of the workload. ( In 10g, a new type of pool can also be defined in the SGA: Streams pool, set with parameter streams_pool_size. This pool is also not subject to automatic memory tuning.) This gives rise to an interesting question. What if you need a non-default block size pool yet want to manage the other pools automatically? If you specify any of these non-auto-tunable parameters (such as db_2k_cache_size), their total size is subtracted from the SGA_TARGET value to calculate the automatically tuned parameter values so that the total size of the SGA remains constant . For instance, imagine that the values look like this:

sga_target = 500M
db_2k_cache_size = 50M
and the rest of the pool parameters are unset. The 2KB buffer pool of 50MB leaves 450MB for the auto-tuned pools such as the default block size buffer pool (db_cache_size), shared pool, Java pool, and large pool. When the non-tunable parameter such as the 2KB block size pool is dynamically adjusted in such a way that the tunable portion's size is affected, the tunable portion is readjusted. For example, raising the value of db_2k_cache_size to 100MB from 50MB leaves only 400MB for the tunable parameters. So the tunable pools such as shared, large, Java, and default buffer pools shrink automatically to reduce their total size to 400MB from 450MB, as shown in Figure 4.
 
Figure 4: Effect of configuring non-automatic buffer parameters
But what if you have sufficient memory available or the risks described above may not be that pronounced? If so, you can turn off automatic resizing by not specifying the parameter SGA_TARGET in the parameter file, by setting it to zero in the file, or by changing it to zero dynamically with ALTER SYSTEM. When SGA_TARGET is set to zero, the current values of the pools are automatically set to their parameter.

Using Enterprise Manager You can also use Enterprise Manager 10g to manipulate these parameters. From the database home page, click the hyperlink "Memory Parameters," which will show you a screen similar to the one in Figure 5.

 
Figure 5: Adjusting Automatic Shared Memory Management in Enterprise Manager

Note the items circled in red: The database is running in Automatic Shared Memory Management mode and the total size is 564MB, the same value specified in the parameter SGA_TARGET. You can modify it here and click on the Apply button to accept the values; the tunable parameters will automatically adjust. Specifying a Minimum for Each Pool Suppose you have set SGA_TARGET to 600MB and the various pools have been allocated automatically:

Pool Size (MB)
Buffer 404
Java 4
Large 4
Shared 148

Looking at the above you might conclude that the Java and large pools are a bit inadequate at 4MB; this value will definitely need to be increased at runtime. Therefore, you may want to make sure the pools at least start with higher values—say, 8MB and 16MB respectively. You can do that by explicitly specifying the value of these pools in the parameter file or dynamically using ALTER SYSTEM as shown below.
alter system set large_pool_size = 16M;
alter system set java_pool_size = 8M;
Checking the pools now, you can see:
SQL> select pool, sum(bytes)/1024/1024 Mbytes from v$sgastat group by pool;

POOL             MBYTES
------------ ----------
java pool             8
large pool           16
shared pool         148

SQL> select current_size from v$buffer_pool;

CURRENT_SIZE
------------
         388
The reallocation of the pools is shown below:

Pool Size (MB)
Buffer 388
Java 8
Large 16
Shared 148

Note how the Java and large pools have been reconfigured to 8MB and 16MB respectively, and that to keep the total SGA under 600MB, the buffer pool has reduced to 388MB from 404MB. Of course, these pools are still governed by Automatic Shared Memory Management—their sizes will shrink or expand based on demand. The values you have specified explicitly put a lower limit on the pool size; they will never sink below this limit.
Conclusion The memory requirements of various pools in Oracle SGA are not static—rather, they vary based on the demand on the system. Automatic Shared Memory Management in Oracle Database 10g allows DBAs to manage system memory more efficiently by dynamically reallocating resources to where they are needed most while enforcing a specified maximum to prevent paging and swapping. More efficient memory management also leads to fewer memory requirements, which can make leaner hardware more viable. For more information about Automatic Shared Memory Management, see Chapter 7 of the Oracle Database Performance Tuning Guide.

2010년 4월 13일 화요일

ORA-01480: trailing null missing from STR bind value

ORA-01480:

trailing null missing from STR bind value
Cause: A bind variable of type 5 (null-terminated string) does not contain the terminating null in its buffer.
Action: Terminate the string with a null character

 

 

http://ora-01480.ora-code.com/ 

2010년 4월 12일 월요일

DB_CACHE_SIZE

DB_CACHE_SIZE

Property Description
Parameter type Big integer
Syntax DB_CACHE_SIZE = integer [K | M | G]
Default value

If SGA_TARGET is set: If the parameter is not specified, then the default is 0 (internally determined by the Oracle Database). If the parameter is specified, then

the user-specified value indicates a minimum value for the memory pool.

If SGA_TARGET is not set, then the default is either 48 MB or 4 MB * number of CPUs, whichever is greater

Modifiable ALTER SYSTEM
Basic No

DB_CACHE_SIZE specifies the size of the DEFAULT buffer pool for buffers with the primary block size (the block size defined by the DB_BLOCK_SIZE initialization parameter).

The value must be at least 4M * number of cpus * granule size (smaller values are automatically rounded up to this value). A user-specified value larger than this is rounded up to the nearest granule size. A value of zero is illegal because it is needed for the DEFAULT memory pool of the primary block size, which is the block size for the SYSTEM tablespace.

 

 

http://download.oracle.com/docs/cd/B28359_01/server.111/b28320/initparams049.htm

 

I got a help request from a client who was running Oracle 11.1.0.6 64-bit. Their memory_target parameter was set to 5G, with sga_target and all pool parameters set to 0. pga_aggregate_target was explicitly set to 750MB. However, Oracle would not allocate more than 64MB RAM to the Buffer Cache. We looked through multiple snapshots and never found a case where db_cache_size was above 64MB, despite a staggering amount of disk reads. So we tried to change the db_cache_size manually to set the minimum:

SQL> alter system set db_cache_size = 1024M;
alter system set db_cache_size = 1024M
*
ERROR at line 1:
ORA-32017: failure in updating SPFILE
ORA-00384: Insufficient memory to grow cache

I wanted to see if I could duplicate the issue, so I tested it on my 11.1.0.6 Windows 64-bit instance. I prepared the system by setting pga_aggregate_target to 128M, sga_target to 512M, and memory_target = 1648M.

NOTE: Throughout these examples, I’ve removed the irrelevant results from “show parameter target”.

Setting It Up

SQL> alter system set pga_aggregate_target = 128M;

System altered.

SQL> alter system set sga_target = 512M;

System altered.

SQL> alter system set memory_target = 1648M;

System altered.

SQL> show parameter target

NAME                             TYPE        VALUE
-------------------------------- ----------- -----
memory_max_target                big integer 1648M
memory_target                    big integer 1648M
pga_aggregate_target             big integer 128M
sga_target                       big integer 512M

SQL> show sga

Total System Global Area 1720328192 bytes
Fixed Size                  2115656 bytes
Variable Size            1426065336 bytes
Database Buffers          285212672 bytes
Redo Buffers                6934528 bytes

The next step was to test the change:

Testing the Change

SQL> alter system set db_cache_size = 1024M;
alter system set db_cache_size = 1024M
*
ERROR at line 1:
ORA-32017: failure in updating SPFILE
ORA-00384: Insufficient memory to grow cache

So I tried turning off memory_target, and look what happens to the PGA:

Turn off memory_target

SQL> alter system set memory_target = 0;

System altered.

SQL> show parameter target

NAME                             TYPE        VALUE
-------------------------------- ----------- -----
memory_max_target                big integer 1648M
memory_target                    big integer 0
pga_aggregate_target             big integer 1136M
sga_target                       big integer 512M

The PGA was given all of the extra space! This was pretty strange, so I went ahead and changed the PGA to 128M and tried my test again:

Try again

SQL> alter system set pga_aggregate_target = 128M;

System altered.

SQL> show parameter target

NAME                             TYPE        VALUE
-------------------------------- ----------- -----
memory_max_target                big integer 1648M
memory_target                    big integer 0
pga_aggregate_target             big integer 128M
sga_target                       big integer 512M

SQL> alter system set db_cache_size = 1024M;
alter system set db_cache_size = 1024M
*
ERROR at line 1:
ORA-32017: failure in updating SPFILE
ORA-00384: Insufficient memory to grow cache

Even then, it would not let me grow the buffer cache. I had to disable sga_target for 11g to finally allow it:

Solution

SQL> alter system set sga_target = 0;

System altered.

SQL> alter system set db_cache_size = 1024M;

System altered.

SQL> alter system set memory_target = 1648M;

System altered.

SQL> show parameter target

NAME                             TYPE        VALUE
-------------------------------- ----------- -----
memory_max_target                big integer 1648M
memory_target                    big integer 1648M
pga_aggregate_target             big integer 128M
sga_target                       big integer 0

Is this expected behavior from memory_target? Did I miss something? Is it a bug in 11.1.0.6? I was not able to find any notes on Metalink regarding the issue. The Oracle Documentation states that this should work just fine. When memory_target is enabled, sga_target and pga_aggregate_target should only work as minimums if explicitly set.

I will play around with it some more if I get the chance. In the meantime, I have to wonder how many DBAs have confidently set memory_target, all the while not knowing their individual pools weren’t being sized properly?

Update 1

I just did another test where I “primed the pump” so to speak. To do so, I set the sga_target higher. It allowed me to grow the db_cache_size at that point. However, I then set db_cache_size down to 0, set sga_target back to 512M, and was still able to set db_cache_size back up to 1024M afterwards.

NAME                         TYPE        VALUE
---------------------------- ----------- -----
memory_max_target            big integer 1648M
memory_target                big integer 1648M
pga_aggregate_target         big integer 128M
sga_target                   big integer 512M

SQL> alter system set db_cache_size = 1024M;
alter system set db_cache_size = 1024M
*
ERROR at line 1:
ORA-32017: failure in updating SPFILE
ORA-00384: Insufficient memory to grow cache

SQL> alter system set sga_target = 1300M;

System altered.

SQL> alter system set db_cache_size = 1024M;

System altered.

SQL> alter system set db_cache_size = 0;

System altered.

SQL> alter system set sga_target = 512M;

System altered.

SQL> show parameter target

NAME                         TYPE        VALUE
---------------------------- ----------- -----
memory_max_target            big integer 1648M
memory_target                big integer 1648M
pga_aggregate_target         big integer 128M
sga_target                   big integer 512M

SQL> alter system set db_cache_size = 1024M;

System altered.

SQL> show parameter target

NAME                         TYPE        VALUE
---------------------------- ----------- -----
memory_max_target            big integer 1648M
memory_target                big integer 1648M
pga_aggregate_target         big integer 128M
sga_target                   big integer 512M

SQL> show parameter db_cache_size

NAME                             TYPE        VALUE
-------------------------------- ----------- -----
db_cache_size                    big integer 1G

The end looks just like the beginning. The only difference would be an internal barrier being lifted.

 

http://www.oraclealchemist.com/oracle/strange-behavior-with-memory_target/ 

2010년 4월 9일 금요일

Dynamic Query with Dynamic SQL

Building a Dynamic Query with Dynamic SQL

You use three statements to process a dynamic multi-row query: OPEN-FOR, FETCH, and CLOSE. First, you OPEN a cursor variable FOR a multi-row query. Then, you FETCH rows from the result set one at a time. When all the rows are processed, you CLOSE the cursor variable. (For more information about cursor variables, see "Using Cursor Variables (REF CURSORs)".)

Examples of Dynamic SQL for Records, Objects, and Collections

Example 7-3 Dynamic SQL Fetching into a Record

As the following example shows, you can fetch rows from the result set of a dynamic multi-row query into a record:

DECLARE
   TYPE EmpCurTyp IS REF CURSOR;
   emp_cv   EmpCurTyp;
   emp_rec  emp%ROWTYPE;
   sql_stmt VARCHAR2(200);
   my_job   VARCHAR2(15) := 'CLERK';
BEGIN
   sql_stmt := 'SELECT * FROM emp WHERE job = :j';
   OPEN emp_cv FOR sql_stmt USING my_job;
   LOOP
      FETCH emp_cv INTO emp_rec;
      EXIT WHEN emp_cv%NOTFOUND;
      -- process record
   END LOOP;
   CLOSE emp_cv;
END;
/

Example 7-4 Dynamic SQL for Object Types and Collections

The next example illustrates the use of objects and collections. Suppose you define object type Person and VARRAY type Hobbies, as follows:

CREATE TYPE Person AS OBJECT (name VARCHAR2(25), age NUMBER);
CREATE TYPE Hobbies IS VARRAY(10) OF VARCHAR2(25);

Using dynamic SQL, you can write a package that uses these types:

CREATE OR REPLACE PACKAGE teams AS
   PROCEDURE create_table (tab_name VARCHAR2);
   PROCEDURE insert_row (tab_name VARCHAR2, p Person, h Hobbies);
   PROCEDURE print_table (tab_name VARCHAR2);
END;
/

CREATE OR REPLACE PACKAGE BODY teams AS
   PROCEDURE create_table (tab_name VARCHAR2) IS
   BEGIN
      EXECUTE IMMEDIATE 'CREATE TABLE ' || tab_name ||
         ' (pers Person, hobbs Hobbies)';
   END;

   PROCEDURE insert_row (
      tab_name VARCHAR2,
      p Person,
      h Hobbies) IS
   BEGIN
      EXECUTE IMMEDIATE 'INSERT INTO ' || tab_name ||
         ' VALUES (:1, :2)' USING p, h;
   END;

   PROCEDURE print_table (tab_name VARCHAR2) IS
      TYPE RefCurTyp IS REF CURSOR;
      cv RefCurTyp;
      p  Person;
      h  Hobbies;
   BEGIN
      OPEN cv FOR 'SELECT pers, hobbs FROM ' || tab_name;
      LOOP
         FETCH cv INTO p, h;
         EXIT WHEN cv%NOTFOUND;
         -- print attributes of 'p' and elements of 'h'
      END LOOP;
      CLOSE cv;
   END;
END;
/

From an anonymous block, you might call the procedures in package TEAMS:

DECLARE
   team_name VARCHAR2(15);
BEGIN
   team_name := 'Notables';
   teams.create_table(team_name);
   teams.insert_row(team_name, Person('John', 31),
      Hobbies('skiing', 'coin collecting', 'tennis'));
   teams.insert_row(team_name, Person('Mary', 28),
      Hobbies('golf', 'quilting', 'rock climbing'));
   teams.print_table(team_name);
END;
/

http://download.oracle.com/docs/cd/B14117_01/appdev.101/b10807/11_dynam.htm#sthref935 

2010년 4월 8일 목요일

PCC-F-02104, Unable to connect to Oracle

참 골치 아픈 에러다 ...

 

Unable to connect to Oracle 은 여러가지의 의미를 가진다.

 

     1. ORACLE 이 shutdown 되어 있는상태.

     2. PL/SQL 구문검사시 해당 USER/PASSWD 가 일치하지 않는 경우.

     3. LIstener 가 활성화 되지 않은 경우.

     4. 기타 서버의 상태가 접속 가능 하지 않는 상황.

     

특히 PL/SQL 문장이 포함된 파일인 경우 위의 에러는 해당 USER 의 상태를 확인 하여야한다.

ID / USER 대소문자만 틀려도 위의 에러가 발생한다.

 

pcscfg.cfg 내에 있는  USERID=PROC5/PROC5 

- PL/SQL 문법 검사시 사용된다.

 

자신의 코드 안에 있는 접속 USERID/PASSWD

- *.pc 를 c 로 변환하여, 실행파일을 수행시 해당 유저의 세션을 open 할때 사용한다.

- 실행파일을 수행하여 세션을 open 할때 유저정보가 틀리다면 위의 에러가 아닌 다른 에러를 출력한다.

 

  ORA-01017 : invalid username/password: logon denied

 

PL/SQL 이 포함되지 않는 경우라면..

 

SQLCHECK=SYNTAX

으로 변경한다.

 

2010년 4월 7일 수요일

ORA-28000: the account is locked

SQL> conn proc/proc
ERROR:
ORA-28000: the account is locked

 

SQL> alter user proc account unlock;

 

User altered.

 

SQL> conn proc/proc
Connected.

error while loading shared libraries: libclntsh.so.11.1: cannot open shared object file: No such file or directory

[oracle@localhost ~]$ proc
proc: error while loading shared libraries: libclntsh.so.11.1: cannot open shared object file: No such file or directory

 

.bash_profile 에 추가

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ORACLE_HOME/lib

 

그래도 안되면 $ORACLE_HOME/lib 에 파일 이 있는지 확인후 없으면 링크

[oracle@localhost lib]$ ln -s libclntsh.so.10.1  libclntsh.so

 

 

2010년 4월 5일 월요일

PRO*C에서 PLSQL PROCEDURE에 HOST ARRAY BINDING하는 방법

http://kr.forums.oracle.com/forums/thread.jspa?messageID=1661451 

 

PRO*C에서 PLSQL PROCEDURE에 HOST ARRAY BINDING하는 방법
게시일: 2007. 1. 29 오전 2:39





제품 : PRECOMPILERS

작성날짜 : 2001-06-15

PRO*C에서 PLSQL PROCEDURE에 HOST ARRAY BINDING하는 방법
=======================================================

proc*c안에서 PL/SQL stored procedures로 host arrays를 넘기는
방법을 알아봅니다.

sample program 실행하는 방법.

1. 먼저 pl/sql package를 만듭니다.
sqlplus scott/tiger @pkg.sql

2. 만든 package를 test해 봅니다.
sqlplus scott/tiger @harness.sql

3. testit.pc를 compile합니다.
make -f $ORACLE_HOME/precomp/demo/proc/demo_proc.mk build EXE=testit OBJS=testit.o PROCFLAGS="SQLCHECK=full USERID=scott/tiger"

Program



pkg.sql - - - - - - - - - - - - - - Code begins here - - - - - - - - - - - - - - - -
rem pkg.sql follows...
create or replace package my_package as
type charTabTyp is table of char(15) index by binary_integer;
type numTabTyp is table of number index by binary_integer;
procedure test_plsql_table_parameters (t1 in out charTabTyp,
t2 in out numTabTyp);
end my_package;
/
show errors
create or replace package body my_package as
procedure test_plsql_table_parameters (t1 in out charTabTyp,
t2 in out numTabTyp) is
begin
for i in 1..t1.count loop
t1(i):= 'NEW '||i;
end loop;
for i in 1..t2.count loop
t2(i):= i*100;
end loop;
end;
end my_package;
/
show errors
quit

pkg.sql- - - - - - - - - - - - Code ends here - - - - - - - - - - - - - - - -

harness.sql - - - - - - - - - - Code begins here - - - - - - - - - - - - - - - -
rem harness.sql follows...
set serverout on
declare
v1 my_package.charTabTyp;
v2 my_package.numTabTyp;
begin
for i in 1..5 loop
v1(i):=i||' '||sysdate;
v2(i):=i*10;
end loop;
dbms_output.put_line('Before...');
dbms_output.put_line('Num rows in v1 is '||v1.count);
for i in 1..v1.count loop
dbms_output.put_line(v1(i));
end loop;
dbms_output.put_line('Num rows in v2 is '||v2.count);
for i in 1..v2.count loop
dbms_output.put_line(v2(i));
end loop;
my_package.test_plsql_table_parameters(v1, v2);
dbms_output.put_line('AFTER...');
dbms_output.put_line('Num rows in v1 is '||v1.count);
for i in 1..v1.count loop
dbms_output.put_line(v1(i));
end loop;
dbms_output.put_line('Num rows in v2 is '||v2.count);
for i in 1..v2.count loop
dbms_output.put_line(v2(i));
end loop;
end;
/
quit
harness.sql - - - - - - - - - - Code ends here - - - - - - - - - - - - - - - -

testit.pc - - - - - - - - - - - Code begins here - - - - - - - - - - - - - - - -
/* testit.pc starts here... */

#include <stdio.h>
#include <string.h>
#include <sqlca.h>

void sql_error();

/* as the parameter is a PL/SQL in out we need to reserve a space for the
terminator. */
typedef char mystring[16];
EXEC SQL TYPE mystring is CHARZ(16);

#define SIZE 20
main()
{
mystring char_array[SIZE];
int num_array[SIZE];
int i,j;
char *connstr = "scott/tiger";

/* Register sql_error() as the error handler. */
EXEC SQL WHENEVER SQLERROR DO sql_error("ORACLE error--\n");

/* Connect to ORACLE. */
EXEC SQL CONNECT :connstr;

printf("\nConnected to ORACLE as user: %s\n", connstr);

printf("Populating the arrays to be inserted...\n");
for (i=0; i<SIZE; i++)
{
num_array = i*10;
strcpy(char_array," Hello");
printf("\tElement %d of num_array is %d\n", i, num_array);
printf("\tElement %d of char_array is %s\n", i, char_array);
}
EXEC SQL EXECUTE
begin
my_package.test_plsql_table_parameters(:char_array, :num_array);
end;
END-EXEC;

printf("After call to stored procedure the contents looks like...\n");
for (i=0; i<SIZE; i++)
{
printf("\tElement %d of num_array is %d\n", i, num_array);
printf("\tElement %d of char_array is %s\n", i, char_array);
}
printf("\nG'day.\n\n\n");

/* Disconnect from ORACLE. */
EXEC SQL COMMIT WORK RELEASE;
exit(0);
}

void
sql_error(msg)
char *msg;
{
char err_msg[128];
int buf_len, msg_len;

EXEC SQL WHENEVER SQLERROR CONTINUE;

printf("\n%s\n", msg);
buf_len = sizeof (err_msg);
sqlglm(err_msg, &buf_len, &msg_len);
printf("%.*s\n", msg_len, err_msg);

EXEC SQL ROLLBACK RELEASE;
exit(1);
}


testit.pc - - - - - - - - - - - Code ends here - - - - - - - - - - - - - - - -

Sample Output



Connected to ORACLE as user: scott/tiger
Populating the arrays to be inserted...
Element 0 of num_array is 0
Element 0 of char_array is Hello
Element 1 of num_array is 10
Element 1 of char_array is Hello
Element 2 of num_array is 20
Element 2 of char_array is Hello
Element 3 of num_array is 30
Element 3 of char_array is Hello
Element 4 of num_array is 40
Element 4 of char_array is Hello
Element 5 of num_array is 50
Element 5 of char_array is Hello
Element 6 of num_array is 60
Element 6 of char_array is Hello
Element 7 of num_array is 70
Element 7 of char_array is Hello
Element 8 of num_array is 80
Element 8 of char_array is Hello
Element 9 of num_array is 90
Element 9 of char_array is Hello
Element 10 of num_array is 100
Element 10 of char_array is Hello
Element 11 of num_array is 110
Element 11 of char_array is Hello
Element 12 of num_array is 120
Element 12 of char_array is Hello
Element 13 of num_array is 130
Element 13 of char_array is Hello
Element 14 of num_array is 140
Element 14 of char_array is Hello
Element 15 of num_array is 150
Element 15 of char_array is Hello
Element 16 of num_array is 160
Element 16 of char_array is Hello
Element 17 of num_array is 170
Element 17 of char_array is Hello
Element 18 of num_array is 180
Element 18 of char_array is Hello
Element 19 of num_array is 190
Element 19 of char_array is Hello
After call to stored procedure the contents looks like...
Element 0 of num_array is 100
Element 0 of char_array is NEW 1
Element 1 of num_array is 200
Element 1 of char_array is NEW 2
Element 2 of num_array is 300
Element 2 of char_array is NEW 3
Element 3 of num_array is 400
Element 3 of char_array is NEW 4
Element 4 of num_array is 500
Element 4 of char_array is NEW 5
Element 5 of num_array is 600
Element 5 of char_array is NEW 6
Element 6 of num_array is 700
Element 6 of char_array is NEW 7
Element 7 of num_array is 800
Element 7 of char_array is NEW 8
Element 8 of num_array is 900
Element 8 of char_array is NEW 9
Element 9 of num_array is 1000
Element 9 of char_array is NEW 10
Element 10 of num_array is 1100
Element 10 of char_array is NEW 11
Element 11 of num_array is 1200
Element 11 of char_array is NEW 12
Element 12 of num_array is 1300
Element 12 of char_array is NEW 13
Element 13 of num_array is 1400
Element 13 of char_array is NEW 14
Element 14 of num_array is 1500
Element 14 of char_array is NEW 15
Element 15 of num_array is 1600
Element 15 of char_array is NEW 16
Element 16 of num_array is 1700
Element 16 of char_array is NEW 17
Element 17 of num_array is 1800
Element 17 of char_array is NEW 18
Element 18 of num_array is 1900
Element 18 of char_array is NEW 19
Element 19 of num_array is 2000
Element 19 of char_array is NEW 20

G'day.

simple VARRAY example


DECLARE
  TYPE
Str_Array IS VARRAY(4) OF VARCHAR2(50);
  v_array  
Str_Array;

  PROCEDURE PROCESS_ARRAY
(v_str_array  Str_Array)
  AS
 
BEGIN
    FOR i IN v_str_array
.first .. v_str_array.last LOOP
      DBMS_OUTPUT
.PUT_LINE('Hello '||v_str_array(i));
   
END LOOP;
 
END;

BEGIN

  v_array
:= Str_Array('John','Paul','Ringo','George');

  PROCESS_ARRAY
(v_array);

 
-- can also pass unbound Str_Array
  PROCESS_ARRAY
(Str_Array('John','Paul','Ringo','George'));

END;