簡體   English   中英

C# SQL 服務器 - 將列表傳遞給存儲過程

[英]C# SQL Server - Passing a list to a stored procedure

我從我的 C# 代碼調用 SQL 服務器存儲過程:

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

最后這里有一些 sql 在 c# 中使用它:

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 中將其拆分為您可以使用的表。 大多數人通常會創建一個指定的 function 來執行此操作,例如:

 INSERT INTO <SomeTempTable>
 SELECT item FROM dbo.SplitCommaString(@myParameter)

然后您可以在其他查詢中使用它。

不,數組/列表不能直接傳遞給 SQL 服務器。

可以使用以下選項:

  1. 傳遞一個逗號分隔的列表,然后在 SQL 中有一個 function 拆分列表。 逗號分隔的列表很可能會作為 Nvarchar() 傳遞
  2. 傳遞 xml 並在 SQL 中具有 function
  3. 使用新定義的用戶定義表類型 (SQL 2008)
  4. 動態構建 SQL 並將原始列表作為“1,2,3,4”傳遞並構建 SQL 語句。 這很容易受到 SQL 注入攻擊,但它會起作用。

是的,將 Stored proc 參數設為VARCHAR(...)然后將逗號分隔的值傳遞給存儲過程。

If you are using Sql Server 2008 you can leverage TVP ( Table Value Parameters ): SQL 2008 TVP and LINQ if structure of QueryTable more complex than array of strings otherwise it would be an overkill because requires table type to be created within SQl Server

用一列而不是 List 創建一個數據表,並將字符串添加到表中。 您可以將此數據表作為結構化類型傳遞,並與表的標題字段執行另一個連接。

如果您更喜歡在 SQL 中拆分 CSV 列表,則可以使用公用表表達式(CTE) 來執行此操作。 請參閱使用 CTE 進行字符串拆分的有效方法

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" s

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# 中,試試這個

我知道的唯一方法是構建 CSV 列表,然后將其作為字符串傳遞。 然后,在 SP 方面,只需拆分它並做任何你需要的事情。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM