sql - 如何防止此 SQL 脚本进入无限循环?
问题描述
我有两个带列的表
- 用户:id、linkedinID、stackoverflowId、bitbucketid、bitbucketid、githubid
- 简历:id、userid、linkedId、stackoverflowId、bitbucketid、bitbucketid、githubid、excludeprofile(布尔类型)
我想将所有 id(userId、linkedIn 等)传输到users
表列,如果恢复表中没有一个 Id,则将 true 存储在 excludeprofile 中。
我为此编写了以下脚本
BEGIN TRANSACTION
DECLARE @userId Int
DECLARE @linkedIn varchar(max)
DECLARE @StackOverflow varchar(max)
DECLARE @HackerRank varchar(max)
DECLARE @Bitbucket varchar(max)
DECLARE @Github varchar(max)
DECLARE @x int
SET @x = 0
WHILE @x <> (SELECT COUNT(*) FROM Users)
BEGIN
IF NOT EXISTS (SELECT id FROM Users
ORDER BY Id OFFSET @x ROWS
FETCH NEXT 1 ROWS ONLY)
BEGIN
SET @userId = (SELECT TOP 1 id FROM Users)
SET @x = @x + 1;
END
IF (@userId <> NULL)
BEGIN
IF EXISTS (SELECT LinkedInProfile FROM Resumes WHERE Resumes.UserId = @userId)
BEGIN
SET @linkedIn = (SELECT LinkedInProfile FROM Resumes WHERE Resumes.UserId = @userId)
END
if exists(select Github from Resumes where Resumes.UserId=@userId)
begin
set @Github =(select Github from Resumes where Resumes.UserId=@userId)
end
if exists(select Bitbucket from Resumes where Resumes.UserId=@userId)
begin
set @Bitbucket =(select Bitbucket from Resumes where Resumes.UserId=@userId)
end
if exists(select HackerRank from Resumes where Resumes.UserId=@userId)
begin
set @HackerRank =(select HackerRank from Resumes where Resumes.UserId=@userId)
end
if exists(select StackOverflow from Resumes where Resumes.UserId=@userId)
begin
set @StackOverflow =(select StackOverflow from Resumes where Resumes.UserId=@userId)
end
end
END
if(@linkedIn!=null)
begin
update Users set LinkedInProfile=@linkedIn
where Users.Id = @userId;
end
if(@linkedIn <> null or @Bitbucket <> null or @Github = null or @StackOverflow = null or @HackerRank = null)
begin
update Resumes set ExcludeProfiles=0
where Resumes.UserId = @userId;
end
if(@linkedIn = null and @Bitbucket = null and @Github = null and @StackOverflow = null and @HackerRank = null)
begin
update Resumes set ExcludeProfiles=0
where Resumes.UserId = @userId;
end
COMMIT TRANSACTION
我认为循环是无限的,因为执行没有停止。
解决方案
就像评论中的每个人已经指出的那样:这些操作不需要WHILE
循环或光标。
创建目标表
declare @User table
(
Id int, --User
LI_id int, --LinkedIn
SO_id int, --StackOverflow
BB_id int, --BitBucket
GH_id int --GitHub
);
declare @Resume table
(
Id int,
Us_id int, --User (1*)
LI_id int, --LinkedIn (2*)
SO_id int, --StackOveflow (3*)
BB_id int, --BitBucket (4*)
GH_id int, --GitHub (5*)
Excl bit --ExcludeProfile
);
解决方案 1
将恢复行标记为默认不排除 ( Excl = 0
)。执行此操作的正确方法是在表定义中使用列默认值。
insert into @Resume (Id, Us_id, LI_id, SO_id, BB_id, GH_id, Excl) values
(1, 101, 201, 301, 401, 501, 0),
(2, 102, null, 302, 402, 502, 0),
(3, 103, 203, 303, 403, 503, 0),
(4, null, null, null, null, null, 0); --resume without id's
然后可以通过两个查询来实现该解决方案。如果您想避免一个查询在没有另一个查询的情况下成功运行,那么您应该在它们周围添加一个事务。
- 将有效行从Resume复制到User。
- 将Resume中的所有无效行标记为已排除。
执行:
insert into @User (Id, LI_id, SO_id, BB_id, GH_id)
select Us_id, LI_id, SO_id, BB_id, GH_id
from @Resume
where not ( Us_id is null
and LI_id is null
and SO_id is null
and BB_id is null
and GH_id is null);
update @Resume
set Excl = 1
where Us_id is null
and LI_id is null
and SO_id is null
and BB_id is null
and GH_id is null;
解决方案 2
另一种方法是在默认情况下使用排除用户标记Resume行 ( Excl = 1
)。同样,您可以为此使用列默认值。
insert into @Resume (Id, Us_id, LI_id, SO_id, BB_id, GH_id, Excl) values
(1, 101, 201, 301, 401, 501, 1),
(2, 102, null, 302, 402, 502, 1),
(3, 103, 203, 303, 403, 503, 1),
(4, null, null, null, null, null, 1); --resume without id's
使用这种方法,现在可以使用输出子句在单个查询中复制(插入)和更新有效的Resume行。这也意味着现在不需要事务,因为查询现在是单个操作。
update r
set r.Excl = 0
output inserted.Us_id,
inserted.LI_id,
inserted.SO_id,
inserted.BB_id,
inserted.GH_id
into @User
from @Resume r
where not ( r.Us_id is null
and r.LI_id is null
and r.SO_id is null
and r.BB_id is null
and r.GH_id is null);
结果
两种解决方案的输出相同。
select * from @resume;
Id Us_id LI_id SO_id BB_id GH_id Excl
----------- ----------- ----------- ----------- ----------- ----------- -----
1 101 201 301 401 501 0
2 102 NULL 302 402 502 0
3 103 203 303 403 503 0
4 NULL NULL NULL NULL NULL 1
select * from @user;
Id LI_id SO_id BB_id GH_id
----------- ----------- ----------- ----------- -----------
101 201 301 401 501
102 NULL 302 402 502
103 203 303 403 503
推荐阅读
- docker - 无法通过我的 docker 容器中的 /dev/video10 将 udp 视频流发送到暗网
- java - 通过带有流的反应器处理值
- c# - 如何分配客户端 ID(字符串)存储 3 位数字字符串?
- c# - 在 C# 中编辑字符串
- typescript - 在打字稿项目中使用 tinymce
- python - 在python数据框中的df.loc下循环
- php - admin_post.php(wordpress)挂钩到数据库错误
- microsoft-edge - 不要使用 Vaadin 和 Edge 在输入字段中存储数据
- c# - 在 Visual Studio 中创建 Windows 窗体时出现问题
- html - Html 表格 - 鼠标悬停时突出显示特定列的行