Ora 24381 ошибка и в массиве dml

“Oops! Something went wrong” seems to be the fashionable thing to do when throwing errors these days. Not surprisingly, when issuing a query from PowerShell against Oracle, it kept producing this error at random

ORA-24381: error(s) in array DML

The error did not always happen. It only happened once in a while and it was always on this statement:

SELECT NVL(MAX(USERNAME),'NOT_THERE') as usr1
FROM DBA_USERS
WHERE USERNAME = 'AN_USER_ID'

The error gave me no clue about what the underlying issue is and more importantly I had no idea why it was so random. The complete error is below:

System.Management.Automation.MethodInvocationException: Exception calling “Fill” with “1” argument(s): “ORA-24381: error(s) in array DML”
—> Oracle.DataAccess.Client.OracleException: ORA-24381: error(s) in array DML
at Oracle.DataAccess.Client.OracleException.HandleErrorHelper(Int32 errCode, OracleConnection conn, IntPtr opsErrCtx, OpoSqlValCtx* pOpoSqlValCtx, Object src, String procedure, Boolean bCheck)
at Oracle.DataAccess.Client.OracleCommand.ExecuteReader(Boolean requery, Boolean fillRequest, CommandBehavior behavior)
at Oracle.DataAccess.Client.OracleDataAdapter.Fill(DataTable[] dataTables, Int32 startRecord, Int32 maxRecords, IDbCommand command, CommandBehavior behavior)
at System.Data.Common.DbDataAdapter.Fill(DataTable dataTable)
at CallSite.Target(Closure , CallSite , Object , Object )
— End of inner exception stack trace —
at System.Management.Automation.ExceptionHandlingOps.CheckActionPreference(FunctionContext funcContext, Exception exception)
at System.Management.Automation.Interpreter.ActionCallInstruction`2.Run(InterpretedFrame frame)
at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)

As one can see from the error message, I do use the Oracle-provided ODP.NET OLEDB drivers and not the Microsoft provider for Oracle. No amount of frantic Googling helped although the issue seemed to have a theme. The theme was that this error happened to others when the data would not fit into the target usually when doing BULK INSERT. In my case, I was just doing a simple SELECT.

Solution: CAST to length

In any case, without beating around the bush, I figured that my problem had to do Oracle’s bad estimation of the string length (that led to the issue). So, I forced a CAST to limit the string to 30 characters and the issue went away!

SELECT NVL(MAX(USERNAME),
           CAST('NOT_THERE' AS VARCHAR2(30))
          ) as usr1
FROM DBA_USERS
WHERE USERNAME = 'AN_USER_ID'

In your case, the problem might be a similar data length issue and you might be able to resolve it too with a simple cast. I hope that this post helps you. Good luck!

Краткие итоги

Входной массив

Может быть и PL/SQL массивом и Nested Table.
Три метода перебора элементов
1.Указание интервала индексов

forall i in l_col.first .. l_col.last
forall i in 1 .. 10
-- В этом случае индексы округлятся
forall i in 1.3 .. 2.4


В этом случае нельзя работать с коллекциями с дырками (удаленными элементами)

2. INDICES OF

FORALL i IN INDICES OF l_t
FORALL i IN INDICES OF l_t BETWEEN 1 AND 1

Позволяет  работать с коллекцияями с дырками. Можно ограничить интервал
3. VALUES OF

FORALL i IN VALUES OF l_tsubscripts

В одной коллекции храним индексы (PLS_INTEGER или BINARY_INTEGER) от рабочей коллекции. Если указанного элемента в рабочей коллекции нет — будет ошибка. Индексы могут храниться как в PL/SQL так и в Nested массиве.

Обработка ошибок

Если на одном из элементов коллекции проиисходит иисключение, то транзакцияя сохранит все предыдущие успешные операции.

Можно использовать конструкцию SAVE EXCEPTION. В этом случае операция дойдет до конца и, если при выполнении встретились ошибки, будет сгенерировано исключение ORA-24381: error(s) in array DML. Для обработки ошибок можно использовать массив SQL%BULK_EXCEPTIONS

SQL%BULK_EXCEPTIONS

1. Нумерация всегда с 1. Чаще всего для обработки будет использоваться
FOR err IN 1 .. SQL%BULK_EXCEPTIONS.COUNT LOOP
2. SQL%BULK_EXCEPTIONS(err).ERROR_INDEX — номер итерации. Если массив неразряженный и начинается с 1 — то получить входные данные, вызвавшие ошибку очень просто. В остальных случаях придется яотсчитывать в цикле

3. SQL%BULK_EXCEPTIONS(err).ERROR_CODE — код ошибки

4. SQLERRM(-SQL%BULK_EXCEPTIONS(err).ERROR_CODE) — сообщение об ошибке

SQL%BULK_ROWCOUNT

Массив, который хранит в себе сколько строк было обработано на каждой итерации. Массив индексируется индексами от рабочего массива, т.е. если в рабочем массиве элементы со 2-го по 5-й, то и в SQL%BULK_ROWCOUNT будут 2, 3, 4, 5

Пример кода


DROP TABLE a;
CREATE TABLE a (a NUMBER CHECK (a > 0));

DECLARE
l_cnt NUMBER;

TYPE t IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;
l_t t;

TYPE t_nest IS TABLE OF NUMBER;
l_tn t_nest := t_nest();

-- suscript -- только PLS_INTEGER and BINARY_INTEGER
TYPE t_subscripts IS TABLE OF PLS_INTEGER;
l_tsubscripts t_subscripts := t_subscripts();

TYPE t_subscripts2 IS TABLE OF PLS_INTEGER index by pls_integer;
l_tsubscripts2 t_subscripts2;

BEGIN
l_t(1) := 1;
l_t(3) := 3;
-- ora-22160 -- коллекция разряженная
BEGIN
FORALL i IN l_t.first .. l_t.last
INSERT INTO a VALUES (l_t(i));
dbms_output.put_line('Should be 0');
EXCEPTION WHEN OTHERS THEN
dbms_output.put_line('Error: ' || SQLCODE || ' - ' || SQLERRM);
END;

-- можно использовать indices of
FORALL i IN INDICES OF l_t
INSERT INTO a VALUES (l_t(i));
dbms_output.put_line('Row count: ' || SQL%ROWCOUNT);

-- можно использовать indices of
FORALL i IN INDICES OF l_t BETWEEN 1 AND 1
INSERT INTO a VALUES (l_t(i));
dbms_output.put_line('Indices of with lower and upper bound Row count: ' || SQL%ROWCOUNT);

-- Аналогично работает с nested tables
l_tn.EXTEND(3);
l_tn(1) := 1;
l_tn(2) := 2;
l_tn(3) := 3;
l_tn.delete(2);
BEGIN
FORALL i IN l_tn.first .. l_tn.last
INSERT INTO a VALUES (l_tn(i));
dbms_output.put_line('Should be 0');
EXCEPTION WHEN OTHERS THEN
dbms_output.put_line('Nested tables Error: ' || SQLCODE || ' - ' || SQLERRM);
END;

FORALL i IN INDICES OF l_tn
INSERT INTO a VALUES (l_tn(i));
dbms_output.put_line('Nested Row count: ' || SQL%ROWCOUNT);

-- values of
l_tsubscripts.EXTEND(1);
l_tsubscripts(1) := 3;

-- При использованиии values of + nested table коллекция должна начинаться с 1
BEGIN
FORALL i IN VALUES OF l_tsubscripts
INSERT INTO a VALUES (l_tn(i));
dbms_output.put_line('values of + nested table Row count: ' || SQL%ROWCOUNT);
EXCEPTION WHEN OTHERS THEN
dbms_output.put_line('values of + nested table Error: ' || SQLCODE || ' - ' || SQLERRM);
END;

-- При использованиии values of + pl/sql массивы коллекция может быть какая угодно
l_tsubscripts2(1000) := 3;
BEGIN
FORALL i IN VALUES OF l_tsubscripts2
INSERT INTO a VALUES (l_tn(i));
dbms_output.put_line('Values of Row count: ' || SQL%ROWCOUNT);
EXCEPTION WHEN OTHERS THEN
dbms_output.put_line('Error: ' || SQLCODE || ' - ' || SQLERRM);
END;

-- Нет элемента -- это ошибка
l_tsubscripts2(1000) := 3;
l_tsubscripts2(1001) := 10;
BEGIN
FORALL i IN VALUES OF l_tsubscripts2
INSERT INTO a VALUES (l_tn(i));
dbms_output.put_line('Values of Row count: ' || SQL%ROWCOUNT);
EXCEPTION WHEN OTHERS THEN
dbms_output.put_line('No element Error: ' || SQLCODE || ' - ' || SQLERRM);
END;
l_t.delete;
l_t(1) := 1;
l_t(2) := 2;
l_t(3) := 3;
-- Границы округляются до ближайшего целого
FORALL i IN 1.3 .. 2.4
INSERT INTO a VALUES (l_t(i));
dbms_output.put_line('bounds rounded Row count: ' || SQL%ROWCOUNT);

-- SAVE EXCEPTION
-- Если не все гладко, то рейсит ошибку ORA-24381
-- Далее разбираемся с SQL%BULK_EXCEPTIONS
l_t.delete;
l_t(1) := 1;
l_t(2) := 2;
l_t(3) := 3;
l_t(4) := -4;
l_t.delete(2);
BEGIN
FORALL i IN 1 .. 4 SAVE EXCEPTIONS
INSERT INTO a VALUES (l_t(i));
dbms_output.put_line('With save exception Row count: ' || SQL%ROWCOUNT);
EXCEPTION WHEN OTHERS THEN
dbms_output.put_line('Error: ' || SQLCODE || ' - ' || SQLERRM);
FOR err IN 1 .. SQL%BULK_EXCEPTIONS.COUNT LOOP
dbms_output.put_line('Row ' || err || ' iteration ' || SQL%BULK_EXCEPTIONS(err).ERROR_INDEX
|| ' code ' || SQL%BULK_EXCEPTIONS(err).ERROR_CODE
|| ' message: ' || SQLERRM(-SQL%BULK_EXCEPTIONS(err).ERROR_CODE));
END LOOP;
END;

-- SAVE EXCEPTION для разряженных коллекций с INDICES OF
l_t.delete;
l_t(10) := 1;
l_t(20) := 2;
l_t(30) := -3;
BEGIN
FORALL i IN INDICES OF l_t SAVE EXCEPTIONS
INSERT INTO a VALUES (l_t(i));
dbms_output.put_line('With save exception indices of Row count: ' || SQL%ROWCOUNT);
EXCEPTION WHEN OTHERS THEN
dbms_output.put_line('indices of Error: ' || SQLCODE || ' - ' || SQLERRM);
FOR err IN 1 .. SQL%BULK_EXCEPTIONS.COUNT LOOP
dbms_output.put_line('indices of Row ' || err || ' iteration ' || SQL%BULK_EXCEPTIONS(err).ERROR_INDEX
|| ' code ' || SQL%BULK_EXCEPTIONS(err).ERROR_CODE
|| ' message: ' || SQLERRM(-SQL%BULK_EXCEPTIONS(err).ERROR_CODE));
END LOOP;
END;

ROLLBACK;

-- при ошибке все предыдущие операции остаются
l_t.delete;
l_t(1) := 1;
l_t(2) := -1;
BEGIN
FORALL i IN 1 .. 2
INSERT INTO a VALUES (l_t(i));
EXCEPTION WHEN OTHERS THEN
dbms_output.put_line('insert with error Row count: ' || SQL%ROWCOUNT);
SELECT COUNT(*) INTO l_cnt FROM a;
dbms_output.put_line('insert with error rows in table ' || l_cnt);
END;

-- использование SQL%BULK_ROWCOUNT
ROLLBACK;
l_t.delete;
l_t(1) := 1;
l_t(2) := 1;
FORALL i IN 1 .. 2
INSERT INTO a VALUES (l_t(i));

-- Индекс в BULK_ROWCOUNT совпадает с тем, что мы обрабатывали
FORALL i IN 2 .. 2
UPDATE a SET a = l_t(i) WHERE a = l_t(i);
dbms_output.put_line('Updated SQL%BULK_ROWCOUNT=' || SQL%BULK_ROWCOUNT(2));

END;
/

1、table create sql:

CREATE TABLE «COMM_APG_TEST».»GOORA_TEMP_VISIT»
( «VISIT_ID» NUMBER(10,0) NOT NULL ENABLE,
«NAME» VARCHAR2(200),
«VAL» NUMBER(10,2),
«VISIT_DATE» DATE,
«MAJOR» VARCHAR2(100)
)

2、code:

sqlText := INSERT INTO GOORA_TEMP_VISIT(VISIT_ID, NAME, VAL, VISIT_DATE, MAJOR) VALUES(:1, :2, :3, :4, :5)
rowNum := 2
visitID := make([]driver.Value, rowNum)
nameText := make([]driver.Value, rowNum)
val := make([]driver.Value, rowNum)
date := make([]driver.Value, rowNum)
major := make([]driver.Value, rowNum)
initalVal := 1.1
for index := 0; index < rowNum; index++ {
visitID[index] = (int64)(index + 1)
if index == 0 {
nameText[index] = «M130201_01»
} else {
nameText[index] = «S170101_01»
}
val[index] = initalVal
date[index] = time.Now().AddDate(0, index, 0)
initalVal += 1.1
if index == 0 {
major[index] = «M-13» <==========
} else {
major[index] = «SP-17» <==========
}
//if index%5 == 0 {
// _, err = stmt.Exec(index, nameText, val, nil)
//} else {
// _, err = stmt.Exec(index, nameText, val, time.Now())
//}
//if err != nil {
// return err
//}
//val += 1.1
}
result, err := conn.BulkInsert(sqlText, rowNum, visitID, nameText, val, date, major)
if err != nil {
return err
}

3、err returned by code snippet witch in «func (session *Session) readPacket() (PacketInterface, error) {«

for loop {
msg, err := session.GetByte()
if err != nil {
return nil, err
}
switch msg {
case 4:
loop = false
session.Summary, err = NewSummary(session)
if err != nil {
return nil, err
}
if session.HasError() {
return nil, session.GetError() <=======
}

4、bulk insert success when i replace the value of field to …

if index == 0 {
major[index] = «M-13» <==========
} else {
major[index] = «S-17» <==========
}

I faced this error Error message: ORA-24381: error(s) in array DML in doing insert operation. There is no exception handling involved in the sql. Can I know now the root cause for this through any view ?

My database is oracle 12c

asked Feb 16, 2020 at 2:43

EXODIA's user avatar

1

Check if this is similar to this article

I figured that my problem had to do Oracle’s bad estimation of the string length (that led to the issue).
So, I forced a CAST to limit the string to 30 characters and the issue went away!

SELECT NVL(MAX(USERNAME),
           CAST('NOT_THERE' AS VARCHAR2(30))
          ) as usr1
FROM DBA_USERS
WHERE USERNAME = 'AN_USER_ID'

In your case, the problem might be a similar data length issue and you might be able to resolve it too with a simple cast.

answered Feb 16, 2020 at 2:58

VonC's user avatar

VonCVonC

1.2m519 gold badges4346 silver badges5164 bronze badges

2

Hi,

While running the job, I’ve the below error msg. Can anyone help in resolving this..

Employees,0: The OCI function OCIStmtExecute returned status 1. Error code: 1400, Error message: ORA-01400: cannot insert NULL into (""SCH"".""EMPLOYEES"".""EMP_ID"").
Employees,0: The following SQL statement failed: INSERT INTO atmosphere.projects(EMP_ID,EMP_NAME,EMP_STATUS,EMP_PHASE,FUN,COST,EMP_TYPE,EMP_TYPE1,NEW_FLAG,CHANGE_FLAG,NO_FLAG,EMP_TRACKING_FLAG,EXCEPTION_STATUS_ID,LOG,HAMATE,WFT,FACK_FLAG,CREATE_USER_ID,EMP_USER_ID,WORK,LAST_UPDATE_DATE,LAST_UPDATE_USER_ID,EXC,REGN_NAME,EXC_REA,GRP_NAME,DIST_NAME,DIV_NAME,CHANGE_ID,NOYPE,PHASE_NAME,CREATE_DATE,STATUS,PARENT_ID,MASTER_ID,REQ_ID,PR,SUP,MS_ID,MS_STATUS,LOG,HAR,COMM,EXP,GOAL,TRANSACTION,NI) VALUES(:EMP_ID,:EMP_NAME,:EMP_STATUS,DEFAULT,:DEFAULT,DEFAULT,DEFAULT,DEFAULT,DEFAULT,DEFAULT,DEFAULT,DEFAULT,DEFAULT,:LOG,:HAR,:COST,:FAS_FLAG,DEFAULT,DEFAULT,DEFAULT,DEFAULT,DEFAULT,DEFAULT,DEFAULT,DEFAULT,DEFAULT,DEFAULT,DEFAULT,DEFAULT,DEFAULT,DEFAULT,DEFAULT,DEFAULT,DEFAULT,:MASTER_ID,:USER_ID,:PR_ID,:SUP_ID,DEFAULT,DEFAULT,DEFAULT,DEFAULT,DEFAULT,DEFAULT,DEFAULT,DEFAULT,DEFAULT).
Employees,0: The OCI function OCIStmtExecute returned status -1. Error code: 24,381, Error message: ORA-24381: error(s) in array DML. (CC_OraStatement::executeInsert, file CC_OraStatement.cpp, line 1,925)
Employees,0: Number of rows inserted on the current node: 0.
Employees,0: The runLocally() of the operator failed.
Employees,0: Input 0 consumed 500 records.
Employees,0: Operator terminated abnormally: runLocally() did not return APT_StatusOk
node_node1: Player 10 terminated unexpectedly.
main_program: APT_PMsectionLeader(1, node1), player 10 - Unexpected termination by Unix signal 15(SIGTERM).
main_program: Step execution finished with status = FAILED.
main_program: Startup time, 0:13; production run time, 0:08.
Job Info aborted.

Возможно, вам также будет интересно:

  • Org8a сетевой не установлен ошибка соединения с менеджером лицензий
  • Org xml sax saxparseexception ошибка
  • Org postgresql util psqlexception ошибка при попытке подсоединения
  • Org postgresql util psqlexception ошибка отношение не существует
  • Org apache maven plugins ошибка

  • Понравилась статья? Поделить с друзьями:
    0 0 голоса
    Рейтинг статьи
    Подписаться
    Уведомить о
    guest

    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии