Proc*c를 이용해 Sub Program(Procedure or Function)을 호출 하는 방법에 대해 설명한다.
자료를 되져보면 대부분의 샘플 코드가 Procedure 로만 되어 있다.
여기서는 Function을 호출 해 보기로 한다.
사실 호출 방법은 거의 비슷 하다.
- 컴파일 방법
PL/SQL 구문을 사용하기 때문에 proc 컴파일 옵션을 주어야 한다.
그런데, 컴파일 옵션을 주면 다른 Pro*c 구문에서 컴파일이 안되는 일이 발생을 한다.
따라서, PL/SQL 구문을 사용하는 소스는 별도 .pc 파일로 때어 내어서 별도 컴파일을 해야한다.
DB Link로 Remote 테이블을 참조 하고 있는 프로세스가 작업을 수행하고 있는 상태에서,
Remote DB가 Shotdown 되는 경우 위 에러가 발생 한다.
Remote DB가 Start되고 새로운 세션을 맺어야 프로세스가 정상 동작을 한다.
세션을 유지한 상태에서 Remote DB가 Start 되어도 위 에러가 계속 발생한다.
말이 어렵다 테스트 해보자.
1. ORA TNS에 RemoteDB를 추가한다.
2. DB 링크를 생성한다.
CREATE PUBLIC DATABASE LINK test_link CONNECT TO remoteDBid IDENTIFIED BY remoteDBpwd USING 'remoteDB';
CREATE SYNONYM test_proc FOR test_proc_table@test_link
SELECT * FROM test_proc
3. 데이터를 삽입한다.
insert into test_proc values ( 1, 1 );
insert into test_proc values ( 2, 1 );
~~~~~~
insert into test_proc values ( 33, 1 );
insert into test_proc values ( 44, 1 );
4. 테스트 프로그램을 작성한다.
$ vi t.pc
#include <stdio.h>
EXEC SQL INCLUDE SQLCA;
#define MAX_ARRAY_SIZE 10
int main()
{
int n;
EXEC SQL BEGIN DECLARE SECTION;
int hSEQ;
char hOracleUser[20] = "localDBid";
char hOraclePwd[20] = "localDBpwd";
EXEC SQL END DECLARE SECTION;
EXEC SQL CONNECT :hOracleUser IDENTIFIED BY :hOraclePwd;
if(sqlca.sqlcode !=0)
{
printf( "login fail\n");
return 0;
}
for (n=0; n<10; n++)
{
printf( "start of job\n");
EXEC SQL DECLARE CUR_TEST_PROC CURSOR FOR
SELECT SEQ FROM TEST_PROC;
EXEC SQL OPEN CUR_TEST_PROC;
while(1)
{
EXEC SQL FETCH CUR_TEST_PROC INTO :hSEQ;
sleep(3);
if(sqlca.sqlcode != 0)
{
if(sqlca.sqlcode == 1403)
{
printf( "data not found\n");
break;
}
else
{
printf( "fetch Error [%20s]\n" , sqlca.sqlerrm.sqlerrmc);
break;
}
}
printf("fetch [%d]\n", hSEQ );
}
EXEC SQL CLOSE CUR_TEST_PROC;
printf( "end of job\n");
} /* for */
return 0;
}
$ proc iname=t.pc
$ cc -o t t.c -L/home/oracle/app/oracle/product/8.1.7/lib -lclntsh -R/home/oracle/app/oracle/product/8.1.7/lib
SQL> set autot on exp
SQL> 사용자 쿼리
SQL> set autot off
SQL> rollback;
- 현재 연결된 세션
SQL> select count(*) from v$session;
- 세션 정보
SQL> select status, sid from v$session;
- 사용자명 별 연결 세션
SQL> select USERNAME, count(1) from v$session group by USERNAME;
- 케릭터셋 보기
SQL> select * from v$nls_parameters WHERE PARAMETER='NLS_CHARACTERSET'
- 메모리에 올라가 있는 쿼리 보기
SQL> select * from V$SQL_SHARED_MEMORY
- 메모리에 올라가 있는 쿼리 지우기
(CPU, DISK 사용량이 증가하므로, 야간에 작업할 것)
SQL> ALTER SYSTEM FLUSH SHARED_POOL;
- 연결된 커서 갯수 및 쿼리 출력
SQL> SELECT a.cnt,
a.user_name,
b.sql_text,
a.hash_value
FROM (SELECT COUNT (*) cnt,
user_name,
hash_value
FROM v$open_cursor
GROUP BY user_name,
hash_value) a,
v$sqlarea b
WHERE a.hash_value = b.hash_value AND ROWNUM <= 100
ORDER BY cnt DESC;
- 특정 테이블의 외래키 출력
SQL> SELECT A.TABLE_NAME table_name
, A.CONSTRAINT_NAME key_name
, B.TABLE_NAME referencing_table
, B.CONSTRAINT_NAME foreign_key_name
, B.STATUS fk_status
FROM USER_CONSTRAINTS A
, USER_CONSTRAINTS B
WHERE A.CONSTRAINT_NAME = B.R_CONSTRAINT_NAME
AND B.CONSTRAINT_TYPE = 'R'
AND A.OWNER = '대문자 계정명'
AND ( A.TABLE_NAME = '대문자 테이블명' OR B.TABLE_NAME = '대문자 테이블명' )
NORMAL : 현재 사용자가 연결을 끊을때까지 대기 default 옵션
TRANSACTIONAL : 접속된 사용자들이 새롭게 트랜잭션을 시작할 수 없습니다. 사용자의 트랜잭션이 끝나면 연결이 종료되면 모든 트랙잭션이 종료되면 데이터베이스가 즉시 종료 됩니다.
IMMEDIATE : 현재 진행중인 SQL문이 완료되지 않으며 현재 사용자의 연결을 즉시 끝으며, 모든 트랜잭션을 롤백합니다.
ABORT : 강제 종료라고 할수 있으며 다음번 데이터베이스 시작시 인스턴스 복구가 필요합니다.
* 사용 Software : EVC4.0, SQL SERVER CE 4.0
ADO쓰지 않고,, OLEDB사용
* 예제소스 : SQL SERVER CE 인스톨후 NorthwindOleDb 사용
로컬에 그냥 DB파일(sdf)을 사용하여 에뮬로 테스트 할 예정
ADO 쓰지 않고..OLEDB 사용함...
헌데.. "CLSID_SQLSERVERCE_2_0"가 등록 되지 않았다고 함..
어떻게 해야죠?
hr = CoCreateInstance( CLSID_SQLSERVERCE_2_0,
0,
CLSCTX_INPROC_SERVER,
IID_IDBInitialize,
(void**)&pIDBInitialize);
CREATE procedure p_GetValue (
@tagName as nvarchar(20),
@mode as real output,
@sp as real output,
@pv as real output,
@ivp as real output,
@alm_a as real output,
@alm_b as real output,
@alm_c as real output,
@alm_dbnd as real output,
@mvp as real output,
@out as real output,
@in as real output,
@ao as real output
)
if @FieldName_mode IS Null
set @strSQL = @strSQL + N' @mode=null'
else
set @strSQL = @strSQL + N' @mode= ' + @FieldName_mode
if @FieldName_sp IS Null
set @strSQL = @strSQL + N', @sp=null'
else
set @strSQL = @strSQL + N', @sp=' + @FieldName_sp
if @FieldName_pv IS Null
set @strSQL = @strSQL + N', @pv=null'
else
set @strSQL = @strSQL + N', @pv=' + @FieldName_pv
if @FieldName_ivp IS Null
set @strSQL = @strSQL + N', @ivp=null'
else
set @strSQL = @strSQL + N', @ivp=' + @FieldName_ivp
if @FieldName_alm_a IS Null
set @strSQL = @strSQL + N', @alm_a=null'
else
set @strSQL = @strSQL + N', @alm_a=' + @FieldName_alm_a
if @FieldName_alm_b IS Null
set @strSQL = @strSQL + N', @alm_b=null'
else
set @strSQL = @strSQL + N', @alm_b=' + @FieldName_alm_b
if @FieldName_alm_c IS Null
set @strSQL = @strSQL + N', @alm_c=null'
else
set @strSQL = @strSQL + N', @alm_c=' + @FieldName_alm_c
if @FieldName_alm_dbnd IS Null
set @strSQL = @strSQL + N', @alm_dbnd=null'
else
set @strSQL = @strSQL + N', @alm_dbnd=' +@FieldName_alm_dbnd
if @FieldName_mvp IS Null
set @strSQL = @strSQL + N', @mvp=null'
else
set @strSQL = @strSQL + N', @mvp=' + @FieldName_mvp
if @FieldName_out IS Null
set @strSQL = @strSQL + N', @out =null'
else
set @strSQL = @strSQL + N', @out =' + @FieldName_out
if @FieldName_in IS Null
set @strSQL = @strSQL + N', @in =null'
else
set @strSQL = @strSQL + N', @in =' + @FieldName_in
if @FieldName_ao IS Null
set @strSQL = @strSQL + N', @ao =null'
else
set @strSQL = @strSQL + N', @ao =' + @FieldName_ao
set @strSQL = @strSQL + N' from ' + @tableName
print @strSQL
exec sp_executesql @strSQL,
N'@mode real output, @sp real output, @pv real output, @ivp real output, @alm_a real output, @alm_b real output, @alm_c real output, @alm_dbnd real output, @mvp real output, @out real output, @in real output, @ao real output',
@mode output, @sp output, @pv output, @ivp output, @alm_a output, @alm_b output, @alm_c output, @alm_dbnd output, @mvp output, @out output, @in output, @ao output
end