Замена цикла с помощью операции на основе набора

Мне известно, что я, вероятно, слишком много выполняю операции "ряд за трудом". Есть ли подходящая замена для следующего цикла:

DECLARE @clientId int;
DECLARE @enabledClients TABLE(id int); --Some clients will have this setting enabled by default
DECLARE @enabled nvarchar(10);

SET @clientId = (SELECT MIN(clientId) FROM dbo.Client);

INSERT INTO @enabledClients (id) SELECT [id] FROM dbo.Client WHERE name IN ('FOO', 'BAR');

WHILE @clientId IS NOT NULL
BEGIN
    SET @enabled = ISNULL((SELECT 'true' from @enabledClients where id = @clientId), 'false');
     MERGE INTO [dbo].[ClientSetting] AS Target
        USING (VALUES('EnableReports', @enabled)) AS SOURCE ([Key], [Value])
        ON (Target.[clientId] = @clientId AND Target.[Key] = Source.[Key])
    WHEN NOT MATCHED THEN
        INSERT ([ClientId], [Key], [Value])
        VALUES (@clientId, SOURCE.[Key], SOURCE.[Value])
    SET @clientId = (SELECT MIN(clientId) FROM dbo.Client WHERE clientId > @clientId);
END

1 ответ

Решение

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

INSERT INTO [dbo].[ClientSetting]([ClientId], [Key], [Value])
     SELECT id, 'EnableReports', clientEnabled FROM dbo.Clients
        WHERE not exists (SELECT 1 from [dbo].[ClientSetting] cs
                            WHERE cs.clientid = clients.id)

В этом случае вам не нужно использовать оператор слияния, потому что вы используете только путь вставки. Я изобрел столбец clientEnabled, я полагаю, что будет флаг, а не просто набор имен клиентов, о которых известно, что они включены.

Это имеет смысл?

Другие вопросы по тегам