Стратегия снимать большой набор данных Oracle - PullRequest
0 голосов
/ 24 апреля 2020

Моя проблема:

У меня есть приложение и пользователи, которые входят в систему, имеют список авторизации отдела:

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

У большинства пользователей более 5000 отделов, назначенных для их профиля.

Мне поручено написать модель данных + код приложения, который будет «снимать» свой список авторизованных отделов каждый раз, когда пользователь входит в систему, чтобы мы могли ссылаться на то, что этому пользователю было разрешено делать (примечание: идентификаторы DEPT не являются аккуратно пронумерованы, как в этом примере).

То, что я пробовал:

Моей первой мыслью было преобразовать список отделов в длинную строку 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, который будет эффективным алгоритмом сопоставления, чтобы найти, если существует SECURITY_CONFIG_ID, который точно соответствует списку отделов.

Я даже не уверен, что существует эффективный способ решения этой проблемы.

Решение Попытка № 3:

Задайте переполнение стека. Что бы вы сделали?

1 Ответ

0 голосов
/ 24 апреля 2020

Мне удалось достичь стратегии № 1. Код приложения (Java) обрабатывал сравнение CLOB лучше, чем мой SQL клиент (DBeaver) с PreparedStatement:

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();
    ...
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...