Foros del Web » Programación para mayores de 30 ;) » Bases de Datos General » SQL Server »

Problema con Insert PK dulicado

Estas en el tema de Problema con Insert PK dulicado en el foro de SQL Server en Foros del Web. Hola buenos días expertos. El motivo de mi post es por un problema que de un tiempo de implementado mi proyecto se me están presentando ...
  #1 (permalink)  
Antiguo 26/05/2012, 11:18
 
Fecha de Ingreso: mayo-2011
Mensajes: 6
Antigüedad: 13 años
Puntos: 1
Problema con Insert PK dulicado

Hola buenos días expertos.
El motivo de mi post es por un problema que de un tiempo de implementado mi proyecto se me están presentando problemas en mi procemiento INSERT.
El mensaje es "VIOLATION OF PRIMARY KEY CONSTRAINT PK_VENTA"
Tiene de implementado 8 meses. Sin problemas.

Les detallado el SP en cuestion:

**********************
USE [BDpanificadora]
GO
/****** Object: StoredProcedure [dbo].[usp_insertar_venta] Script Date: 05/26/2012 11:16:06 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[usp_insertar_venta]
@codEmi int,
@codTipDoc int,
@serVenta varchar(4),
@numVenta varchar(8),
@codClie int,
@codMetodo int,
@codTurno int,
@codForma int,
@codTarje int,
@numTarje varchar(15),
@fecVenta date,
@totVenta decimal(12,2),
@igvVenta decimal(12,2),
@pagoVenta decimal(12,2),
@pagoCon decimal(12,2),
@tienda int,
@usuario int,
@obsprecio varchar(140),
@usuAuto int,
@SerieTik Varchar(4),
@retCod int OUTPUT,
@NumFac Varchar(8) OUTPUT,
@varVentaDet tVentaDet READONLY
AS
DECLARE @vcod int,
@nPag int,
@ntemp varchar(8),
@nRetTik int,
@error_var int

BEGIN TRANSACTION T1;
BEGIN
SET @vcod= (SELECT max(IDventa) FROM Venta)
SET @nPag=(SELECT MAX(IDpago) FROM Pago)

-- OBTENER NUMERO CORRELATIVO DE LA SERIE AUTORIZADA
IF @codTipDoc=11
BEGIN
SET @ntemp=(SELECT max(Numero) FROM [dbo].[Venta] WHERE Serie=@SerieTik)

IF (@ntemp) IS NULL
BEGIN
SET @nRetTik=1
SET @serVenta=@SerieTik
SET @numVenta=RIGHT('00000000' + Convert(VARCHAR,@nRetTik),8)
SET @NumFac=@numVenta
END
ELSE
BEGIN
SET @nRetTik=Convert(Int,@ntemp)+1
SET @serVenta=@SerieTik
SET @numVenta=RIGHT('00000000' + Convert(VARCHAR,@nRetTik),8)
SET @NumFac=@numVenta
END
END
ELSE
BEGIN
SET @NumFac=''
END

-- FIN

IF (@vcod) IS NULL
BEGIN
SET @vcod=1
END
ELSE
BEGIN
SET @vcod=@vcod+1
END

IF (@nPag) IS NULL
BEGIN
SET @nPag=1
END
ELSE
BEGIN
SET @nPag=@nPag+1
END

SET @retCod=@vcod

Insert Into Venta
(IDventa,IDcliente,IDtienda,IDemision,IDcompago,ID turno,IDmetodo,Serie,Numero,Fecha,Subtotal
,Igv,Total,PagaCon,Acuenta,Saldo,Procesada,Anulada ,IDusuario,FechaReg,FlagBloqueo,Notas,IDusuauto)
values(@vcod,@codClie,@tienda,@codEmi,@codTipDoc,@ codTurno,@codMetodo,@serVenta,@numVenta
,@fecVenta,@totVenta-@igvVenta,@igvVenta,@totVenta,@pagoCon,@pagoVenta, @totVenta-@pagoVenta
,1,0,@usuario,GETDATE(),0,@obsprecio,(CASE WHEN @obsprecio='' THEN NULL ELSE @usuAuto END))
SELECT @error_var=@@error
IF (@error_var<>0) GOTO TratarError

IF @pagoVenta>0
BEGIN
Insert Into Pago
(IDpago,IDventa,IDtienda,IDcliente,Fecha,IDturno,P agoImp,IDforma,IDtarjeta,NumTarjeta
,Anulado,FlagCobranza,IDusuario,FechaReg,FlagBloqu eo)values(@nPag,@vcod,@tienda,@codClie,@fecVenta
,@codTurno,@pagoVenta,@codForma,@codTarje,@numTarj e,0,0,@usuario,GETDATE(),0)
SELECT @error_var=@@error
IF (@error_var<>0) GOTO TratarError
END
END

BEGIN TRANSACTION T2;
BEGIN
MERGE DetVenta AS TARGET
USING @varVentaDet AS SOURCE
ON (Target.IDventa = @vcod
AND Target.IDpromerter = Source.CodProTer
AND Target.IDderivado = Source.CodProDer)
WHEN NOT MATCHED BY TARGET THEN
INSERT (IDventa,Linea,TipoProducto,IDpromerter,IDderivado ,IDunidad,PrecioVenta,Cantidad,Subtotal,Igv,DifPre cio)
VALUES (@vcod,Source.nLinea,Source.CodTipPro,Source.CodPr oTer,Source.CodProDer,Source.CodUni
,Source.precio,Source.cantidad,Source.subtotal,Sou rce.igv,Source.DifPrecio);
SELECT @error_var=@@error
IF (@error_var<>0) GOTO TratarError
END

BEGIN TRANSACTION T3;
BEGIN
WITH TemDetTer (IDpromerter,IDtienda,TipoProducto,Stock)
AS
(
SELECT IDpromerter,IDtienda,TipoProducto,Stock
FROM dbo.DetMerTer
WHERE IDtienda=@tienda AND TipoProducto=1 -- productos terminados
)
,TemVentaDet (CodProTer,CodTipPro,cantidad)
AS
(
SELECT CodProTer,CodTipPro,cantidad
FROM @varVentaDet
WHERE CodTipPro=1 -- productos terminados
)

MERGE TemDetTer AS TARGET
USING TemVentaDet AS SOURCE
ON (Target.IDpromerter = Source.CodProTer
AND Target.IDtienda = @tienda
AND Target.TipoProducto=Source.CodTipPro)-- productos terminados
WHEN MATCHED THEN
UPDATE
SET TARGET.Stock = Round(TARGET.Stock-Source.cantidad,2);
SELECT @error_var=@@error
IF (@error_var<>0) GOTO TratarError
END

BEGIN TRANSACTION T4;
BEGIN
WITH TemDetDer (IDderivado,IDtienda,TipoProducto,Stock)
AS
(
SELECT IDderivado,IDtienda,TipoProducto,Stock
FROM dbo.DetMerTer
WHERE IDtienda=@tienda AND TipoProducto=2 -- productos terminados
)
,TemVentaDer (CodProDer,CodTipPro,cantidad)
AS
(
SELECT CodProDer,CodTipPro,cantidad
FROM @varVentaDet
WHERE CodTipPro=2 -- productos terminados
)

MERGE TemDetDer AS TARGET
USING TemVentaDer AS SOURCE
ON (Target.IDderivado = Source.CodProDer
AND Target.IDtienda = @tienda
AND Target.TipoProducto=Source.CodTipPro)-- productos terminados
WHEN MATCHED THEN
UPDATE
SET TARGET.Stock = Round(TARGET.Stock-Source.cantidad,2);
SELECT @error_var=@@error
IF (@error_var<>0) GOTO TratarError
END

COMMIT TRANSACTION T4
COMMIT TRANSACTION T3
COMMIT TRANSACTION T2
COMMIT TRANSACTION T1
RETURN 0

TratarError:
--Si ha ocurrido algún error llegamos hasta aquí
If @error_var<>0
BEGIN
ROLLBACK TRAN
RETURN -1
END

**********************
Como Observaran yo obtengo mi numero correlativo el cual es obtenido haciendo un select max, ese codigo me es necesario para otras tablas.
Ahora la ocurrencia segun lo que he podido apreciar es cuando varios usuarios concurrentes (20) estan sobre ta tabla trantando de insertar su registro.
El soft es un punto de venta.
Numero de registros de la tabla en mencion es de 600,000 registros a la fecha.

No se que puede estar pasando. Me pregunto si el select max demora mucho tiempo ya que tambien hago otros select max el cual tienen las misma cantidad de registros.

Lo otro pueda ser que sea por el BEGIN TRAN que utilizo, al hacer commit recien grabo y ahi se puede estar chocando con otros codigos capturados por otro usuario.

Me podrian orientar como lo puedo manejar mejor mi ID obtenido por codigo.
¿Seria mejor usar IDENTITY? ¿tendria el mismo problema?

Espero sus respuestas expertos de acuerdo a sus experiencias obtenidas. Este es mi primer proyecto con SQL.

Gracias de antemano.
Saludos a todos.
  #2 (permalink)  
Antiguo 27/05/2012, 15:21
 
Fecha de Ingreso: octubre-2009
Mensajes: 35
Antigüedad: 14 años, 6 meses
Puntos: 2
Respuesta: Problema con Insert PK dulicado

mi recomendaciones es que utilices un identity porque así el gestor internamente realiza el incremento y pues puede ser que en el transcurso de mili segundo de diferencia entre el max e ingresar la nueva tupla otro usuario este ingresando una tupla entonces, el max que realizo ya esta descontinuado mientras que cuando utilizas el identity, al momento de ingresar se realiza el aumento del id o si no queres usar un identity por lo menos utiliza un triger asi realizas el max exactamente al momento de ingresar la tupla

Etiquetas: insert, registro, select, sql, tabla
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 20:11.