Oracle自定义编码规则的实现
在编写程序的过程中,我们经常会用到对一些记录进行编码的实现,有时候定义的编码规则并不能很好的实现需求,比如使用lpad(rpad)函数进行补充的时候,有个长度的限制,这时候就影响了编码的正常使用。
在下面提供了一个公用的扩展性比较好的编码规则
1、创建编码的客户化表
-- Create table
create table CUX.CUX_DOC_SEQUENCES
(
doc_type VARCHAR2 (30 ),
pk1_value VARCHAR2 (50 ),
pk2_value VARCHAR2 (50 ),
pk3_value VARCHAR2 (50 ),
pk4_value VARCHAR2 (50 ),
pk5_value VARCHAR2 (50 ),
next_seq_number NUMBER ,
created_by NUMBER ,
creation_date DATE ,
last_updated_by NUMBER ,
last_update_date DATE ,
last_update_login NUMBER
)
tablespace APPS_TS_TX_DATA
pctfree 10
initrans 1
maxtrans 255
storage
(
initial 128 K
next 128 K
minextents 1
maxextents unlimited
pctincrease 0
);
-- Create/Recreate indexes
create unique index CUX.CUX_DOC_SEQUENCES_U1 on CUX.CUX_DOC_SEQUENCES (DOC_TYPE, PK1_VALUE, PK2_VALUE, PK3_VALUE, PK4_VALUE, PK5_VALUE)
tablespace APPS_TS_TX_IDX
pctfree 10
initrans 2
maxtrans 255
storage
(
initial 128 K
next 128 K
minextents 1
maxextents unlimited
pctincrease 0
);
2、定义生成编码的function
FUNCTION next_seq_number(p_doc_type IN VARCHAR2 ,
p_pk1_value IN VARCHAR2 DEFAULT NULL ,
p_pk2_value IN VARCHAR2 DEFAULT NULL ,
p_pk3_value IN VARCHAR2 DEFAULT NULL ,
p_pk4_value IN VARCHAR2 DEFAULT NULL ,
p_pk5_value IN VARCHAR2 DEFAULT NULL ,
p_init_number IN NUMBER DEFAULT 1 ) RETURN NUMBER IS
PRAGMA AUTONOMOUS_TRANSACTION ;
CURSOR c_seq IS
SELECT ds.rowid row_id, ds.next_seq_number
FROM cux_doc_sequences ds
WHERE ds.doc_type = p_doc_type
AND ds.pk1_value = nvl(p_pk1_value, '-1' )
AND ds.pk2_value = nvl(p_pk2_value, '-1' )
AND ds.pk3_value = nvl(p_pk3_value, '-1' )
AND ds.pk4_value = nvl(p_pk4_value, '-1' )
AND ds.pk5_value = nvl(p_pk5_value, '-1' )
FOR UPDATE NOWAIT;
l_row_id VARCHAR2 (18 );
l_next_seq_number NUMBER ;
BEGIN
OPEN c_seq;
FETCH c_seq
INTO l_row_id, l_next_seq_number;
IF c_seq%NOTFOUND THEN
l_next_seq_number := nvl(p_init_number, 1 );
INSERT INTO cux_doc_sequences
(doc_type,
pk1_value,
pk2_value,
pk3_value,
pk4_value,
pk5_value,
next_seq_number,
creation_date,
created_by,
last_update_date,
last_updated_by,
last_update_login)
VALUES
(p_doc_type,
nvl(p_pk1_value, '-1' ),
nvl(p_pk2_value, '-1' ),
nvl(p_pk3_value, '-1' ),
nvl(p_pk4_value, '-1' ),
nvl(p_pk5_value, '-1' ),
l_next_seq_number,
SYSDATE ,
fnd_global.user_id,
SYSDATE ,
fnd_global.user_id,
fnd_global.login_id);
ELSE
l_next_seq_number := l_next_seq_number + 1 ;
UPDATE cux_doc_sequences
SET next_seq_number = l_next_seq_number,
last_update_date = SYSDATE ,
last_updated_by = fnd_global.user_id,
last_update_login = fnd_global.login_id
WHERE ROWID = l_row_id;
END IF ;
CLOSE c_seq;
COMMIT ;
RETURN l_next_seq_number;
END next_seq_number;
FUNCTION next_seq_number(p_doc_type IN VARCHAR2 ,
p_doc_prefix IN VARCHAR2 ,
p_seq_length IN NUMBER DEFAULT 0 ,
p_pk1_value IN VARCHAR2 DEFAULT NULL ,
p_pk2_value IN VARCHAR2 DEFAULT NULL ,
p_pk3_value IN VARCHAR2 DEFAULT NULL ,
p_pk4_value IN VARCHAR2 DEFAULT NULL ,
p_pk5_value IN VARCHAR2 DEFAULT NULL ,
p_init_number IN NUMBER DEFAULT 1 ) RETURN VARCHAR2 IS
l_next_seq_number NUMBER ;
l_doc_number VARCHAR2 (150 );
BEGIN
l_next_seq_number := next_seq_number(p_doc_type => p_doc_type,
p_pk1_value => p_pk1_value,
p_pk2_value => p_pk2_value,
p_pk3_value => p_pk3_value,
p_pk4_value => p_pk4_value,
p_pk5_value => p_pk5_value,
p_init_number => p_init_number);
IF p_seq_length IS NULL OR p_seq_length = 0 THEN
l_doc_number := p_doc_prefix || l_next_seq_number;
ELSE
IF length(l_next_seq_number) >= p_seq_length THEN
l_doc_number := p_doc_prefix || l_next_seq_number;
ELSE
l_doc_number := p_doc_prefix ||
lpad(l_next_seq_number, p_seq_length, '0' );
END IF ;
END IF ;
RETURN l_doc_number;
END next_seq_number;
3、调用function生成编码
例子:
FUNCTION get_receipt_number(p_org_id IN NUMBER, p_receipt_date DATE )
RETURN VARCHAR2 IS
l_receipt_number VARCHAR2 (30 );
BEGIN
l_receipt_number := cux_doc_sequence_utl.next_seq_number(p_doc_type => 'POS_AR_RECEIPT_NUMBER' ,
p_doc_prefix => 'POS_' ||
to_char(p_receipt_date,
'YYYYMM' ),
p_seq_length => 5 ,
p_pk1_value => p_org_id,
p_pk2_value => to_char(p_receipt_date,
'YYYYMM' ));
RETURN l_receipt_number;
EXCEPTION
WHEN no_data_found THEN
RETURN NULL ;
cux_conc_utl.log_msg( 'FUNCTION get_receipt_number ERROR:' ||
'NO_DATA_FOUND' );
--RAISE fnd_api.g_exc_error;
WHEN too_many_rows THEN
RETURN NULL ;
cux_conc_utl.log_msg( 'FUNCTION get_receipt_number ERROR:' ||
'TOO_MANY_ROWS' );
--RAISE fnd_api.g_exc_error;
WHEN OTHERS THEN
RETURN NULL ;
cux_conc_utl.log_msg( 'FUNCTION get_receipt_number ERROR:' || SQLERRM );
--RAISE fnd_api.g_exc_error;
END get_receipt_number;