Как предоставить строку идентификаторов в предложении IN оператора Select, даже если столбец является целым числом - PullRequest
1 голос
/ 12 апреля 2009

Я делаю пейджинговые данные, используя ObjectDataSource, и у меня есть следующий метод:

public int GetNumberOfArticles(string employeeIds)
{
    System.Data.DataTable dataTable;
    System.Data.SqlClient.SqlDataAdapter dataAdapter;
    System.Data.SqlClient.SqlCommand command;

    int numberOfArticles = 0;

    command = new System.Data.SqlClient.SqlCommand();
    command.Connection = Classes.Database.SQLServer.SqlConnection;

    command.CommandText = @"SELECT COUNT(*)
                            FROM 
                                  [Articles]
                            WHERE 
                                  [Articles].[EmployeeID] IN (@EmployeeIds)";

    command.Parameters.AddWithValue("@EmployeeIds", employeeIds);
    numberOfArticles = (int)command.ExecuteScalar();
    return numberOfArticles;
}

EmployeeID является целым числом, и поэтому все, что я помещаю в employeeIds, будет преобразовано в целое число. Однако, поскольку я использую ключевое слово IN, очевидно, что я хочу заменить employeeIds списком идентификаторов, разделенных запятыми:

1, 2, 3

Но когда я заменяю строку:

command.Parameters.AddWithValue("@EmployeeIds", employeeIds);

с чем-то вроде:

command.Parameters.AddWithValue("@EmployeeIds", "1, 2, 3");

Я получил исключение, потому что я указал строку, а EmployeeIds - целое число. Итак, как мне это сделать?

спасибо.

Edit:

Из ответов я понимаю, что это должно быть сделано вручную, однако класс, который содержит этот метод, будет автоматически создан ObjectDataSource. Так как же я могу предоставить значения employeeIds во время выполнения?

Ответы [ 4 ]

2 голосов
/ 12 апреля 2009

Вы можете создать свой SQL-оператор следующим образом, используя конкатенацию строк:

"SELECT ... IN (@ id1, @ id2, @ id3)"

и затем:

command.Parameters.AddWithValue ("@ id1", employeeIds [0]); command.Parameters.AddWithValue ("@ id2", employeeIds [1]); command.Parameters.AddWithValue ("@ id3", employeeIds [2]);

(конечно, используя for-loop).

Таким образом, вы по-прежнему вставляете значения, используя параметры.

2 голосов
/ 12 апреля 2009

Единственный способ сделать это - проанализировать строку вручную в запросе и вставить значения в таблицу памяти, а затем соединить таблицу памяти в запросе, а не использовать предложение IN.

Например, эта страница в CodeProject представляет эту функцию:

IF EXISTS(SELECT * FROM sysobjects WHERE ID = OBJECT_ID(’UF_CSVToTable’))
 DROP FUNCTION UF_CSVToTable
GO

CREATE FUNCTION UF_CSVToTable
(
 @psCSString VARCHAR(8000)
)
RETURNS @otTemp TABLE(sID VARCHAR(20))
AS
BEGIN
 DECLARE @sTemp VARCHAR(10)

 WHILE LEN(@psCSString) > 0
 BEGIN
  SET @sTemp = LEFT(@psCSString, ISNULL(NULLIF(CHARINDEX(',', @psCSString) - 1, -1),
                    LEN(@psCSString)))
  SET @psCSString = SUBSTRING(@psCSString,ISNULL(NULLIF(CHARINDEX(',', @psCSString), 0),
                               LEN(@psCSString)) + 1, LEN(@psCSString))
  INSERT INTO @otTemp VALUES (@sTemp)
 END

RETURN
END
Go

Вы можете использовать его так:

SELECT                          
    COUNT(*)
FROM 
    [Articles]

JOIN dbo.UF_CSVToTable(@EmployeeIds) ids on ids.sID = [Articles].[EmployeeID]

В конце концов, как правило, это не очень хорошая практика. Но если это необходимо, тогда этот подход должен дать вам его довольно просто.

1 голос
/ 12 апреля 2009

Аналогично этот вопрос , вам нужно добавить параметр для каждого значения во время выполнения:

public int GetNumberOfArticles(string employeeIds)
{
    System.Data.DataTable dataTable;
    System.Data.SqlClient.SqlDataAdapter dataAdapter;
    System.Data.SqlClient.SqlCommand command;

    int numberOfArticles = 0;

    command = new System.Data.SqlClient.SqlCommand();
    command.Connection = Classes.Database.SQLServer.SqlConnection;

    string params = string.Join(",", employeeIds.Select((e, i)=> "@employeeId" + i.ToString()).ToArray());
    command.CommandText = @"SELECT                          
                               COUNT(*)
                            FROM 
                               [Articles]
                            WHERE 
                               [Articles].[EmployeeID] IN (" + params + ")";

    for (int i = 0; i < employeeIds.Length; i++) {
       command.Parameters.AddWithValue("@employeeId" + i.ToString(), employeeIds[i]);
    }

    numberOfArticles = (int)command.ExecuteScalar();

    return numberOfArticles;
}
0 голосов
/ 12 апреля 2009

Параметр - это отдельное значение, и его нельзя использовать для динамического создания оператора SQL, как вы пытаетесь это сделать. Вам нужно будет создать инструкцию SQL, используя конкатенацию строк, которая может быть простой:

command.CommandText = @"SELECT COUNT(*) FROM [Articles] " +
    "WHERE [Articles].[EmployeeID] IN (" + employeeIds + ")";

Однако вам нужно очистить строку employeeIds, если она поступает от ввода пользователя, чтобы избежать уязвимости внедрения SQL. Вы можете сделать это, разбив строку на массив и проанализировав каждый элемент, чтобы убедиться, что это int. Если он проходит, вы можете повторно объединить массив в строку перед объединением.

...