C#コードからSQL Serverストアドプロシージャを呼び出しています。
using (SqlConnection conn = new SqlConnection(connstring))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand("InsertQuerySPROC", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
var STableParameter = cmd.Parameters.AddWithValue("@QueryTable", QueryTable);
var NDistanceParameter = cmd.Parameters.AddWithValue("@NDistanceThreshold", NDistanceThreshold);
var RDistanceParameter = cmd.Parameters.AddWithValue(@"RDistanceThreshold", RDistanceThreshold);
STableParameter .SqlDbType = SqlDbType.Structured;
NDistanceParameter.SqlDbType = SqlDbType.Int;
RDistanceParameter.SqlDbType = SqlDbType.Int;
// Execute the query
SqlDataReader QueryReader = cmd.ExecuteReader();
私のストアドプロシージャはかなり標準ですが、QueryTable
との結合を行います(したがって、ストアドプロシージャを使用する必要があります)。
ここで、文字列のリストList<string>
をパラメーターセットに追加します。たとえば、ストアドプロシージャクエリは次のようになります。
SELECT feature
FROM table1 t1
INNER JOIN @QueryTable t2 ON t1.fid = t2.fid
WHERE title IN <LIST_OF_STRINGS_GOES_HERE>
ただし、文字列のリストは動的で数百の長さです。
文字列のリストList<string>
をストアドプロシージャに渡す方法はありますか?または、これを行うより良い方法はありますか?
ありがとう、ブレット
SQL Server 2008を使用している場合、ユーザー定義テーブルタイプと呼ばれる新しい機能があります。使用方法の例を次に示します。
ユーザー定義テーブルタイプを作成します。
CREATE TYPE [dbo].[StringList] AS TABLE(
[Item] [NVARCHAR](MAX) NULL
);
次に、ストアドプロシージャで適切に使用する必要があります。
CREATE PROCEDURE [dbo].[sp_UseStringList]
@list StringList READONLY
AS
BEGIN
-- Just return the items we passed in
SELECT l.Item FROM @list l;
END
最後に、C#で使用するいくつかのsqlを示します。
using (var con = new SqlConnection(connstring))
{
con.Open();
using (SqlCommand cmd = new SqlCommand("exec sp_UseStringList @list", con))
{
using (var table = new DataTable()) {
table.Columns.Add("Item", typeof(string));
for (int i = 0; i < 10; i++)
table.Rows.Add("Item " + i.ToString());
var pList = new SqlParameter("@list", SqlDbType.Structured);
pList.TypeName = "dbo.StringList";
pList.Value = table;
cmd.Parameters.Add(pList);
using (var dr = cmd.ExecuteReader())
{
while (dr.Read())
Console.WriteLine(dr["Item"].ToString());
}
}
}
}
これをSSMSから実行するには
DECLARE @list AS StringList
INSERT INTO @list VALUES ('Apple')
INSERT INTO @list VALUES ('Banana')
INSERT INTO @list VALUES ('Orange')
-- Alternatively, you can populate @list with an INSERT-SELECT
INSERT INTO @list
SELECT Name FROM Fruits
EXEC sp_UseStringList @list
この状況の典型的なパターンは、コンマで区切られたリストで要素を渡し、SQLでそれを使用可能なテーブルに分割することです。ほとんどの人は通常、次のような指定された関数を作成します。
INSERT INTO <SomeTempTable>
SELECT item FROM dbo.SplitCommaString(@myParameter)
そして、他のクエリで使用できます。
いいえ、配列/リストをSQL Serverに直接渡すことはできません。
次のオプションが利用可能です。
はい、ストアドプロシージャパラメータをVARCHAR(...)
として作成し、コンマ区切りの値をストアドプロシージャに渡します。
Sql Server 2008を使用している場合、TVPを活用できます( テーブル値パラメーター ): SQL 2008 TVPおよびLINQ QueryTableの構造が文字列の配列よりも複雑な場合SQl Server内でテーブルタイプを作成する必要があるため、やり過ぎ
SQLでCSVリストを分割する場合は、 共通テーブル式 (CTE)を使用して別の方法で分割できます。 CTEを使用して文字列を分割する効率的な方法 を参照してください。
Listの代わりに1つの列でデータテーブルを作成し、テーブルに文字列を追加します。このデータテーブルを構造化タイプとして渡し、テーブルのタイトルフィールドと別の結合を実行できます。
私が知っている唯一の方法は、CSVリストを作成し、それを文字列として渡すことです。次に、SP側で、分割して必要なことを行います。
CREATE TYPE [dbo].[StringList1] AS TABLE(
[Item] [NVARCHAR](MAX) NULL,
[counts][nvarchar](20) NULL);
tYPEをテーブルとして作成し、「StringList1」という名前を付けます
create PROCEDURE [dbo].[sp_UseStringList1]
@list StringList1 READONLY
AS
BEGIN
-- Just return the items we passed in
SELECT l.item,l.counts FROM @list l;
SELECT l.item,l.counts into tempTable FROM @list l;
End
上記の手順を作成し、「UserStringList1」という名前を付けます
String strConnection = ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString.ToString();
SqlConnection con = new SqlConnection(strConnection);
con.Open();
var table = new DataTable();
table.Columns.Add("Item", typeof(string));
table.Columns.Add("count", typeof(string));
for (int i = 0; i < 10; i++)
{
table.Rows.Add(i.ToString(), (i+i).ToString());
}
SqlCommand cmd = new SqlCommand("exec sp_UseStringList1 @list", con);
var pList = new SqlParameter("@list", SqlDbType.Structured);
pList.TypeName = "dbo.StringList1";
pList.Value = table;
cmd.Parameters.Add(pList);
string result = string.Empty;
string counts = string.Empty;
var dr = cmd.ExecuteReader();
while (dr.Read())
{
result += dr["Item"].ToString();
counts += dr["counts"].ToString();
}
c#で、これを試してください