2012-08-16 743 views
3

我想查询SQL列的行是否包含多个值中的任何一个。查询SQL字段是否包含多个值中的任何一个

例如,返回其列A包含以下任一字的表的行: ('cow','farmer','milk')

当你知道这些单词是什么时候足够简单,但我想写一个可以在任何字符串数组中进行提交的存储过程,并且如果特定行的列A包含它们中的任何一个,它将返回该行。

我希望能在养活:

('cow','farmer','milk')

('cow','farmer','steak','yikes')

('cow','farmer','three', 'pigs', 'wolf') 

它必须是相对简单的,但我不能为了我的生活而形成它出。 我SQL Server 2008上

+0

能否请你告诉样本数据?例如。该表是否在每一行中包含单个值,或者该表是否可以包含像“cow,milk”这样的字符串? – 2012-08-17 00:00:45

+0

对不起,数据将是整个句子,我想看看是否有任何这些单词存在。 – Matt 2012-08-17 00:02:26

+0

您可以尝试我的解决方案,只需将JOIN更改为LIKE而不是=。现在无法从手机正确编辑。 – 2012-08-17 00:07:09

回答

9

一个简单的方法:

declare @candidates varchar = '|cow|farmer|three|pigs|wolf|' 
select * from TableName where @candidates like '%|' + FieldName + '|%' 

在2008年SQL做到这一点,最好的办法是用table-valued parameter

+0

+1 - 对这个问题的下意识反应是使用分裂函数,但在这种情况下,它不是必需的。我会说'LIKE'仍然比TVP更有效率,但我不确定,因为我没有直接在这个用例中测试过这些,我仍然会发布一个TVP答案,因此OP可以测试。 – 2012-08-16 23:47:23

+3

我认为OP想要FieldName *包含的行中的一个单词 - 这将检查FieldName *是否等于*其中一个单词。 – Blorgbeard 2012-08-16 23:52:10

+0

@Blorgbeard我还将“_包含多个values_中的任何一个”解释为“其值与任何值相对应”,但您可能是对的。 – Diego 2012-08-16 23:56:19

3

SQL Server不知道“数组”是什么。您可以编写一个拆分表值函数,将每个值转换为一行,然后与基表连接,但与Av的答案相比,这绝对是次优的。或者你可以对一个表值参数进行测试。 TVP是definitely the best performer compared to all of the splitting techniques, even CLR

CREATE TYPE dbo.FarmItems AS TABLE(Item VARCHAR(32)); 
GO 

CREATE PROCEDURE dbo.FindFarmItems 
    @List dbo.FarmItems READONLY 
AS 
BEGIN 
    SET NOCOUNT ON; 

    SELECT t.col1, t.col2, ... 
    FROM dbo.table AS t 
    INNER JOIN @List AS L 
    ON t.columnA = L.Item; 
END 
GO 

然后在C#中,你只是构建一个DataTable你的“阵列”,并传递它:

DataTable dt = new DataTable(); 
dt.Columns.Add("Item", typeof(string)); 
dt.Rows.Add("cow"); 
dt.Rows.Add("farmer"); 
... 

using (SqlConnection conn = new ...) 
{ 
    SqlCommand c = new SqlCommand("dbo.FindFarmItems", conn); 
    2.CommandType = CommandType.StoredProcedure; 
    SqlParameter tvp = c.Parameters.AddWithValue("@List", dt); 
    tvp.SqlDbType = SqlDbType.Structured; 
    // execute, get a reader, etc... 
} 
1

你不能传递数组存储过程,数组不存在TSQL 。你有几个选择,我给你两个。

选项1 - 快速和肮脏(我不推荐)
值传递的字符串,并将其添加到动态SQL语句。

CREATE PROCEDURE MyProc 
    @Values varchar(1000) 
AS 

DECLARE @SQL VARCHAR(2000) 

SET @SQL = 'SELECT blahblah WHERE SomeField IN (' + @Values + ')' 

-- Execute the statement and return the result 

END 

除了明显的SQL注入漏洞,这种方法不适用于大集合,它也不会执行得太好。而且,如果任何值包含逗号,它将不起作用。我真的不推荐它,但它可能对快速测试有用。

选项2 - 一个更灵活的解决方案
商店都在一个临时表,你会在你的存储过程中引用你的价值观。

CREATE TABLE #MyTempTable 
-- Fields... 

INSERT INTO #MyTempTable 
-- Insert the values 

CREATE PROCEDURE MyProc 
    @Values varchar(1000) 
AS 

SELECT 
    SomeFields 
FROM 
    MyTable 
    JOIN 
    #MyTempTable ON 
    -- Add join clause 

END 

该解决方案可能会更好地扩展。

正如其他人所建议的那样,您也可以使用内存表(我个人避免,因为我从来没有很多运气,他们总是比临时表执行更差)或表参数,但是你必须事先声明其类型。

+0

随着新的信息,第一个解决方案不起作用,因为你不能像IN一样组合。对于第二个,代码的关键部分完全缺失 - 如何将值的数组(大概来自应用程序)放入#temp表中。 – 2012-08-17 00:09:23

+0

OP在原文中没有写“LIKE”,因此我没有使用它。显然,现在他澄清了他的需求,我的解决方案不再适用。 – Diego 2012-08-17 00:12:45

1

您可以使用XML数据类型列表数据传递给您的存储过程:

create procedure dbo.LookItUp 

    @idList xml 

as 

    declare @lookup table 
    (
    id int not null 
) 

    insert @lookup (id) 
    select distinct t.id.value('.','int') 
    from @idList.nodes('/ids/id') as t(id) 
    where t.id is not null 

    select * 
    from dbo.my_data_table t 
    join @lookup   lu on lu.id = t.object_id 

    return 0 
go 

轻松!

0

我有同样的困境,并提出以下。例如,如果表-A包含(“我的牛”,“我的羊”,“我的狗”)和表-B包含(“狗”,“牛”),然后...

create table #table_a (field1 varchar(128)) 
insert into #table_a values('My Cow') 
insert into #table_a values('My Goat') 
insert into #table_a values('My Dog') 

create table #table_b (field1 varchar(128)) 
insert into #table_b values('Dog') 
insert into #table_b values('Cow') 

select * from #table_a table_a where (select count(*) from #table_b table_b where charindex(table_b.field1, table_a.field1) > 0) > 0 

返回(“我的牛','我的狗')

希望这会有所帮助。

0

您可以简单地使用WHERE IN(昏迷分隔的字符串)

这里列是我的完整例子,如何做到这一点:

create table #bar (foo varchar(20)) 

insert into #bar (foo) values('cow') 
insert into #bar (foo) values('cat') 

select foo from #bar 
where foo in ('cow','farmer','milk') 

drop table #bar 
相关问题