我有两个表:
如果tb1
中有同一行,我正在尝试更新tb2
中的几个列值,否则,如果行中不存在,则需要插入tb2
中的所有新值。表tb1
。
我用过一个游标,但是它的运行速度非常慢。
我的代码:
DECLARE @accountId INT, @id INT,
@title NVARCHAR(1000), @num_questions INT,
@type NVARCHAR(1000), @starts_at NVARCHAR(1000),
@finishes_at NVARCHAR(1000), @published_at NVARCHAR(1000),
@summary NVARCHAR(2000), @updated_at NVARCHAR(1000)
-- Data from tb2
DECLARE quizRecSet CURSOR FOR
SELECT
AccountId, ID, title, num_questions, type,
starts_at, finishes_at, published_at, summary, updated_at
FROM
tb2
WHERE
accountId = 1
ORDER BY
updated_at DESC
OPEN quizRecSet
FETCH NEXT FROM quizRecSet INTO @accountId, @id, @title, @num_questions, @type,
@starts_at, @finishes_at, @published_at, @summary, @updated_at
WHILE (@@FETCH_STATUS = 0)
BEGIN
IF ((SELECT COUNT(*) FROM tb1(nolock)
WHERE ID = @ID AND accountId = @accountId) = 0)
BEGIN
INSERT INTO tb1
VALUES (@accountId, @id, @title, @num_questions, @type,
@starts_at, @finishes_at, @published_at, @summary, @updated_at)
END
ELSE
BEGIN
UPDATE tb1
SET title = @title, num_questions = @num_questions,
type = @type, published_at = @published_at,
summary = @summary, updated_at = @updated_at
WHERE ID = @ID AND AccountId = @accountId
END
FETCH NEXT FROM quizRecSet INTO @accountId, @id, @title, @num_questions, @type,
@starts_at, @finishes_at, @published_at, @summary, @updated_at
END
CLOSE quizRecSet
DEALLOCATE quizRecSet
上面的代码工作非常缓慢,因为tb1和tb2中都有很多行(大约2M)
有人可以帮助我寻求更好的替代方法并提高性能。
谢谢
答案 0 :(得分:1)
也许运行得更快:
insert into tb1 (accountId, ID, title, num_questions, type,
starts_at, finishes_at, published_at, summary, updated_at)
select AccountId, ID, title, num_questions, type,
starts_at, finishes_at, published_at, summary, updated_at
from tb2
where accountId = 1 -- from the previous cursor sample
and not exists
(select 1 from tb1 where ID=tb2.ID and accountId = tb2.accountId)
update tb1 set
title = tb2.title, num_questions = tb2.num_questions,
type=tb2.type, published_at = tb2.published_at,
summary = tb2.summary, updated_at = tb2.updated_at
from tb1
join tb2 on (tb1.ID = tb2.ID and tb1.accountId = tb2.accountId)
where tb1.accountId = 1 -- from the previous cursor sample
and not (tb1.title=tb2.title and tb1.num_questions=tb2.num_questions
and tb1.type=tb2.type and tb1.published_at=tb2.published_at
and tb1.summary=tb2.summary and tb1.updated_at=tb2.updated_at)
答案 1 :(得分:0)
设置操作比光标操作快。以下sql可以帮助您提高性能。在这种情况下,我们首先要更新表tb1
,然后再插入从表tb2
到表tb1
尚不存在的行。
UPDATE tb1 SET
title = t2.title,
num_questions = t2.num_questions,
type = t2.type,
published_at = t2.published_at,
summary = t2.summary,
updated_at = t2.updated_at
FROM tb1 AS t1
JOIN tb2 AS t2 ON (t1.ID = t2.ID AND t1.accountId = t2.accountId)
WHERE t1.accountId = 1
INSERT INTO tb1 (
t2.AccountId, t2.ID, t2.title, t2.num_questions, t2.type,
t2.starts_at, t2.finishes_at, t2.published_at, t2.summary, t2.updated_at)
SELECT
t2.AccountId, t2.ID, t2.title, t2.num_questions, t2.type,
t2.starts_at, t2.finishes_at, t2.published_at, t2.summary, t2.updated_at
FROM (
SELECT
AccountId, ID, title, num_questions, type,
starts_at, finishes_at, published_at, summary, updated_at
FROM tb2
EXCEPT
SELECT
t2.AccountId, t2.ID, t2.title, t2.num_questions, t2.type,
t2.starts_at, t2.finishes_at, t2.published_at, t2.summary, t2.updated_at
FROM tb2 AS t2
JOIN tb1 AS t1 ON (t1.ID = t2.ID AND t1.accountId = t2.accountId)
WHERE t2.accountId = 1
) AS TempTable