14

複数の値のいずれかが含まれているかどうかについて、SQL 列の行を照会したいと考えています。

たとえば、列 A に次の単語のいずれかが含まれているテーブルの行を返します ('cow','farmer','milk')

単語が何であるかを知っていれば十分に簡単ですが、文字列の任意の配列をフィードできる sproc を書きたいと思います。特定の行の列 A にそれらのいずれかが含まれている場合、行が返されます。

私はフィードできるようにしたいと思います:

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

また

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

また

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

それは比較的簡単なはずですが、私の人生ではそれを理解することはできません. 私はSQL Server 2008を使用しています

4

6 に答える 6

16

1 つの簡単なアプローチ:

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

SQL 2008 でこれを行う最善の方法は、テーブル値パラメーターを使用することです。

于 2012-08-16T23:45:15.010 に答える
4

SQL Server は、「配列」が何であるかを認識していません。各値を行に変換し、ベース テーブルに対して結合する分割テーブル値関数を作成できますが、これは Av の回答と比較して最適ではありません。または、テーブル値パラメーターに対してテストすることもできます。TVP は、 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...
}
于 2012-08-16T23:50:46.370 に答える
3

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

簡単!

于 2012-08-17T00:22:07.977 に答える
1

配列は TSQL に存在しないため、配列をストアド プロシージャに渡すことはできません。いくつかのオプションがあります。そのうちの 2 つを紹介します。

オプション 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

このソリューションは、拡張性に優れている可能性があります。

他の人が示唆しているように、インメモリテーブル(私は個人的には避けていますが、あまり運がなかったので、常に一時テーブルよりもパフォーマンスが悪い)またはテーブルパラメーターを使用することもできますが、事前にその型を宣言する必要があります.

于 2012-08-16T23:54:03.083 に答える
-1

単純に WHERE column 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
于 2017-07-10T14:46:32.140 に答える