SQL-поиск по нескольким спискам значений для нескольких столбцов - PullRequest
0 голосов
/ 09 октября 2018

У меня может быть слегка наивный вопрос, но я никогда раньше не работал с базами данных.Я инженер .NET и использую Dapper для доступа к базе данных SQL Server.

Ситуация следующая: у меня есть денормализованная таблица для сохранения нескольких типов объектов.У каждого есть составной ключ (type, id, owner_id), и каждая строка ключа имеет строковый тип (но это не важно).И, скажем, я пишу в базу много интересов для разных пользователей (Bulk post).Чтобы они не повторялись, мне нужно сделать запрос и определить, какие уже присутствуют в базе данных.

Итак, у меня есть этот код в моем InterestService классе:

private IEnumerable<Interest> GetAlreadyExistingInterestsFor(IEnumerable<Interest> interestsForCreating) =>
    _interestRepository.GetInterests(interestsForCreating.Select(interest => interest.Id).ToList(),
                                     interestsForCreating.Select(interest => interest.UserId).ToList());

После этого у меня есть немного логики и так далее.Это не важно.

InterestRepository метод GetInterests выглядит следующим образом:

public GetInterests(IList<string> interestIds, IList<string> userIds) 
{
    var query = @"SELECT type, id, owner_id
                  FROM entities
                  WHERE type = 'interest'
                   AND id IN @InterestIds
                   AND owner_id IN @UserIds";
    return _dbContext.ExecuteQuery(query, new { InterestIds = interestIds, UserIds = userIds });
}

Код может содержать ошибки, потому что сейчас у меня нет возможности получить доступ к рабочей средено я думаю, что идея ясна.Итак, вопрос в том, является ли это лучшим подходом к выполнению запроса.А если есть лучшее, то что это.

Ответы [ 2 ]

0 голосов
/ 10 октября 2018

Если stored procedure не вариант, вы можете использовать один из следующих методов.

  1. Преобразуйте ваши interestIds и userIds в строки
    string interests = "(1, 2, 3, 4)", если списки содержат только цифры, или ('a1', 'b1', 'c2'), если они являются строками.

Затем просто вставьте их в свой запрос

var query = @"SELECT type, id, owner_id
              FROM entities
              WHERE type = 'interest'
               AND id IN "+ interests
               + " AND owner_id IN " + users;

Этот метод считается плохой практикой и является приглашением к атаке с использованием SQL-инъекций (в случае ввода данных пользователем).Используйте его если вы абсолютно уверены в своих данных.

SQL Server 2016+ имеет встроенную функцию string_split, которую можно использовать здесь.Функция разбивает строку с разделителями на таблицу t(value).
Снова преобразует списки в строки string interests="a1, a2, b3, c4"; (здесь нет ни одной кавычки)

и запрос

var query = @"SELECT type, id, owner_id
              FROM entities
              WHERE type = 'interest'
               AND id IN (select value from string_split(@interests,','))
               AND owner_id IN (select value from string_split(@users,','))";

Для более ранних версий вы можете создать UDF с той же функциональностью.

create function dbo.split_string(@input varchar(max), @separator varchar(2))
returns table as
return
(with cte as(
select cast('<v>'+ REPLACE(@input, @separator, '</v><v>') +'</v>' as xml) x
)
select t.v.value('.[1]', 'varchar(max)') [value]
from cte
cross apply x.nodes('v') t(v))
0 голосов
/ 09 октября 2018

По сути, вы можете просто делать именно то, что было сделано в этом посте, но с двумя наборами вместо 1 для табличного параметра. Используя Dapper, как передать значения для типа SQL в качестве параметра?

Он использует хранимую процедуру и табличный параметр SQL.

...