0

我有一个参数,其中包含用分号分隔的多个项目。我需要在 IN 子句中使用这些项目。例如:

parItems = 'item1;;item2;;item3'

然后我需要添加到这样的sql:

SELECT somestuff, morestuff FROM sometable WHERE item in (parItems)

有没有简单的方法来完成这项工作?

对不起。正如我之前所说,它将在 Reporting Services 上查看 MSSQL DB 而不是 Oracle ODBC

4

5 回答 5

1

你可以。但是你需要一些基础设施。

您需要在 SQL 中定义的集合类型。假设每一项不超过 100 字节

CREATE TYPE item_arr
    AS TABLE OF varchar2(100);

然后,您需要一个函数来解析分号分隔的列表并返回此集合类型。我会使用 Tom Kyte 的in_list 函数的变体

create or replace function in_list( p_items in varchar2 )
  return item_arr
as
  l_string varchar2(32000) := p_items || ';';
  l_items  item_arr := item_arr();
  l_pos    number;
begin
  loop
     exit when l_string is null;
     l_pos := instr( l_string, ';' );
     l_items.extend;
     l_items(l_items.count) :=
                 ltrim( rtrim( substr( l_string, 1, l_pos-1 ) ) );
     l_string := substr( l_string, l_pos+1 );
  end loop;
  return l_items;
end;

然后,您可以在 SQL 语句中使用此函数

SELECT somestuff, morestuff 
  FROM sometable 
 WHERE item in (SELECT column_value
                  FROM TABLE( in_list( parItems )))
于 2012-08-07T15:27:33.560 回答
1

只需解析您的字符串以替换;;with ',',您就可以将其直接传递给IN ('...')语句。

'item1;;item2;;item3'-->'item1','item2','item3'

最简单的方法是在将字符串作为参数传递之前对其进行转换。

像这样:IN ('item1','item2','item3')

于 2012-08-07T15:24:30.803 回答
0
Use AsG
Go
Drop FUNCTION AsG_inListesiOlustur
Go
CREATE FUNCTION AsG_inListesiOlustur (@pDegerListesi nvarchar(MAX), @pBossaVarsayilanDeger varchar(50))
   RETURNS @pNeticeTablo TABLE (Deger varchar(50) NOT NULL) AS
BEGIN
   DECLARE @Pozisyon        int,
           @sonrakiPozisyon    int,
           @uzunluk   int

   SELECT @Pozisyon = 0, @sonrakiPozisyon = 1
   Select @pDegerListesi = LTRIM(RTRIM(@pDegerListesi))
   If LEN(@pDegerListesi) = 0
     Begin
     If LEN(@pBossaVarsayilanDeger) > 0 
       Begin
       INSERT @pNeticeTablo (Deger) VALUES (@pBossaVarsayilanDeger)
       End
     End Else
     Begin   
     WHILE @sonrakiPozisyon > 0
       BEGIN
       SELECT @sonrakiPozisyon = CharIndex(',', @pDegerListesi, @Pozisyon + 1)
       SELECT @uzunluk = CASE WHEN @sonrakiPozisyon > 0
                              THEN @sonrakiPozisyon
                              ELSE Len(@pDegerListesi) + 1
                         END - @Pozisyon - 1
       INSERT @pNeticeTablo (Deger)
          VALUES (Convert(varchar, SubString(@pDegerListesi, @Pozisyon + 1, @uzunluk)))
       SELECT @Pozisyon = @sonrakiPozisyon
       End
     End
   RETURN
END
Go

Select * From  [AsG].[dbo].[AsG_inListesiOlustur]('1,4', '0')
Go

Select * From  [AsG].[dbo].[AsG_inListesiOlustur]('', '')
Go
于 2013-01-14T14:09:18.873 回答
0

如果列表相对较短(即少于 4000 个字符),另一种方法是使用 INSTR 函数:

SELECT somestuff, morestuff FROM sometable
WHERE INSTR( ';;' || parItems || ';;'
           , ';;' || item || ';;'
           ) > 0;

然而,这种方法的主要缺点是谓词没有选择性。然而,根据数据量,这并不总是一个问题。

于 2012-08-08T01:56:08.077 回答
0

这是另一个变体;类似于贾斯汀的回答,但对于 SQL Server:

下面的函数将返回一个可以加入的表。

CREATE FUNCTION listToTable (@list nvarchar(MAX))
   RETURNS @tbl TABLE (item varchar(50) NOT NULL) AS
BEGIN
   DECLARE @pos        int,
           @nextpos    int,
           @valuelen   int

   SELECT @pos = 0, @nextpos = 1

   WHILE @nextpos > 0
   BEGIN
      SELECT @nextpos = charindex(';', @list, @pos + 1)
      SELECT @valuelen = CASE WHEN @nextpos > 0
                              THEN @nextpos
                              ELSE len(@list) + 1
                         END - @pos - 1
      INSERT @tbl (item)
         VALUES (convert(varchar, substring(@list, @pos + 1, @valuelen)))
      SELECT @pos = @nextpos
   END
   RETURN
END

SELECT somestuff, morestuff 
FROM sometable a
join listToTable('item1;item2;item3') b
on a.columnA = b.item
于 2012-08-07T18:49:29.127 回答