IF NOT EXISTS(SELECT 1 FROM Table WHERE TId = @Tid)
BEGIN
INSERT INTO Table (
INSERTDATE,
TID
)
VALUES (
GETDATE(),
@Tid
);
END
END
TID是其他表的主键,主要为了避免重复插入的
这是什么情况。。。
是代码的问题?
求解
36 个解决方案
#1
检查表上是否有触发器
#2
改了一下表名,代码没问题,触发器的可能性比较大
--CREATE TABLE test (INSERTDATE datetime,TID int )
create PROC [dbo].[Insert]
@Tid Int
AS
BEGIN
IF NOT EXISTS(SELECT 1 FROM test WHERE TId = @Tid)
BEGIN
INSERT INTO test (
INSERTDATE,
TID
)
VALUES (
GETDATE(),
@Tid
);
END
END
[Insert] 1
SELECT * FROM test
/*
INSERTDATE TID
----------------------- -----------
2014-05-27 10:20:13.350 1
*/
#3
链接池+高并发?
#4
可能调用的代码有bug,连调了两次
#5
同时插入两条相同数据 插入时间完全相同 这不符合正常逻辑吗!!
#6
如果要避免数据重复,建议INSERTDATE,TID联合作唯一索引
#7
我也试过好几次 都没有问题 但是每周都会出现这种情况
检查过了 没有触发器
#8
个别情况下的重复,有可能是并发执行引起的
放在事务中,是否存在判断时候加上锁提示
IF NOT EXISTS(SELECT 1 FROM test WITH(xlock,rowlock) WHERE TId = @Tid)
#9
不懂。。
#10
我重新调试了一遍 无法重复提交 。
这种情况偶尔会出现
#11
那可能是并发导致的,你的库并发很高吗?
#12
其实再把TID做唯一索引就好 可是重复的时候还会报错啊
#13
并发的确很高
#14
请问 “WITH(xlock,rowlock) ”是起什么作用的?
#15
锁住行
#16
用这个试试,为了编译成功,我把你的table换成test了
ALTER PROC [dbo].[Insert] @Tid INT
AS
BEGIN
BEGIN
INSERT INTO test
( INSERTDATE ,
TID
)
SELECT GETDATE() ,
@Tid
FROM test
WHERE NOT EXISTS ( SELECT 1
FROM test
WHERE TId = @Tid )
END
END
#17
如果要避免数据重复,建议INSERTDATE,TID联合作唯一索引
其实再把TID做唯一索引就好 可是重复的时候还会报错啊
那你的存储过程或触发器写得有问题了,若批量插入数据时将出错了
#18
个别情况下的重复,有可能是并发执行引起的
放在事务中,是否存在判断时候加上锁提示
IF NOT EXISTS(SELECT 1 FROM test WITH(xlock,rowlock) WHERE TId = @Tid)
ALTER PROC [dbo].[Insert]
@Tid Int
AS
BEGIN
INSERT INTO [Table] (INSERTDATE,)
SELECT @Tid,GETDATE() FROM [TABLE] WHERE TId <> @Tid
END
#20
不带有select的insert语句不能用hints。也就是单纯的Insert into values不能用with 这些。你的这个说法,应该不会造成连时间都相同的数据(假设你的时间是系统生成而不是你手动指定的)。多个人同时点insert还有点可能
#21
用这个试试,为了编译成功,我把你的table换成test了
ALTER PROC [dbo].[Insert] @Tid INT
AS
BEGIN
BEGIN
INSERT INTO test
( INSERTDATE ,
TID
)
SELECT GETDATE() ,
@Tid
FROM test
WHERE NOT EXISTS ( SELECT 1
FROM test
WHERE TId = @Tid )
END
END
哦
请问你写的这种方法和我原来的那种有什么区别吗?
#22
把判断直接写在insert过程中,算一步,你那个写法算2步
#23
把判断直接写在insert过程中,算一步,你那个写法算2步
但如果楼主是高并发的情况下,这样会导致数据丢失的吧,高并发产生的数据不一定都是重复无用数据
#24
把判断直接写在insert过程中,算一步,你那个写法算2步
但如果楼主是高并发的情况下,这样会导致数据丢失的吧,高并发产生的数据不一定都是重复无用数据
不会丢失,只把不存在的数据插入,逻辑来说和你的一样,只是插入的过程直接判断
#25
同时插入两条相同数据 插入时间完全相同 这不符合正常逻辑吗!!
那个时间精度才到毫秒,一个毫秒内很多条数据完全是有可能的
#26
把判断直接写在insert过程中,算一步,你那个写法算2步
但如果楼主是高并发的情况下,这样会导致数据丢失的吧,高并发产生的数据不一定都是重复无用数据
不会丢失,只把不存在的数据插入,逻辑来说和你的一样,只是插入的过程直接判断
我是这样测试的,如下,写了一个存储过程,用sqlquerystress来开循环和线程
create table t
(
id int,
Createdate datetime
)
create index index_1 on t(id,createdate)
alter proc test_p
@i int
as
begin
begin tran
if not exists(select 1 from t with(xlock,rowlock) where id=@i )
begin
insert into t values (@i,GETDATE());
end
commit
end
--执行调用方式
declare @i int
set @i=cast( rand()*100000 as int)
exec test_p @i
然后用
select COUNT(1),id,Createdate from t
group by id,Createdate
having(COUNT(1))>1
alter proc test_p
@i int
as
begin
INSERT INTO t
( id, Createdate )
SELECT top 1 @i, GETDATE() FROM test
WHERE NOT EXISTS ( SELECT 1 FROM t WHERE id = @i )
end
还请版主指教,为啥
begin tran
if not exists(select 1 from t with(xlock,rowlock) where id=@i )
begin
insert into t values (@i,GETDATE());
end
commit
这种方式是不行的,还是锁不住?
我在手动测试的时候,第一个窗口
begin tran
if not exists(select 1 from t with(xlock,rowlock) where id=12345)
begin
insert into t values (12345,GETDATE());
end
不提交,同样的脚本,第二个窗口中就被阻塞了,按道理也是没问题的啊
create table t
(
id int,
Createdate datetime
)
create index index_1 on t(id,createdate)
alter proc test_p
@i int
as
begin
begin tran
if not exists(select 1 from t with(xlock,rowlock) where id=@i )
begin
insert into t values (@i,GETDATE());
end
commit
end
--执行调用方式
declare @i int
set @i=cast( rand()*100000 as int)
exec test_p @i
然后用
select COUNT(1),id,Createdate from t
group by id,Createdate
having(COUNT(1))>1
alter proc test_p
@i int
as
begin
INSERT INTO t
( id, Createdate )
SELECT top 1 @i, GETDATE() FROM test
WHERE NOT EXISTS ( SELECT 1 FROM t WHERE id = @i )
end
还请版主指教,为啥
begin tran
if not exists(select 1 from t with(xlock,rowlock) where id=@i )
begin
insert into t values (@i,GETDATE());
end
commit
这种方式是不行的,还是锁不住?
我在手动测试的时候,第一个窗口
begin tran
if not exists(select 1 from t with(xlock,rowlock) where id=12345)
begin
insert into t values (12345,GETDATE());
end
不提交,同样的脚本,第二个窗口中就被阻塞了,按道理也是没问题的啊
alter proc test_p
@i int
as
begin
begin try
begin tran
if not exists(select 1 from t with(xlock,rowlock) where id=@i )
begin
insert into t values (@i,GETDATE());
end
commit
end try
begin catch
insert into logmsg values (@i,'数据重复异常');
end catch
end
select COUNT(1),id,Createdate from t
group by id,Createdate
having(COUNT(1))>1
create table t
(
id int,
Createdate datetime
)
create index index_1 on t(id,createdate)
alter proc test_p
@i int
as
begin
begin tran
if not exists(select 1 from t with(xlock,rowlock) where id=@i )
begin
insert into t values (@i,GETDATE());
end
commit
end
--执行调用方式
declare @i int
set @i=cast( rand()*100000 as int)
exec test_p @i
然后用
select COUNT(1),id,Createdate from t
group by id,Createdate
having(COUNT(1))>1
alter proc test_p
@i int
as
begin
INSERT INTO t
( id, Createdate )
SELECT top 1 @i, GETDATE() FROM test
WHERE NOT EXISTS ( SELECT 1 FROM t WHERE id = @i )
end
还请版主指教,为啥
begin tran
if not exists(select 1 from t with(xlock,rowlock) where id=@i )
begin
insert into t values (@i,GETDATE());
end
commit
这种方式是不行的,还是锁不住?
我在手动测试的时候,第一个窗口
begin tran
if not exists(select 1 from t with(xlock,rowlock) where id=12345)
begin
insert into t values (12345,GETDATE());
end
不提交,同样的脚本,第二个窗口中就被阻塞了,按道理也是没问题的啊
alter proc test_p
@i int
as
begin
begin try
begin tran
if not exists(select 1 from t with(xlock,rowlock) where id=@i )
begin
insert into t values (@i,GETDATE());
end
commit
end try
begin catch
insert into logmsg values (@i,'数据重复异常');
end catch
end
select COUNT(1),id,Createdate from t
group by id,Createdate
having(COUNT(1))>1
create table t
(
id int,
Createdate datetime
)
create index index_1 on t(id,createdate)
alter proc test_p
@i int
as
begin
begin tran
if not exists(select 1 from t with(xlock,rowlock) where id=@i )
begin
insert into t values (@i,GETDATE());
end
commit
end
--执行调用方式
declare @i int
set @i=cast( rand()*100000 as int)
exec test_p @i
然后用
select COUNT(1),id,Createdate from t
group by id,Createdate
having(COUNT(1))>1
alter proc test_p
@i int
as
begin
INSERT INTO t
( id, Createdate )
SELECT top 1 @i, GETDATE() FROM test
WHERE NOT EXISTS ( SELECT 1 FROM t WHERE id = @i )
end
还请版主指教,为啥
begin tran
if not exists(select 1 from t with(xlock,rowlock) where id=@i )
begin
insert into t values (@i,GETDATE());
end
commit
这种方式是不行的,还是锁不住?
我在手动测试的时候,第一个窗口
begin tran
if not exists(select 1 from t with(xlock,rowlock) where id=12345)
begin
insert into t values (12345,GETDATE());
end
不提交,同样的脚本,第二个窗口中就被阻塞了,按道理也是没问题的啊
--CREATE TABLE test (INSERTDATE datetime,TID int )
create PROC [dbo].[Insert]
@Tid Int
AS
BEGIN
IF NOT EXISTS(SELECT 1 FROM test WHERE TId = @Tid)
BEGIN
INSERT INTO test (
INSERTDATE,
TID
)
VALUES (
GETDATE(),
@Tid
);
END
END
[Insert] 1
SELECT * FROM test
/*
INSERTDATE TID
----------------------- -----------
2014-05-27 10:20:13.350 1
*/
#3
链接池+高并发?
#4
可能调用的代码有bug,连调了两次
#5
同时插入两条相同数据 插入时间完全相同 这不符合正常逻辑吗!!
#6
如果要避免数据重复,建议INSERTDATE,TID联合作唯一索引
#7
改了一下表名,代码没问题,触发器的可能性比较大
--CREATE TABLE test (INSERTDATE datetime,TID int )
create PROC [dbo].[Insert]
@Tid Int
AS
BEGIN
IF NOT EXISTS(SELECT 1 FROM test WHERE TId = @Tid)
BEGIN
INSERT INTO test (
INSERTDATE,
TID
)
VALUES (
GETDATE(),
@Tid
);
END
END
[Insert] 1
SELECT * FROM test
/*
INSERTDATE TID
----------------------- -----------
2014-05-27 10:20:13.350 1
*/
我也试过好几次 都没有问题 但是每周都会出现这种情况
检查过了 没有触发器
#8
个别情况下的重复,有可能是并发执行引起的
放在事务中,是否存在判断时候加上锁提示
IF NOT EXISTS(SELECT 1 FROM test WITH(xlock,rowlock) WHERE TId = @Tid)
#9
链接池+高并发?
不懂。。
#10
可能调用的代码有bug,连调了两次
我重新调试了一遍 无法重复提交 。
这种情况偶尔会出现
#11
那可能是并发导致的,你的库并发很高吗?
#12
如果要避免数据重复,建议INSERTDATE,TID联合作唯一索引
其实再把TID做唯一索引就好 可是重复的时候还会报错啊
#13
那可能是并发导致的,你的库并发很高吗?
并发的确很高
#14
个别情况下的重复,有可能是并发执行引起的
放在事务中,是否存在判断时候加上锁提示
IF NOT EXISTS(SELECT 1 FROM test WITH(xlock,rowlock) WHERE TId = @Tid)
请问 “WITH(xlock,rowlock) ”是起什么作用的?
#15
个别情况下的重复,有可能是并发执行引起的
放在事务中,是否存在判断时候加上锁提示
IF NOT EXISTS(SELECT 1 FROM test WITH(xlock,rowlock) WHERE TId = @Tid)
请问 “WITH(xlock,rowlock) ”是起什么作用的?
锁住行
#16
用这个试试,为了编译成功,我把你的table换成test了
ALTER PROC [dbo].[Insert] @Tid INT
AS
BEGIN
BEGIN
INSERT INTO test
( INSERTDATE ,
TID
)
SELECT GETDATE() ,
@Tid
FROM test
WHERE NOT EXISTS ( SELECT 1
FROM test
WHERE TId = @Tid )
END
END
#17
如果要避免数据重复,建议INSERTDATE,TID联合作唯一索引
其实再把TID做唯一索引就好 可是重复的时候还会报错啊
那你的存储过程或触发器写得有问题了,若批量插入数据时将出错了
#18
个别情况下的重复,有可能是并发执行引起的
放在事务中,是否存在判断时候加上锁提示
IF NOT EXISTS(SELECT 1 FROM test WITH(xlock,rowlock) WHERE TId = @Tid)
ALTER PROC [dbo].[Insert]
@Tid Int
AS
BEGIN
INSERT INTO [Table] (INSERTDATE,)
SELECT @Tid,GETDATE() FROM [TABLE] WHERE TId <> @Tid
END
#20
不带有select的insert语句不能用hints。也就是单纯的Insert into values不能用with 这些。你的这个说法,应该不会造成连时间都相同的数据(假设你的时间是系统生成而不是你手动指定的)。多个人同时点insert还有点可能
#21
用这个试试,为了编译成功,我把你的table换成test了
ALTER PROC [dbo].[Insert] @Tid INT
AS
BEGIN
BEGIN
INSERT INTO test
( INSERTDATE ,
TID
)
SELECT GETDATE() ,
@Tid
FROM test
WHERE NOT EXISTS ( SELECT 1
FROM test
WHERE TId = @Tid )
END
END
哦
请问你写的这种方法和我原来的那种有什么区别吗?
#22
把判断直接写在insert过程中,算一步,你那个写法算2步
#23
把判断直接写在insert过程中,算一步,你那个写法算2步
但如果楼主是高并发的情况下,这样会导致数据丢失的吧,高并发产生的数据不一定都是重复无用数据
#24
把判断直接写在insert过程中,算一步,你那个写法算2步
但如果楼主是高并发的情况下,这样会导致数据丢失的吧,高并发产生的数据不一定都是重复无用数据
不会丢失,只把不存在的数据插入,逻辑来说和你的一样,只是插入的过程直接判断
#25
同时插入两条相同数据 插入时间完全相同 这不符合正常逻辑吗!!
那个时间精度才到毫秒,一个毫秒内很多条数据完全是有可能的
#26
把判断直接写在insert过程中,算一步,你那个写法算2步
但如果楼主是高并发的情况下,这样会导致数据丢失的吧,高并发产生的数据不一定都是重复无用数据
不会丢失,只把不存在的数据插入,逻辑来说和你的一样,只是插入的过程直接判断
我是这样测试的,如下,写了一个存储过程,用sqlquerystress来开循环和线程
create table t
(
id int,
Createdate datetime
)
create index index_1 on t(id,createdate)
alter proc test_p
@i int
as
begin
begin tran
if not exists(select 1 from t with(xlock,rowlock) where id=@i )
begin
insert into t values (@i,GETDATE());
end
commit
end
--执行调用方式
declare @i int
set @i=cast( rand()*100000 as int)
exec test_p @i
然后用
select COUNT(1),id,Createdate from t
group by id,Createdate
having(COUNT(1))>1
alter proc test_p
@i int
as
begin
INSERT INTO t
( id, Createdate )
SELECT top 1 @i, GETDATE() FROM test
WHERE NOT EXISTS ( SELECT 1 FROM t WHERE id = @i )
end
还请版主指教,为啥
begin tran
if not exists(select 1 from t with(xlock,rowlock) where id=@i )
begin
insert into t values (@i,GETDATE());
end
commit
这种方式是不行的,还是锁不住?
我在手动测试的时候,第一个窗口
begin tran
if not exists(select 1 from t with(xlock,rowlock) where id=12345)
begin
insert into t values (12345,GETDATE());
end
不提交,同样的脚本,第二个窗口中就被阻塞了,按道理也是没问题的啊
create table t
(
id int,
Createdate datetime
)
create index index_1 on t(id,createdate)
alter proc test_p
@i int
as
begin
begin tran
if not exists(select 1 from t with(xlock,rowlock) where id=@i )
begin
insert into t values (@i,GETDATE());
end
commit
end
--执行调用方式
declare @i int
set @i=cast( rand()*100000 as int)
exec test_p @i
然后用
select COUNT(1),id,Createdate from t
group by id,Createdate
having(COUNT(1))>1
alter proc test_p
@i int
as
begin
INSERT INTO t
( id, Createdate )
SELECT top 1 @i, GETDATE() FROM test
WHERE NOT EXISTS ( SELECT 1 FROM t WHERE id = @i )
end
还请版主指教,为啥
begin tran
if not exists(select 1 from t with(xlock,rowlock) where id=@i )
begin
insert into t values (@i,GETDATE());
end
commit
这种方式是不行的,还是锁不住?
我在手动测试的时候,第一个窗口
begin tran
if not exists(select 1 from t with(xlock,rowlock) where id=12345)
begin
insert into t values (12345,GETDATE());
end
不提交,同样的脚本,第二个窗口中就被阻塞了,按道理也是没问题的啊
alter proc test_p
@i int
as
begin
begin try
begin tran
if not exists(select 1 from t with(xlock,rowlock) where id=@i )
begin
insert into t values (@i,GETDATE());
end
commit
end try
begin catch
insert into logmsg values (@i,'数据重复异常');
end catch
end
select COUNT(1),id,Createdate from t
group by id,Createdate
having(COUNT(1))>1
create table t
(
id int,
Createdate datetime
)
create index index_1 on t(id,createdate)
alter proc test_p
@i int
as
begin
begin tran
if not exists(select 1 from t with(xlock,rowlock) where id=@i )
begin
insert into t values (@i,GETDATE());
end
commit
end
--执行调用方式
declare @i int
set @i=cast( rand()*100000 as int)
exec test_p @i
然后用
select COUNT(1),id,Createdate from t
group by id,Createdate
having(COUNT(1))>1
alter proc test_p
@i int
as
begin
INSERT INTO t
( id, Createdate )
SELECT top 1 @i, GETDATE() FROM test
WHERE NOT EXISTS ( SELECT 1 FROM t WHERE id = @i )
end
还请版主指教,为啥
begin tran
if not exists(select 1 from t with(xlock,rowlock) where id=@i )
begin
insert into t values (@i,GETDATE());
end
commit
这种方式是不行的,还是锁不住?
我在手动测试的时候,第一个窗口
begin tran
if not exists(select 1 from t with(xlock,rowlock) where id=12345)
begin
insert into t values (12345,GETDATE());
end
不提交,同样的脚本,第二个窗口中就被阻塞了,按道理也是没问题的啊
alter proc test_p
@i int
as
begin
begin try
begin tran
if not exists(select 1 from t with(xlock,rowlock) where id=@i )
begin
insert into t values (@i,GETDATE());
end
commit
end try
begin catch
insert into logmsg values (@i,'数据重复异常');
end catch
end
select COUNT(1),id,Createdate from t
group by id,Createdate
having(COUNT(1))>1
create table t
(
id int,
Createdate datetime
)
create index index_1 on t(id,createdate)
alter proc test_p
@i int
as
begin
begin tran
if not exists(select 1 from t with(xlock,rowlock) where id=@i )
begin
insert into t values (@i,GETDATE());
end
commit
end
--执行调用方式
declare @i int
set @i=cast( rand()*100000 as int)
exec test_p @i
然后用
select COUNT(1),id,Createdate from t
group by id,Createdate
having(COUNT(1))>1
alter proc test_p
@i int
as
begin
INSERT INTO t
( id, Createdate )
SELECT top 1 @i, GETDATE() FROM test
WHERE NOT EXISTS ( SELECT 1 FROM t WHERE id = @i )
end
还请版主指教,为啥
begin tran
if not exists(select 1 from t with(xlock,rowlock) where id=@i )
begin
insert into t values (@i,GETDATE());
end
commit
这种方式是不行的,还是锁不住?
我在手动测试的时候,第一个窗口
begin tran
if not exists(select 1 from t with(xlock,rowlock) where id=12345)
begin
insert into t values (12345,GETDATE());
end
不提交,同样的脚本,第二个窗口中就被阻塞了,按道理也是没问题的啊