对大型数据集Oracle进行快照的策略

问题描述 投票:0回答:1

我的问题:

我有一个应用程序,登录的用户有部门授权列表:

DEPT1, DEPT2, DEPT3, ..., DEPT5000, DEPT5001, ...

大多数用户为自己的个人资料分配了5,000多个部门。

我的任务是编写一个数据模型+应用程序代码,该代码将在用户每次登录时“快照”其授权部门的列表,以便我们可以参考该用户被授权执行的操作(注意:DEPT ID不是整齐地编号(如本例所示)。

我尝试过的:

我首先想到的是将部门列表转换为长CSV字符串并将其存储为CLOB:

CREATE TABLE UI_SECURITY_CONFIG (
    SECURITY_CONFIG_ID NUMBER(19,0) NOT NULL,
    DEPTSCSV CLOB NOT NULL
);

并且每个DEPTSCSV CLOB都是唯一的。如果用户具有与以前登录的其他用户相同的安全配置文件,则只需选择该安全配置。否则,它将创建一个新行。基本上,选择DEPTSCSV ='DEPT1,DEPT2,DEPT3 ...',如果不存在,则将其插入。但是这种方法失败了,因为一个巨大的字符串(超过25,000个字符)是不可比的:

SELECT * FROM UI_SECURITY_CONFIG WHERE DEPTSCSV = 'DEPT0001, DEPT0002, DEPT0003, ..., DEPT5001, DEPT5002'

SQL Error [1704] [42000]: ORA-01704: string literal too long

解决方案尝试2:

因此,我想到了将CSV中的每个项目都做成表格中自己的行:

CREATE TABLE UI_SECURITY_CONFIG (
    SECURITY_CONFIG_ID NUMBER(19,0) NOT NULL,
    DEPTID VARCHAR2(20) NOT NULL
);

INSERT INTO UI_SECURITY_CONFIG(SECURITY_CONFIG_ID, DEPTID) VALUES(1, 'DEPT0001');
INSERT INTO UI_SECURITY_CONFIG(SECURITY_CONFIG_ID, DEPTID) VALUES(1, 'DEPT0002');
INSERT INTO UI_SECURITY_CONFIG(SECURITY_CONFIG_ID, DEPTID) VALUES(1, 'DEPT0003');
...
INSERT INTO UI_SECURITY_CONFIG(SECURITY_CONFIG_ID, DEPTID) VALUES(1, 'DEPT5001');
INSERT INTO UI_SECURITY_CONFIG(SECURITY_CONFIG_ID, DEPTID) VALUES(1, 'DEPT5002');

但是我正在努力编写SQL select,这将是一种有效的匹配算法,以查找是否存在与Departments列表完全匹配的SECURITY_CONFIG_ID。

我什至不确定是否有解决此问题的有效方法。

解决方案尝试3:

询问堆栈溢出。你会怎么做?

oracle data-modeling datamodel
1个回答
0
投票

我能够实现策略1。与PreparedStatement相比,应用程序代码(Java)比我的SQL客户端(DBeaver)处理CLOB比较更好:

String sql = "SELECT SECURITY_CONFIG_ID FROM UI_SECURITY_CONFIG WHERE dbms_lob.compare(DEPTSCSV, ?) = 0";

String DEPTSCSV = "DEPT0001, DEPT0002, ...";

try(PreparedStatement objStmt = objConn.prepareStatement(sql)) {
    Clob clob1 = objConn.createClob();
    clob1.setString(1, DEPTSCSV);
    objStmt.setClob(1, clob1);

    ResultSet result = objStmt.executeQuery();
    ...
}
© www.soinside.com 2019 - 2024. All rights reserved.