/* =============================================================== *
GET_PK:取得主键定义
说明:
如果返回NULL,表示这个表没有定义主键
* =============================================================== */
FUNCTION GET_PK(p_table CHAR) RETURN CHAR IS
CURSOR c_col(p_constraint CHAR) IS
SELECT COLUMN_NAME
FROM USER_CONS_COLUMNS
WHERE CONSTRAINT_NAME = p_constraint
ORDER BY POSITION;
v_constraint VARCHAR2(30);
v_pk VARCHAR2(60); --主键定义,字段间以逗号分割
BEGIN
/* 取主键名称 */
BEGIN
SELECT CONSTRAINT_NAME
INTO v_constraint
FROM USER_CONSTRAINTS
WHERE TABLE_NAME = UPPER(p_table) AND
CONSTRAINT_TYPE = 'P';
EXCEPTION
WHEN NO_DATA_FOUND THEN
RETURN NULL;
END;
/* 取出主键字段 */
v_pk := '';
FOR rec IN c_col(v_constraint) LOOP
v_pk := v_pk || rec.column_name || ',';
END LOOP;
v_pk := SUBSTR(v_pk,1,LENGTH(v_pk)-1);
RETURN v_pk;
END GET_PK;
/* =============================================================== *
EXIST_PK:判断主键是否已经存在
说明:
如果返回NULL,表示这个表没有定义主键
* =============================================================== */
FUNCTION EXIST_PK(p_table CHAR) RETURN BOOLEAN IS
v_constraint VARCHAR2(30);
v_count NUMBER(2);
BEGIN
/* 取主键名称 */
BEGIN
SELECT CONSTRAINT_NAME
INTO v_constraint
FROM USER_CONSTRAINTS
WHERE TABLE_NAME = UPPER(p_table) AND
CONSTRAINT_TYPE = 'P';
EXCEPTION
WHEN NO_DATA_FOUND THEN
RETURN NULL;
END;
/* 判断主键是否已经存在 */
SELECT COUNT(*)
INTO v_count
FROM USER_INDEXES
WHERE INDEX_NAME = v_constraint;
IF v_count = 0 THEN
RETURN FALSE;
ELSE
RETURN TRUE;
END IF;
END EXIST_PK;
/* =============================================================== *
ENABLE_PK:ENABLE主键
说明:
1.返回值含义:
-3:没有定义主键
-2:主键已经存在
-1:重建主键失败
0:建主键成功,没有重复记录
n(n>0):建主键成功,重复记录数为n
* =============================================================== */
FUNCTION ENABLE_PK(p_table CHAR,p_storage CHAR,p_exception CHAR)
RETURN NUMBER
IS
v_exist BOOLEAN;
v_SQL VARCHAR2(2000);
v_RowNum NUMBER(10);
v_return NUMBER(10);
v_pk VARCHAR2(60);
e_fail EXCEPTION;
PRAGMA EXCEPTION_INIT(e_fail,-2437);
v_Delete VARCHAR2(1000) :=
'DELETE #表名 WHERE ROWID IN(
SELECT ROW_ID FROM #异常表
WHERE TABLE_NAME = ''#表名''
MINUS
SELECT MIN(ROWID) FROM #表名
WHERE ROWID IN
(SELECT ROW_ID FROM #异常表
WHERE TABLE_NAME = ''#表名'')
GROUP BY #关键字 )';
BEGIN
/* 如果主键已经存在,那么返回 */
v_exist := EXIST_PK(p_table);
IF v_exist IS NULL THEN
RETURN -3;
ELSIF v_exist = TRUE THEN
RETURN -2;
END IF;
对付大数据量的表,有一种办法是:
alter table xx enable primary key xxxx
然后再用类似下列的语句删除:
DELETE #表名 WHERE ROWID IN(
SELECT ROW_ID FROM #异常表
WHERE TABLE_NAME = ''#表名''
MINUS
SELECT MIN(ROWID) FROM #表名
WHERE ROWID IN
(SELECT ROW_ID FROM #异常表
WHERE TABLE_NAME = ''#表名'')
GROUP BY #关键字 )