Oracle-seqence(序列 ),手动序列

2018年11月22日 14:57 · 阅读(496) ·

[目录]

参考

ORACLE SEQUENCE 具体解释

Oracle 序列

什么是序列

数据库对象的一种。通过序列生成连续的数字以此来实现主键字段的自己主动、唯一增长,而且一个序列可为多列、多表同一时候使用。

创建一个简单序列

例子:

  1. --创建序列
  2. create sequence seq_test --创建一个序列
  3. minvalue 1 --最小值
  4. maxvalue 100000 --最大值
  5. start with 1 --指定序列起始数
  6. increment by 1 --指定序列增长步长
  7. cache 20 --指定数据库内存中预分配的序列值个数,以便高速获取。最小cache值为2

测试序列

  1. --测试序列
  2. select seq_test.nextval as 下一个值 from dual;
  3. select seq_test.currval as 当前值 from dual

创建语法说明

increment by:指定序列增长步长。能够为正(升序)、负整数(降序)。但不能为0。最高精度28。

start with: 指定序列起始数。默觉得序列最小值。

maxvalue :指定序列最大值。最大28位。必须大于等于起始值且大于等于序列最小值。

nomaxvalue 无最大值(实际为10^27或-1)。默认。

minvalue :指定序列最小值。

nominvalue :无最小值(实际为1或-10^26)。默认。

cycle :指定序列达到最大值或最小值后继续从头开始生成。带有cycle条件序列当达到最大值后,下一个值从最小值 minvalue 开始循环!

例子:

  1. create sequence seq_test --创建一个序列
  2. minvalue 1 --最小值
  3. maxvalue 100000 --最大值
  4. start with 1 --指定序列起始数
  5. increment by 1 --指定序列增长步长
  6. cycle --指定序列达到最大值或最小值后继续从头开始生成
  7. cache 20 --指定数据库内存中预分配的序列值个数,以便高速获取。最小cache值为2

nocycle :不循环生成。默认。

cache :指定数据库内存中预分配的序列值个数,以便高速获取。最小 cache 值为2。假设系统发生问题。全部缓存的没有被 DML 语句使用并提交的序列值将丢失。潜在丢失值数量等于 cache 的数量。cache 参数最大值为:(cell(maxvalue - minvalue)) / abs(increment)

nocache :不指定缓存数,默认缓存20。

order :指定 order 条件保证序列按请求顺序生成。

此条件适用于 rac 环境。

noorder :不保证序列按请求顺序生成。

授权序列

  1. grant select on seq_test to luoma with grant option;
  2. grant select on seq_test to luoma;

修改语法说明

语法说明:

1.想以不同的数字又一次开始序列,必须删除重建

例如上面创建的例子中的序列修改为 55:

  1. alter sequence seq_test start with 55 --修改序列起始数

执行提示:

  1. ORA-02293:无法变更启动序列号

2.改动的 maxvalue 必须大于序列当前值

例如:

  1. alter sequence seq_test maxvalue 1 --修改序列最大值

执行提示:

  1. ORA-04004:MINVALUE 必须小于 MAXVALUE

删除语法说明

例子:

  1. drop sequence seq_test--删除序列

手动序列

案例:客户化系统单据序列操作的 API

序列对应表-COMMON_DOC_SEQUENCES

  1. -- Create table
  2. create table COMMON_DOC_SEQUENCES
  3. (
  4. doc_type VARCHAR2(45) not null,
  5. pk1_value VARCHAR2(50) not null,
  6. pk2_value VARCHAR2(50),
  7. pk3_value VARCHAR2(50),
  8. pk4_value VARCHAR2(75),
  9. pk5_value VARCHAR2(50),
  10. next_seq_number NUMBER,
  11. created_by NUMBER not null,
  12. creation_date DATE not null,
  13. last_updated_by NUMBER not null,
  14. last_update_date DATE not null,
  15. last_update_login NUMBER
  16. );
  17. -- Create/Recreate indexes
  18. create unique index COMMON_DOC_SEQUENCES_N1 on COMMON_DOC_SEQUENCES (DOC_TYPE, PK1_VALUE, PK2_VALUE, PK3_VALUE, PK4_VALUE, PK5_VALUE);

序列对应包

  1. CREATE OR REPLACE PACKAGE "COMMON_DOC_SEQUENCE_UTL" AS
  2. /*==================================================
  3. Program Name:
  4. COMMON_DOC_SEQUENCE_UTL
  5. Description:
  6. 该程序包提供客户化系统单据序列操作的 API
  7. History:
  8. ==================================================*/
  9. /*==================================================
  10. Function Name :
  11. next_seq_number
  12. Description:
  13. 获取下一个单据号
  14. Argument:
  15. p_doc_type : 单据类型
  16. p_pk1_value : 主关键字1
  17. p_pk2_value : 主关键字2
  18. p_pk3_value : 主关键字3
  19. p_pk4_value : 主关键字4
  20. p_pk5_value : 主关键字5
  21. p_init_number : 初始序列号
  22. Return:
  23. NUMBER : 返回单据号序列
  24. History:
  25. ==================================================*/
  26. FUNCTION next_seq_number
  27. (
  28. p_doc_type IN VARCHAR2,
  29. p_pk1_value IN VARCHAR2 DEFAULT NULL,
  30. p_pk2_value IN VARCHAR2 DEFAULT NULL,
  31. p_pk3_value IN VARCHAR2 DEFAULT NULL,
  32. p_pk4_value IN VARCHAR2 DEFAULT NULL,
  33. p_pk5_value IN VARCHAR2 DEFAULT NULL,
  34. p_init_number IN NUMBER DEFAULT 1
  35. ) RETURN NUMBER;
  36. /*==================================================
  37. Function Name :
  38. next_seq_number
  39. Description:
  40. 获取下一个单据号
  41. Argument:
  42. p_doc_type : 单据类型
  43. p_doc_prefix :前缀
  44. p_seq_length : 长度
  45. p_pk1_value : 主关键字1
  46. p_pk2_value : 主关键字2
  47. p_pk3_value : 主关键字3
  48. p_pk4_value : 主关键字4
  49. p_pk5_value : 主关键字5
  50. p_init_number : 初始序列号
  51. Return:
  52. VARCHAR2 : 返回单据号
  53. History:
  54. ==================================================*/
  55. FUNCTION next_seq_number
  56. (
  57. p_doc_type IN VARCHAR2,
  58. p_doc_prefix IN VARCHAR2,
  59. p_seq_length IN NUMBER DEFAULT 0,
  60. p_pk1_value IN VARCHAR2 DEFAULT NULL,
  61. p_pk2_value IN VARCHAR2 DEFAULT NULL,
  62. p_pk3_value IN VARCHAR2 DEFAULT NULL,
  63. p_pk4_value IN VARCHAR2 DEFAULT NULL,
  64. p_pk5_value IN VARCHAR2 DEFAULT NULL,
  65. p_init_number IN NUMBER DEFAULT 1
  66. ) RETURN VARCHAR2;
  67. /*==================================================
  68. Function Name :
  69. next_seq_number
  70. Description:
  71. 获取当前单据号
  72. Argument:
  73. p_doc_type : 单据类型
  74. p_doc_prefix :前缀
  75. p_seq_length : 长度
  76. p_pk1_value : 主关键字1
  77. p_pk2_value : 主关键字2
  78. p_pk3_value : 主关键字3
  79. p_pk4_value : 主关键字4
  80. p_pk5_value : 主关键字5
  81. p_init_number : 初始序列号
  82. Return:
  83. VARCHAR2 : 返回单据号
  84. History:
  85. ==================================================*/
  86. FUNCTION curr_seq_number
  87. (
  88. p_doc_type IN VARCHAR2,
  89. p_doc_prefix IN VARCHAR2,
  90. p_seq_length IN NUMBER DEFAULT 0,
  91. p_pk1_value IN VARCHAR2 DEFAULT NULL,
  92. p_pk2_value IN VARCHAR2 DEFAULT NULL,
  93. p_pk3_value IN VARCHAR2 DEFAULT NULL,
  94. p_pk4_value IN VARCHAR2 DEFAULT NULL,
  95. p_pk5_value IN VARCHAR2 DEFAULT NULL,
  96. p_init_number IN NUMBER DEFAULT 1
  97. ) RETURN VARCHAR2;
  98. END COMMON_DOC_SEQUENCE_UTL;
  99. /
  100. CREATE OR REPLACE PACKAGE BODY "COMMON_DOC_SEQUENCE_UTL" AS
  101. /*==================================================
  102. Program Name:
  103. COMMON
  104. Description:
  105. 该程序包提供客户化系统单据序列操作的API
  106. History:
  107. ==================================================*/
  108. FUNCTION next_seq_number
  109. (
  110. p_doc_type IN VARCHAR2,
  111. p_pk1_value IN VARCHAR2 DEFAULT NULL,
  112. p_pk2_value IN VARCHAR2 DEFAULT NULL,
  113. p_pk3_value IN VARCHAR2 DEFAULT NULL,
  114. p_pk4_value IN VARCHAR2 DEFAULT NULL,
  115. p_pk5_value IN VARCHAR2 DEFAULT NULL,
  116. p_init_number IN NUMBER DEFAULT 1
  117. ) RETURN NUMBER IS
  118. PRAGMA AUTONOMOUS_TRANSACTION;
  119. l_doc_type VARCHAR2(30);
  120. CURSOR c_seq_del IS
  121. SELECT *
  122. FROM (SELECT ds.rowid row_id
  123. ,ds.next_seq_number
  124. FROM COMMON_DOC_SEQUENCES ds
  125. WHERE ds.doc_type = l_doc_type
  126. AND ds.pk1_value = nvl(p_pk1_value, '-1')
  127. AND ds.pk2_value = nvl(p_pk2_value, '-1')
  128. AND ds.pk3_value = nvl(p_pk3_value, '-1')
  129. AND ds.pk4_value = nvl(p_pk4_value, '-1')
  130. AND ds.pk5_value = nvl(p_pk5_value, '-1')
  131. ORDER BY ds.next_seq_number) tt
  132. WHERE rownum = 1;
  133. CURSOR c_seq IS
  134. SELECT ds.rowid row_id
  135. ,ds.next_seq_number
  136. FROM COMMON_DOC_SEQUENCES ds
  137. WHERE ds.doc_type = p_doc_type
  138. AND ds.pk1_value = nvl(p_pk1_value, '-1')
  139. AND ds.pk2_value = nvl(p_pk2_value, '-1')
  140. AND ds.pk3_value = nvl(p_pk3_value, '-1')
  141. AND ds.pk4_value = nvl(p_pk4_value, '-1')
  142. AND ds.pk5_value = nvl(p_pk5_value, '-1')
  143. FOR UPDATE; -- NOWAIT;
  144. l_row_id VARCHAR2(18);
  145. l_next_seq_number NUMBER;
  146. BEGIN
  147. l_doc_type := p_doc_type || 'DEL';
  148. --先看是否存在删除的数据
  149. OPEN c_seq_del;
  150. FETCH c_seq_del
  151. INTO l_row_id
  152. ,l_next_seq_number;
  153. IF c_seq_del%NOTFOUND THEN
  154. --不存在断号
  155. OPEN c_seq;
  156. FETCH c_seq
  157. INTO l_row_id
  158. ,l_next_seq_number;
  159. IF c_seq%NOTFOUND THEN
  160. l_next_seq_number := nvl(p_init_number, 1);
  161. INSERT INTO COMMON_DOC_SEQUENCES
  162. (doc_type
  163. ,pk1_value
  164. ,pk2_value
  165. ,pk3_value
  166. ,pk4_value
  167. ,pk5_value
  168. ,next_seq_number
  169. ,creation_date
  170. ,created_by
  171. ,last_update_date
  172. ,last_updated_by
  173. ,last_update_login)
  174. VALUES
  175. (p_doc_type
  176. ,nvl(p_pk1_value, '-1')
  177. ,nvl(p_pk2_value, '-1')
  178. ,nvl(p_pk3_value, '-1')
  179. ,nvl(p_pk4_value, '-1')
  180. ,nvl(p_pk5_value, '-1')
  181. ,l_next_seq_number
  182. ,SYSDATE
  183. ,1
  184. ,SYSDATE
  185. ,1
  186. ,1);
  187. ELSE
  188. l_next_seq_number := l_next_seq_number + 1;
  189. UPDATE COMMON_DOC_SEQUENCES
  190. SET next_seq_number = l_next_seq_number,
  191. last_update_date = SYSDATE,
  192. last_updated_by = 1,
  193. last_update_login = 1
  194. WHERE ROWID = l_row_id;
  195. END IF;
  196. CLOSE c_seq;
  197. ELSE
  198. --用删除掉的编号
  199. DELETE FROM COMMON_DOC_SEQUENCES WHERE ROWID = l_row_id;
  200. END IF;
  201. COMMIT;
  202. RETURN l_next_seq_number;
  203. END next_seq_number;
  204. FUNCTION next_seq_number
  205. (
  206. p_doc_type IN VARCHAR2,
  207. p_doc_prefix IN VARCHAR2,
  208. p_seq_length IN NUMBER DEFAULT 0,
  209. p_pk1_value IN VARCHAR2 DEFAULT NULL,
  210. p_pk2_value IN VARCHAR2 DEFAULT NULL,
  211. p_pk3_value IN VARCHAR2 DEFAULT NULL,
  212. p_pk4_value IN VARCHAR2 DEFAULT NULL,
  213. p_pk5_value IN VARCHAR2 DEFAULT NULL,
  214. p_init_number IN NUMBER DEFAULT 1
  215. ) RETURN VARCHAR2 IS
  216. l_next_seq_number NUMBER;
  217. l_doc_number VARCHAR2(150);
  218. BEGIN
  219. l_next_seq_number := next_seq_number(p_doc_type => p_doc_type,
  220. p_pk1_value => p_pk1_value,
  221. p_pk2_value => p_pk2_value,
  222. p_pk3_value => p_pk3_value,
  223. p_pk4_value => p_pk4_value,
  224. p_pk5_value => p_pk5_value,
  225. p_init_number => p_init_number);
  226. IF p_seq_length IS NULL OR p_seq_length = 0 THEN
  227. l_doc_number := p_doc_prefix || l_next_seq_number;
  228. ELSE
  229. IF length(l_next_seq_number) >= p_seq_length THEN
  230. l_doc_number := p_doc_prefix || l_next_seq_number;
  231. ELSE
  232. l_doc_number := p_doc_prefix || lpad(l_next_seq_number, p_seq_length, '0');
  233. END IF;
  234. END IF;
  235. RETURN l_doc_number;
  236. END next_seq_number;
  237. FUNCTION curr_seq_number
  238. (
  239. p_doc_type IN VARCHAR2,
  240. p_doc_prefix IN VARCHAR2,
  241. p_seq_length IN NUMBER DEFAULT 0,
  242. p_pk1_value IN VARCHAR2 DEFAULT NULL,
  243. p_pk2_value IN VARCHAR2 DEFAULT NULL,
  244. p_pk3_value IN VARCHAR2 DEFAULT NULL,
  245. p_pk4_value IN VARCHAR2 DEFAULT NULL,
  246. p_pk5_value IN VARCHAR2 DEFAULT NULL,
  247. p_init_number IN NUMBER DEFAULT 1
  248. ) RETURN VARCHAR2 IS
  249. PRAGMA AUTONOMOUS_TRANSACTION;
  250. CURSOR c_seq IS
  251. SELECT ds.rowid row_id
  252. ,ds.next_seq_number
  253. FROM COMMON_DOC_SEQUENCES ds
  254. WHERE ds.doc_type = p_doc_type
  255. AND ds.pk1_value = nvl(p_pk1_value, '-1')
  256. AND ds.pk2_value = nvl(p_pk2_value, '-1')
  257. AND ds.pk3_value = nvl(p_pk3_value, '-1')
  258. AND ds.pk4_value = nvl(p_pk4_value, '-1')
  259. AND ds.pk5_value = nvl(p_pk5_value, '-1')
  260. FOR UPDATE; -- NOWAIT;
  261. l_row_id VARCHAR2(18);
  262. l_next_seq_number NUMBER;
  263. BEGIN
  264. OPEN c_seq;
  265. FETCH c_seq
  266. INTO l_row_id
  267. ,l_next_seq_number;
  268. IF c_seq%NOTFOUND THEN
  269. l_next_seq_number := next_seq_number(p_doc_type => p_doc_type,
  270. p_doc_prefix => NULL,
  271. p_seq_length => p_seq_length,
  272. p_pk1_value => p_pk1_value,
  273. p_pk2_value => NULL,
  274. p_pk3_value => NULL,
  275. p_pk4_value => NULL,
  276. p_pk5_value => NULL,
  277. p_init_number => 1);
  278. INSERT INTO COMMON_DOC_SEQUENCES
  279. (doc_type
  280. ,pk1_value
  281. ,pk2_value
  282. ,pk3_value
  283. ,pk4_value
  284. ,pk5_value
  285. ,next_seq_number
  286. ,creation_date
  287. ,created_by
  288. ,last_update_date
  289. ,last_updated_by
  290. ,last_update_login)
  291. VALUES
  292. (p_doc_type
  293. ,nvl(p_pk1_value, '-1')
  294. ,nvl(p_pk2_value, '-1')
  295. ,nvl(p_pk3_value, '-1')
  296. ,nvl(p_pk4_value, '-1')
  297. ,nvl(p_pk5_value, '-1')
  298. ,l_next_seq_number
  299. ,SYSDATE
  300. ,1
  301. ,SYSDATE
  302. ,1
  303. ,1);
  304. END IF;
  305. IF p_seq_length IS NULL OR p_seq_length = 0 THEN
  306. l_next_seq_number := p_doc_prefix || l_next_seq_number;
  307. ELSE
  308. IF length(l_next_seq_number) >= p_seq_length THEN
  309. l_next_seq_number := p_doc_prefix || l_next_seq_number;
  310. ELSE
  311. l_next_seq_number := p_doc_prefix || lpad(l_next_seq_number, p_seq_length, '0');
  312. END IF;
  313. END IF;
  314. CLOSE c_seq;
  315. COMMIT;
  316. RETURN l_next_seq_number;
  317. END curr_seq_number;
  318. END COMMON_DOC_SEQUENCE_UTL;
  319. /

使用案例

  1. --流水号获取
  2. declare
  3. var_no number;
  4. var_no_str varchar2(100);
  5. begin
  6. --单独的号码
  7. var_no := COMMON_DOC_SEQUENCE_UTL.next_seq_number('PAYMENT_WRITE_OFF','BATCHID-INVOICE_NO_NUMBER','','','','',1);
  8. dbms_output.put_line(var_no);
  9. --带数量的前缀
  10. var_no_str := COMMON_DOC_SEQUENCE_UTL.next_seq_number('PAYMENT_WRITE_OFF','-',3,'BATCHID-SAVEPREPAYAPPLYDATA','','','','',1);
  11. dbms_output.put_line(var_no_str);
  12. end;

第一次调用

  1. 1
  2. -001

第二次调用

  1. 2
  2. -002

查询生成结果

  1. --验证
  2. select t.*,t.rowid
  3. from common_doc_sequences t
  4. where doc_type = 'PAYMENT_WRITE_OFF'

手动序列-根据表总数据生成

手动序列-根据表总数据生成