SQL0803N es un mensaje de error que significa que la sentencia SQL recién emitida falló debido a la violación de una restricción única dentro de la base de datos. La «N» al final de este error significa que esta sentencia falló y no se ejecutó, pero que probablemente no sea un problema de la base de datos. Consulte Conceptos básicos de Db2: Mensajes de error para obtener más información general sobre la interpretación de mensajes de error de Db2.
¿Qué aspecto tiene este error?
Al igual que con cualquier mensaje de error en Db2, es fundamental obtener el texto completo del mensaje para solucionar el problema. Aquí hay un ejemplo de cómo debería ser ese resultado completo:
insert into dbi_repos.MONITORED_DB_PARTS (db_id ,db_part_num ,coll_id ,server_name ,db_login_id ,db_login_crypt_pwd ,is_monitored ,is_catlg_node) VALUES (1 ,0 ,1 ,'example.com' ,'db2inst1' ,'test' ,'N' ,'Y') DB21034E The command was processed as an SQL statement because it was not a valid Command Line Processor command. During SQL processing it returned: SQL0803N One or more values in the INSERT statement, UPDATE statement, or foreign key update caused by a DELETE statement are not valid because the primary key, unique constraint or unique index identified by "1" constrains table "DBI_REPOS.MONITORED_DB_PARTS_1" from having duplicate values for the index key. SQLSTATE=23505
Si no está emitiendo el comando en una línea de comando Db2, este mensaje puede estar oculto entre los mensajes de salida (logs) de la aplicación. También se puede recibir como un error -803. Cada aplicación que accede a una base de datos debe registrar errores como este en detalle: la verificación de errores es un componente crítico de cualquier aplicación. Los mensajes de salida de una aplicación pueden parecerse un poco más a esto:
DB2 SQL Error: SQLCODE=-803, SQLSTATE=23505, SQLERRMC=1;DBI_REPOS.MONITORED_DB_PARTS_1
Identificando el problema real
En los mensajes de error anteriores, he resaltado las piezas críticas de información en rojo. Incluso si no tiene el texto completo del mensaje de error en el log de una aplicación, estas dos piezas de información deberían devolverse en la salida reducida disponible. Esta información nos dice en este caso que estamos violando el índice número 1 en la tabla DBI_REPOS.MONITORED_DB_PARTS_1. Ahora que tengo esa información, puedo ejecutar una consulta simple para mostrarme qué columnas tienen datos duplicados cuando no deberían:
select substr(indname,1,32) as indname , substr(colnames,1,50) as colnames from syscat.indexes where tabschema='DBI_REPOS' and tabname='MONITORED_DB_PARTS_1' and iid=1 with ur INDNAME COLNAMES -------------------------------- -------------------------------------------------- PX_MONDBPARTS +DB_ID+DB_PART_NUM 1 record(s) selected.
Los valores que se deben cambiar en esta consulta para que coincidan con el mensaje de error específico están en rojo. Tenga en cuenta que el esquema y el nombre de la tabla deben estar en mayúsculas o en mayúsculas y minúsculas específicas si ha sido usted tan malvado como para forzar los nombres de las tablas en mayúsculas y minúsculas.
En este caso, podemos ver que la instrucción intentaba usar valores duplicados para la combinación de DB_ID y DB_PART_NUM. Esta combinación de valores ya existía en la tabla. Puedo verificar eso usando una instrucción sql que está mucho más personalizada para la tabla. En este caso, usaría:
select * from dbi_repos.MONITORED_DB_PARTS where DB_ID=1 and DB_PART_NUM=0 with ur DB_ID DB_PART_NUM COLL_ID SERVER_NAME DB_LOGIN_ID DB_LOGIN_CRYPT_PWD IS_CATLG_NODE IS_MONITORED ----------- ----------- ----------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------- ------------- ------------ 1 0 21 somesillydbserver.example.com db2inst1 XXXXXXXXXXXXXXXXXXXX Y Y 1 record(s) selected.
Los valores que estoy utilizando aquí para DB_ID y DB_PART_NUM son los valores de mi sentencia de inserción original.
Resolviendo el error
Las opciones para resolver este problema son:
- Modifique los datos que se están insertando para que no entren en conflicto con los datos que ya están en la tabla.
- Corrija los datos que ya están en la tabla para asegurarse de que los valores no entren en conflicto con lo que se está insertando.
La solución a este mensaje de error es casi siempre cambiar de alguna manera los datos que intenta insertar a la tabla.
Este no es un problema del sistema de base de datos y, en general, todo lo que un DBA puede hacer es ayudarlo con este análisis para descubrir qué está mal con los datos.