簡體   English   中英

將IN運算符與存儲過程參數一起使用

[英]Using IN operator with Stored Procedure Parameter

我正在ASP.NET 2.0中構建一個網站,正在處理我正在處理的頁面的一些描述:ListView顯示訪問數據庫中的表格(包含帖子),以及具有用於過濾行的多重選擇模式的ListBox(按論壇名稱, value = forumId)。 我將ListBox選定的值轉換為List,然后運行以下查詢。

參數:

OleDbParameter("@Q",list.ToString());

程序:

SELECT * FROM sp_feedbacks WHERE forumId IN ([@Q])

問題是,這行不通。 即使當我從MSACCESS 2007使用字符串1,4,“ 1”,“ 4”或“ 1,4”運行它時,我也得到零結果。 僅選擇一個論壇時,查詢有效。 (例如,在(1)中)。

  • 解? 所以我想我可以將WHERE與許多OR一起使用,但我真的很想避免使用此選項。 另一個解決方案是將DataTable轉換為列表,然后使用LINQ對其進行過濾,這似乎很麻煩。

預先感謝,BBLN。

我在這里看到2個問題:1)list.ToString()並沒有達到您的期望。 嘗試這個:

List<int> foo = new List<int>();
foo.Add(1);
foo.Add(4);
string x = foo.ToString();

“ x”的值將是“ System.Collections.Generic.List`1 [System.Int32]”而不是“ 1,4”。要創建用逗號分隔的列表,請使用string.Join()。

2)OleDbParameter無法理解數組或列表。 您必須做其他事情。 讓我解釋:

假設您成功使用string.Join()創建參數。 產生的SQL將是:

SELECT * FROM sp_feedbacks WHERE forumId IN ('1,4')

OLEDB提供者知道字符串必須在字符串周圍帶有引號。 這是為了保護您免受SQL注入攻擊。 但是您不想傳遞一個字符串:您想傳遞一個數組或一個原義不變的值來傳遞給SQL。

您不是第一個提出這個問題的人,但是恐怕OLEDB並沒有很好的解決方案。 如果是我,我將完全放棄OLEDB並使用動態SQL。 但是,通過Google搜索“參數化SQL數組”,可以在Stack Overflow上找到一些非常好的解決方案:

在哪里(ID數組)

將參數數組傳遞給存儲過程

祝好運! 發布您采用哪種方法!

當你有:

col in ('1,4')

這測試col等於字符串'1,4' 它不會單獨測試這些值。

解決此問題的一種方法是使用like

where ','&@Q&',' like '*,'&col&',*'

這個想法是給每個字符串添加定界符。 因此,該列中的值“ 1”變為“,1”。 @Q的值“ 1,4”變為“,1,4,”。 現在,當您進行比較時,不存在“ 1”與“ 10”匹配的危險。

注意(對於那些不知道的人)。 like的通配符是*而不是SQL標准% 但是,這可能取決於您的連接方式,因此請使用適當的通配符。

將這樣的條件傳遞給查詢始終是一個問題。 對於存儲過程來說,情況更糟,因為您甚至無法調整查詢以適應需求。 當前有2個選項:

  • 使用表值參數並以這種方式傳遞多個值(說實話,有點麻煩)
  • 作為UDF或通過SQL / CLR編寫“拆分”多值函數,然后從查詢中調用

作為記錄,“ dapper”通過以下方式使原始命令(而不是sproc)的操作變得容易:

int[] ids = ...
var list = conn.Query<Foo>(
    "select * from Foo where Id in @ids",
    new { ids } ).ToList();

它弄清楚了如何將其轉換為參數等。

以防萬一有人在尋找SQL Server解決方案:

CREATE FUNCTION [dbo].[SplitString]
(    
  @Input NVARCHAR(MAX),
  @Character CHAR(1)
)
RETURNS @Output TABLE (
  Item NVARCHAR(1000)
)
  AS BEGIN
  DECLARE @StartIndex INT, @EndIndex INT

  SET @StartIndex = 1
  IF SUBSTRING(@Input, LEN(@Input) - 1, LEN(@Input)) <> @Character
  BEGIN
        SET @Input = @Input + @Character
  END

  WHILE CHARINDEX(@Character, @Input) > 0
  BEGIN
        SET @EndIndex = CHARINDEX(@Character, @Input)

        INSERT INTO @Output(Item)
        SELECT SUBSTRING(@Input, @StartIndex, @EndIndex - 1)

        SET @Input = SUBSTRING(@Input, @EndIndex + 1, LEN(@Input))
  END

  RETURN
END

給定一個字符串數組,我將使用以下代碼將其轉換為逗號分隔的字符串列表

var result = string.Join(",", arr);

然后我可以按如下方式傳遞參數

Command.Parameters.AddWithValue("@Parameter", result);

在存儲過程定義中,我將使用上面的參數,如下所示

select * from [dbo].[WhateverTable] where [WhateverColumn] in (dbo.splitString(@Parameter, ','))

暫無
暫無

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

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