Constriant violation on primary key

07/05/2010 - 21:26 por Saga | Informe spam
Saludos, en esta ocasion me gustaria suber su opinion con respecto a lo
siguiente. Tengo una aplicacion que monitorea una carpeta esperando que
otra aplicacion escriba archivos de texto. Cuando encuentro un archivo lo
leo y lo importo a la base de datos (SQL Server 2000). Estiy usando VB
6 y .NET 2008 con ADO 2.7 y ADO.NET (respectivamenete).

Los archivos de datos estan clasificados en 2 categorias: transito y final.
Loas archivos "transito" son aquellos que van llegando durante el dia y
aquellos que son "final" se mandan una sola vez al cierre de la sesion:

div1_44139.transito
div1_37364.transito
div1_47322.transito
div1_48457.final

Usu el prefijo "div1" porque hay varias divisiones (mas de mil) y cada
division manda su conjunto de datos. Dentro de mi codigo tengo un
proceso similar al siguiente:

if dbExisteMovto(t) then
dbUpdateMovto(t)
else
dbInsertMovto(t)
end if

"t" es una estructura donde se guardan los datos pertinentes a la tabla
Movto. El esquema actual trabajaba muy bien hasta que la aplicacion
se dividio en dos. Debido a que el numero de divisiones cada dia es
mayor, la misma aplicacoin se instalo en otra PC. La primera instalacion
se configuro para que solo procese archivos "transito" y la segunda
para que procese los archivos "final".

El problema es que en ocasiones ambas aplicaciones procesan archivos
de la misma division al mismo tiempo, asi que la aplicacion verifica si
existe el registro, al comprobar que no entra a la rutina de Insert, pero
la otra rutina acaba de hacer un INSERT del mismo registro, asi que
cuando ejecuto el INSERT dentro de la otra aplicacion, el proceso
falla indicando una violacion de la llave primaria.

Para eliminar este problema estoy pensando armar una rutina usando
TSQL (y que se ejecute en el servidor) que verifique la existencia del
registro y realice el INSERT o UPDATE segun el resultado. Esto
definitivamente sera una mejoria a como lo tengo ahora, pero quiero
preguntarles a ustedes si esta es la solucion adecuada o si hay otra
mas apropiada para resolver este problema. Les doy las gracias por
su atencion a este post y por cualquier orientacion que se me pueda
dar. Saludos, Saga.

Preguntas similare

Leer las respuestas

#1 Saga
07/05/2010 - 22:30 | Informe spam
Leyedo mi pregunta me entro la duda si me explique bien en el parrafo
"El problema es que en ocasiones ...". Si estuv confuso, aqui lo explico
de nuevo :-)

Aqui les presento una lista de las actividades qeu se realizan en el
Servidor SQL:

a. App1 procesa archivo tipo transito, verifica si existe registro: No
existe
b. App2 procesa archivo tipo final, verifica si existe registro: No existe
c. App1 inserta registro - actividad se realiza con exito
d. App2 inserta registro - genera error porque App1 acaba de insertar
el registro en el paso anterior.

La rutina TSQL seria similar a lo siguiente:

if select count(*) from Movtos where x=1 and y=2 and z=3 > 0
update Movtos set
else
insert into Movtos (

Lo mas probable es que agregue codigo para probar si el proceso
se realizo con exito. Obviamente, es importante que la otra aplicacion
no llegue a insertar un registro despues de procesar la condicion del
IF y antes de hacer el INSERT.

Espero que esta explicacion este mas clara. :-) Saga
Respuesta Responder a este mensaje
#2 Victor Koch
07/05/2010 - 22:39 | Informe spam
Hola Saga,

El problema es el siguiente:

Si todas las operaciones a la base de datos las anidas en una transacción
los registros insertados no van a existir para las demás conexiones hasta
que no termines la transacción.

Esto suena lógico porque si anulas la transacción los registros insertados
dentro de la transacción no van a existir, entonces no es lógico que otra
conexión en medio de una transacción encuentre el registro porque hasta que
termine la transacción no se va a saber a ciencia cierta si el registro
existirá o no.

A mi entender te quedan dos opciones:

1.Guardar en una tabla de la base de datos el nombre del archivo que se
están procesando, esta grabación debería estar fuera de la transacción.
Cuando vas a procesar un archivo primero te fijas si existe en esa tabla, si
existe quiere decir que ya hay una terminal que lo esta procesando.
Si la transacción la tenes que volver para atrás deberías estar eliminando
ese registro o tal vez dejarlo y guardar el motivo de la anulación de la
transacción.
De echo podrías guardar no solo el nombre del archivo sino fecha y hora de
proceso, nombre de la PC que lo proceso, etc,etc.

2.Al momento de comenzar a procesar el archivo abrirlo en modo exclusivo, si
otra terminal intenta abrirlo salta el error que esta siendo usado por otra
terminal.

La apertura seria así:

Open "Camino\MiArchivo" For input Lock Read Write As #1

Un Saludo, Víctor Koch



"Saga" escribió en el mensaje
news:
Saludos, en esta ocasion me gustaria suber su opinion con respecto a lo
siguiente. Tengo una aplicacion que monitorea una carpeta esperando que
otra aplicacion escriba archivos de texto. Cuando encuentro un archivo lo
leo y lo importo a la base de datos (SQL Server 2000). Estiy usando VB
6 y .NET 2008 con ADO 2.7 y ADO.NET (respectivamenete).

Los archivos de datos estan clasificados en 2 categorias: transito y
final.
Loas archivos "transito" son aquellos que van llegando durante el dia y
aquellos que son "final" se mandan una sola vez al cierre de la sesion:

div1_44139.transito
div1_37364.transito
div1_47322.transito
div1_48457.final

Usu el prefijo "div1" porque hay varias divisiones (mas de mil) y cada
division manda su conjunto de datos. Dentro de mi codigo tengo un
proceso similar al siguiente:

if dbExisteMovto(t) then
dbUpdateMovto(t)
else
dbInsertMovto(t)
end if

"t" es una estructura donde se guardan los datos pertinentes a la tabla
Movto. El esquema actual trabajaba muy bien hasta que la aplicacion
se dividio en dos. Debido a que el numero de divisiones cada dia es
mayor, la misma aplicacoin se instalo en otra PC. La primera instalacion
se configuro para que solo procese archivos "transito" y la segunda
para que procese los archivos "final".

El problema es que en ocasiones ambas aplicaciones procesan archivos
de la misma division al mismo tiempo, asi que la aplicacion verifica si
existe el registro, al comprobar que no entra a la rutina de Insert, pero
la otra rutina acaba de hacer un INSERT del mismo registro, asi que
cuando ejecuto el INSERT dentro de la otra aplicacion, el proceso
falla indicando una violacion de la llave primaria.

Para eliminar este problema estoy pensando armar una rutina usando
TSQL (y que se ejecute en el servidor) que verifique la existencia del
registro y realice el INSERT o UPDATE segun el resultado. Esto
definitivamente sera una mejoria a como lo tengo ahora, pero quiero
preguntarles a ustedes si esta es la solucion adecuada o si hay otra
mas apropiada para resolver este problema. Les doy las gracias por
su atencion a este post y por cualquier orientacion que se me pueda
dar. Saludos, Saga.





Respuesta Responder a este mensaje
#3 Saga
07/05/2010 - 23:28 | Informe spam
Hola Victor, gracias por la respuesta. Cabe mencionar que son diferentes
archivos los que procesan las dos aplicaciones, correspondiendo a la
misma division (por decirlo asi).

div1_47322.transito - este tipo lo procesa la app1 en una PC
div1_48457.final - este tipo lo procesa la app2 en otra PC

Saludos, Saga


"Victor Koch" <v i c t o r (arroba)correo(punto)waldbott(punto)com(punto)ar>
wrote in message news:
Hola Saga,

El problema es el siguiente:

Si todas las operaciones a la base de datos las anidas en una transacción
los registros insertados no van a existir para las demás conexiones hasta
que no termines la transacción.

Esto suena lógico porque si anulas la transacción los registros insertados
dentro de la transacción no van a existir, entonces no es lógico que otra
conexión en medio de una transacción encuentre el registro porque hasta
que termine la transacción no se va a saber a ciencia cierta si el
registro existirá o no.

A mi entender te quedan dos opciones:

1.Guardar en una tabla de la base de datos el nombre del archivo que se
están procesando, esta grabación debería estar fuera de la transacción.
Cuando vas a procesar un archivo primero te fijas si existe en esa tabla,
si existe quiere decir que ya hay una terminal que lo esta procesando.
Si la transacción la tenes que volver para atrás deberías estar eliminando
ese registro o tal vez dejarlo y guardar el motivo de la anulación de la
transacción.
De echo podrías guardar no solo el nombre del archivo sino fecha y hora de
proceso, nombre de la PC que lo proceso, etc,etc.

2.Al momento de comenzar a procesar el archivo abrirlo en modo exclusivo,
si otra terminal intenta abrirlo salta el error que esta siendo usado por
otra terminal.

La apertura seria así:

Open "Camino\MiArchivo" For input Lock Read Write As #1

Un Saludo, Víctor Koch



"Saga" escribió en el mensaje
news:
Saludos, en esta ocasion me gustaria suber su opinion con respecto a lo
siguiente. Tengo una aplicacion que monitorea una carpeta esperando que
otra aplicacion escriba archivos de texto. Cuando encuentro un archivo lo
leo y lo importo a la base de datos (SQL Server 2000). Estiy usando VB
6 y .NET 2008 con ADO 2.7 y ADO.NET (respectivamenete).

Los archivos de datos estan clasificados en 2 categorias: transito y
final.
Loas archivos "transito" son aquellos que van llegando durante el dia y
aquellos que son "final" se mandan una sola vez al cierre de la sesion:

div1_44139.transito
div1_37364.transito
div1_47322.transito
div1_48457.final

Usu el prefijo "div1" porque hay varias divisiones (mas de mil) y cada
division manda su conjunto de datos. Dentro de mi codigo tengo un
proceso similar al siguiente:

if dbExisteMovto(t) then
dbUpdateMovto(t)
else
dbInsertMovto(t)
end if

"t" es una estructura donde se guardan los datos pertinentes a la tabla
Movto. El esquema actual trabajaba muy bien hasta que la aplicacion
se dividio en dos. Debido a que el numero de divisiones cada dia es
mayor, la misma aplicacoin se instalo en otra PC. La primera instalacion
se configuro para que solo procese archivos "transito" y la segunda
para que procese los archivos "final".

El problema es que en ocasiones ambas aplicaciones procesan archivos
de la misma division al mismo tiempo, asi que la aplicacion verifica si
existe el registro, al comprobar que no entra a la rutina de Insert, pero
la otra rutina acaba de hacer un INSERT del mismo registro, asi que
cuando ejecuto el INSERT dentro de la otra aplicacion, el proceso
falla indicando una violacion de la llave primaria.

Para eliminar este problema estoy pensando armar una rutina usando
TSQL (y que se ejecute en el servidor) que verifique la existencia del
registro y realice el INSERT o UPDATE segun el resultado. Esto
definitivamente sera una mejoria a como lo tengo ahora, pero quiero
preguntarles a ustedes si esta es la solucion adecuada o si hay otra
mas apropiada para resolver este problema. Les doy las gracias por
su atencion a este post y por cualquier orientacion que se me pueda
dar. Saludos, Saga.









email Siga el debate Respuesta Responder a este mensaje
Ads by Google
Help Hacer una preguntaRespuesta Tengo una respuesta
Search Busqueda sugerida