一个多线程运行Sql的插入数据
set @str=N'insert into ulook(uname,cname,addtime) SELECT a.uname,'''+@cname +''',GETDATE()
FROM per as a WHERE CHARINDEX('',''+LTRIM(id)+'','', '','+@perid+','')>0
    AND NOT EXISTS(SELECT 1 FROM ulook WHERE uname = a.uname AND cname = '''+@cname+''')'
exec sp_executesql  @str
可是最后还是有重复的数据插入,怎么回事?

解决方案 »

  1.   

    sql 是select 一个插一个,而不是全读出来在插
      

  2.   

    如何在多线程中,防止ulook插入uname,cname相同的数据
      

  3.   


    只能在数据库级进行约束了,对uname,cname进行唯一性约束。
      

  4.   

    可以建约束或者唯一索引来定义
    或者你可以试一下 狠点
    select 的时候给来个表锁
    set @str=N'insert into ulook(uname,cname,addtime) SELECT a.uname,'''+@cname +''',GETDATE()
    FROM per with (xlock, tablock) as a   WHERE CHARINDEX('',''+LTRIM(id)+'','', '','+@perid+','')>0
        AND NOT EXISTS(SELECT 1 FROM ulook  WHERE uname = a.uname AND cname = '''+@cname+''')'
    exec sp_executesql  @str
      

  5.   

    NOT EXISTS怎么会判断不出来
      

  6.   

    因为有两个以上进程同时调用这个存储过程(数据并不存在),所以造成where逻辑通过
      

  7.   

    对uname,cname进行唯一性约束这个行,是可以不重复输入了,但程序出错,还要判断出来
      

  8.   

    试试begin tran
    select 1 from ulook with (tablockx) where 1<2
    你的语句
    commit tran
      

  9.   


    begin tran
    select 1 from ulook with (tablockx) where 1>2
    set @str=N'insert into ulook(uname,cname,addtime) SELECT a.uname,'''+@cname +''',GETDATE()
    FROM per as a WHERE CHARINDEX('',''+LTRIM(id)+'','', '','+@perid+','')>0
        AND NOT EXISTS(SELECT 1 FROM ulook WHERE uname = a.uname AND cname = '''+@cname+''')'
    exec sp_executesql  @str
    commit tran
    set @str= 'select * FROM dbo.per where dbo.per.id in ('+@perid+')'
    exec sp_executesql  @str
    在程序中无法显示出记录
      

  10.   

    在sql里运行就没事,但在程序就显示不了数据,最后还要返回数据处理
      

  11.   

    插入是可以但这句
    set @str= 'select * FROM dbo.per where dbo.per.id in ('+@perid+')'
    exec sp_executesql  @str无法返回数据
      

  12.   

    改成这样呢begin tran
    select 1 from ulook with (tablockx) where 1>2
    set @str=N'insert into ulook(uname,cname,addtime) SELECT a.uname,'''+@cname +''',GETDATE()
    FROM per as a WHERE CHARINDEX('',''+LTRIM(id)+'','', '','+@perid+','')>0
        AND NOT EXISTS(SELECT 1 FROM ulook WHERE uname = a.uname AND cname = '''+@cname+''')'
    exec sp_executesql  @str
    set @str= 'select * FROM dbo.per where dbo.per.id in ('+@perid+')'
    exec sp_executesql  @strcommit tran
    没有仔细看你的业务,其实一个插入的话,可以不用tran的
      

  13.   

    呵呵,个人习惯
    如果有大量的业务,我才用tran,否则单独一条更新没有用
      

  14.   

    蛮奇怪的 没理由sqlserver通过,前台程序调用出错的
    会不会是返回了第一个记录集(空集)
    你是用ado调用的吧,我记得ado有一个方法是用Recordset的NextRecordset 你可以试试
      

  15.   

    恩 应该是的 前面那个select语句通过 返回一个空集合,你输出的应该是这个集合