SQL删除不在的地方

时间:2009-02-03 23:43:41

标签: sql sql-server

我有一个像这样的关系映射表:

attributeid bigint
productid bigint

要清除不再使用的关系,我想删除所有recctid = x和attributeid不在(@includedIds)的recor,如下例所示:

@attributetypeid bigint, 
@productid bigint,
@includedids varchar(MAX)  


DELETE FROM reltable 
WHERE productid = @productid AND 
attributetypeid = @attributetypeid AND 
attributeid NOT IN (@includedids);

当运行带有包含多于1个id的includedids param的SQL时 - 就像这样:25,26 - 我得到一个SqlException说:

将数据类型varchar转换为bigint时出错。

这当然是由于varchar(max)参数...

我应该如何构建我的删除语句以使其工作?

5 个答案:

答案 0 :(得分:2)

  SET QUOTED_IDENTIFIER ON
  GO
  CREATE FUNCTION [dbo].[ListToTable] (
  /*
  FUNCTION ListToTable
  Usage: select entry from listtotable('abc,def,ghi') order by entry desc
  PURPOSE: Takes a comma-delimited list as a parameter and returns the values of that list into a table variable.
  */
  @mylist varchar(8000)
  )
  RETURNS @ListTable TABLE (
  seqid int not null,
  entry varchar(255) not null)

  AS

  BEGIN
      DECLARE 
          @this varchar(255), 
          @rest varchar(8000),
          @pos int,
          @seqid int

      SET @this = ' '
      SET @seqid = 1
      SET @rest = @mylist
      SET @pos = PATINDEX('%,%', @rest)
      WHILE (@pos > 0)
      BEGIN
          set @this=substring(@rest,1,@pos-1)
          set @rest=substring(@rest,@pos+1,len(@rest)-@pos)
          INSERT INTO @ListTable (seqid,entry)  VALUES (@seqid,@this)
          SET @pos= PATINDEX('%,%', @rest)
          SET @seqid=@seqid+1
      END
      set @this=@rest
      INSERT INTO @ListTable (seqid,entry) VALUES (@seqid,@this)
      RETURN 
  END

在SQL Server数据库中运行该脚本以创建函数ListToTable。现在,您可以像这样重写查询:

@attributetypeid bigint, 
@productid bigint,
@includedids varchar(MAX)  


DELETE FROM reltable 
WHERE productid = @productid AND 
attributetypeid = @attributetypeid AND 
attributeid NOT IN (SELECT entry FROM ListToTable(@includedids));

其中@includedids是您提供的逗号分隔列表。我在处理列表时一直使用此函数。请记住,此函数不一定要清理您的输入,它只是在逗号分隔列表中查找字符数据并将每个元素放入记录中。希望这会有所帮助。

答案 1 :(得分:1)

Joel Spolsky在这里回答了一个非常相似的问题:Parameterize an SQL IN clause

你可以尝试类似的东西,确保将你的attributetypeid转换为varchar。

答案 2 :(得分:1)

您无法将列表作为参数传递(AFAIK)。

你能否重写sql以使用子查询,如下所示:

delete from reltable
WHERE productid = @productid AND 
attributetypeid = @attributetypeid AND 
attributeid NOT IN (select id from ... where ... );

答案 3 :(得分:0)

可以将逗号分隔的列表发送到用户定义的函数,该函数将其作为简单表返回。然后可以通过NOT IN查询该表。 如果你需要fn,我可以提供..自从我使用sql以来已经大约5年了,我将不得不把我脑部的那部分弄脏......

答案 4 :(得分:0)

Erland拥有definitive guide来处理SQL 2005中的表列表,SQL 2008为您提供table based params

在旁注中我会避免大型列表的NOT IN模式,因为它不会缩放,而是使用左连接。