这可能是一个非常简单的问题,但我试图搜索答案却被谷歌找到了答案,这些答案显示了如何通过制作存储过程来重用查询。我想在存储过程中重用查询的结果。
这是一个简洁的例子,我已经删除了NOCOUNT
,XACT_ABORT
,TRANSACTION
,TRY
以及大部分逻辑。
CREATE PROCEDURE Do_Something
@userId UNIQUEIDENTIFIER
AS
BEGIN
DELETE FROM LikedItems
WHERE likedItemId IN
(
SELECT Items.id FROM Items
WHERE Items.userId = @userId
)
DELETE FROM FollowedItems
WHERE followedItemId IN
(
SELECT Items.id FROM Items
WHERE Items.userId = @userId
)
END
重复使用重复嵌套SELECT
的结果而不是两次执行的语法是什么?
答案 0 :(得分:3)
您可以将SELECT的结果INSERT到临时表或表变量中,但它并不自动意味着整体性能会更好。你需要测量它。
临时表
CREATE PROCEDURE Do_Something
@userId UNIQUEIDENTIFIER
AS
BEGIN
CREATE TABLE #Temp(id int);
INSERT INTO #Temp(id)
SELECT Items.id
FROM Items
WHERE Items.userId = @userId;
DELETE FROM LikedItems
WHERE likedItemId IN
(
SELECT id FROM #Temp
)
DELETE FROM FollowedItems
WHERE followedItemId IN
(
SELECT id FROM #Temp
)
DROP TABLE #Temp;
END
表格变量
CREATE PROCEDURE Do_Something
@userId UNIQUEIDENTIFIER
AS
BEGIN
DECLARE @Temp TABLE(id int);
INSERT INTO @Temp(id)
SELECT Items.id
FROM Items
WHERE Items.userId = @userId;
DELETE FROM LikedItems
WHERE likedItemId IN
(
SELECT id FROM @Temp
)
DELETE FROM FollowedItems
WHERE followedItemId IN
(
SELECT id FROM @Temp
)
END
答案 1 :(得分:1)
您可以声明一个表变量来存储select的结果,然后只是查询它。
CREATE PROCEDURE Do_Something
@userId UNIQUEIDENTIFIER
AS
BEGIN
DECLARE @TempItems TABLE (id int)
INSERT INTO @TempItems
SELECT Items.id FROM Items
WHERE Items.userId = @userId
DELETE FROM LikedItems
WHERE likedItemId IN
(
SELECT id FROM @TempItems
)
DELETE FROM FollowedItems
WHERE followedItemId IN
(
SELECT id FROM @TempItems
)
END
答案 2 :(得分:1)
如果子查询快速而简单 - 无需更改任何内容。在第一次查询之后,项目的数据位于缓存中(如果不是),则获取锁定。如果子查询缓慢而复杂 - 将其存储到表变量中并通过重复使用问题中列出的相同子查询。
如果您的问题与性能无关,并且您要注意复制粘贴:没有复制粘贴。有相同的逻辑,类似的结构和引用 - 是的,你将拥有几乎相同的查询源代码。
一般来说,它不一样。除非您在SERIALIZABLE隔离级别下运行,否则可以在第一个查询之后从Items表中删除或插入某些行。在第一次删除期间,第一次和第二次删除语句之间可能发生许多不同的事每个delete语句也需要它自己的执行计划 - 因此无论如何必须将所有关于受影响的表和连接的信息提供给SERVER。您需要再次使用相同的源进行过滤 - 是的,您再次为子查询提供相同的源。部分代码没有“两次”或“重复使用”。通过复杂查询收集的数据 - 是的,它可以通过临时表/表变量重复使用(不运行相同的复杂查询 - 通过从准备好的源简单查询)之前。