我有一个参数,其中包含用分号分隔的多个项目。我需要在 IN 子句中使用这些项目。例如:
parItems = 'item1;;item2;;item3'
然后我需要添加到这样的sql:
SELECT somestuff, morestuff FROM sometable WHERE item in (parItems)
有没有简单的方法来完成这项工作?
对不起。正如我之前所说,它将在 Reporting Services 上查看 MSSQL DB 而不是 Oracle ODBC
我有一个参数,其中包含用分号分隔的多个项目。我需要在 IN 子句中使用这些项目。例如:
parItems = 'item1;;item2;;item3'
然后我需要添加到这样的sql:
SELECT somestuff, morestuff FROM sometable WHERE item in (parItems)
有没有简单的方法来完成这项工作?
对不起。正如我之前所说,它将在 Reporting Services 上查看 MSSQL DB 而不是 Oracle ODBC
你可以。但是你需要一些基础设施。
您需要在 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 )))
只需解析您的字符串以替换;;
with ','
,您就可以将其直接传递给IN ('...')
语句。
'item1;;item2;;item3'
-->'item1','item2','item3'
最简单的方法是在将字符串作为参数传递之前对其进行转换。
像这样:IN ('item1','item2','item3')
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
如果列表相对较短(即少于 4000 个字符),另一种方法是使用 INSTR 函数:
SELECT somestuff, morestuff FROM sometable
WHERE INSTR( ';;' || parItems || ';;'
, ';;' || item || ';;'
) > 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