Replacing loop with set-based operation

时光毁灭记忆、已成空白 提交于 2019-12-13 01:20:44

问题


I am aware that I probably perform Row-By-Arduous-Row operations far too much. Is there an appropriate replacement for the following loop:

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:


If you want to get started with set based operations, first try to create a SELECT statement that will get back that set of rows that need to be inserted.

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)

In this case, you do not need to use a merge statement because you are only using the insert path. I invented the column clientEnabled, I suppose there would be a flag rather than just a set of client names known to be enabled.

That make sense?



来源:https://stackoverflow.com/questions/25753229/replacing-loop-with-set-based-operation

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!