Sql server 如何将查询结果存储在存储过程的临时表中?

Sql server 如何将查询结果存储在存储过程的临时表中?,sql-server,stored-procedures,temp-tables,Sql Server,Stored Procedures,Temp Tables,我试图将一个复杂查询的结果存储在一个临时表中,但我一直收到一个错误。下面是我的存储过程中的代码: DECLARE @TempItems TABLE ( ID int IDENTITY, ForumThreadID int, ForumID int, ParentID int, title NVARCHAR(MAX), title_path NVARCHAR(MAX), level_id NVARCHAR(MAX), level_id_path NVARCHAR(MAX), PostBody N

我试图将一个复杂查询的结果存储在一个临时表中,但我一直收到一个错误。下面是我的存储过程中的代码:

DECLARE @TempItems TABLE
(
ID int IDENTITY, ForumThreadID int, ForumID int, ParentID int, title NVARCHAR(MAX), title_path NVARCHAR(MAX), 
level_id NVARCHAR(MAX), level_id_path NVARCHAR(MAX), PostBody NVARCHAR(MAX), CreatedBy int, UserName NVARCHAR(50), Created DateTime
)

DECLARE @SQL NVARCHAR(MAX)

SET @SQL = 'WITH TreeList (ForumThreadID, ForumID, ParentID, title, title_path, level_id, level_id_path) as 
    ( 
    SELECT p.ForumThreadID,  
    p.ForumID, 
    p.ParentID,  
    p.PostSubject,  
    CONVERT(nvarchar(max), p.ForumThreadID),  
    ROW_NUMBER() OVER(PARTITION BY ParentID ORDER BY p.ForumThreadID),  
    RIGHT(''0000'' + CAST(ROW_NUMBER() OVER(PARTITION BY ParentID ORDER BY p.ForumThreadID) AS varchar(max)),4)  
    FROM ForumThreads p 
    WHERE (p.ParentID = ' + @ParentID + ') AND (p.Deleted IS NULL) 
    UNION ALL 
    SELECT c.ForumThreadID,  
    c.ForumID,  
    c.ParentID,  
    c.PostSubject,  
    r.title_path + ''/'' + CAST(c.ForumThreadID AS VARCHAR(MAX)),  
    ROW_NUMBER() OVER(PARTITION BY c.ParentID ORDER BY c.ForumThreadID),  
    CONVERT(varchar(max), r.level_id_path + ''.'' + RIGHT(''0000'' + CAST(ROW_NUMBER() OVER(PARTITION BY c.ParentID ORDER BY c.ForumThreadID) AS VARCHAR),4))  
    FROM ForumThreads AS c 
    INNER JOIN treelist AS r 
    ON c.ParentID = r.ForumThreadID 
    WHERE (c.Deleted IS NULL)) 
    SELECT TOP 100 TreeList.*, d.PostBody, d.CreatedBy, Members.UserName, COALESCE(d.Created,''1-JAN-1900'') AS Created 
    FROM TreeList INNER JOIN ForumThreads AS d ON TreeList.ForumThreadID = d.ForumThreadID INNER JOIN 
    Members ON d.CreatedBy = Members.MemberID 
    WHERE (d.Deleted IS NULL) 
    ORDER BY level_id_path;'

INSERT INTO @TempItems (ForumThreadID, ForumID, ParentID, title, title_path, level_id, level_id_path, PostBody, CreatedBy, UserName, Created) EXEC @SQL

SELECT * FROM @TempItems
我得到的错误是:

Msg 203, Level 16, State 2, Procedure spPagedForumThreads, Line 53
The name 'WITH TreeList (ForumThreadID, ForumID, ParentID, title, title_path, level_id, level_id_path) as 
( 
SELECT p.ForumThreadID,  
p.ForumID, 
p.ParentID,  
p.PostSubject,  
CONVERT(nvarchar(max), p.ForumThreadID),  
ROW_NUMBER() OVER(PARTITION BY ParentID ORDER BY p.ForumThreadID),  
RIGHT('0000' + CAST(ROW_NUMBER() OVER(PARTITION BY ParentID ORDER BY p.ForumThreadID) AS varchar(max)),4)  
FROM ForumThreads p 
WHERE (p.ParentID = 10720) AND (p.Deleted IS NULL) 
UNION ALL 
SELECT c.ForumThreadID,  
c.ForumID,  
c.ParentID,  
c.PostSubject,  
r.title_path + '/' + ' is not a valid identifier.
我做错了什么

是否有其他方法可以创建临时表,而不需要将查询保存为字符串


谢谢

EXEC@SQL而不仅仅是EXEC@SQL。

EXEC@SQL执行动态SQL的目的是什么?完成CTE后,您应该能够修改SELECT语句,将其插入@TempItems SELECT TOP 100树列表。*

这应该可以在不需要动态SQL(例如EXEC)的情况下工作。注意:WITH之前的语句需要以分号结尾,以便在语法上有效

DECLARE @TempItems TABLE
(
ID int IDENTITY, ForumThreadID int, ForumID int, ParentID int, title NVARCHAR(MAX), title_path NVARCHAR(MAX), 
level_id NVARCHAR(MAX), level_id_path NVARCHAR(MAX), PostBody NVARCHAR(MAX), CreatedBy int, UserName NVARCHAR(50), Created DateTime
);

WITH TreeList (ForumThreadID, ForumID, ParentID, title, title_path, level_id, level_id_path) as 
    ( 
    SELECT p.ForumThreadID,  
    p.ForumID, 
    p.ParentID,  
    p.PostSubject,  
    CONVERT(nvarchar(max), p.ForumThreadID),  
    ROW_NUMBER() OVER(PARTITION BY ParentID ORDER BY p.ForumThreadID),  
    RIGHT('0000' + CAST(ROW_NUMBER() OVER(PARTITION BY ParentID ORDER BY p.ForumThreadID) AS varchar(max)),4)  
    FROM ForumThreads p 
    WHERE (p.ParentID = ' + @ParentID + ') AND (p.Deleted IS NULL) 
    UNION ALL 
    SELECT c.ForumThreadID,  
    c.ForumID,  
    c.ParentID,  
    c.PostSubject,  
    r.title_path + '/' + CAST(c.ForumThreadID AS VARCHAR(MAX)),  
    ROW_NUMBER() OVER(PARTITION BY c.ParentID ORDER BY c.ForumThreadID),  
    CONVERT(varchar(max), r.level_id_path + '.' + RIGHT('0000' + CAST(ROW_NUMBER() OVER(PARTITION BY c.ParentID ORDER BY c.ForumThreadID) AS VARCHAR),4))  
    FROM ForumThreads AS c 
    INNER JOIN treelist AS r 
    ON c.ParentID = r.ForumThreadID 
    WHERE (c.Deleted IS NULL)) 

INSERT INTO @TempItems (ForumThreadID, ForumID, ParentID, title, title_path, level_id, level_id_path, PostBody, CreatedBy, UserName, Created)
    SELECT TOP 100 TreeList.*, d.PostBody, d.CreatedBy, Members.UserName, COALESCE(d.Created,'1-JAN-1900') AS Created 
    FROM TreeList INNER JOIN ForumThreads AS d ON TreeList.ForumThreadID = d.ForumThreadID INNER JOIN 
    Members ON d.CreatedBy = Members.MemberID 
    WHERE (d.Deleted IS NULL) 
    ORDER BY level_id_path;


SELECT * FROM @TempItems

执行动态SQL的目的是什么?完成CTE后,您应该能够修改SELECT语句,将其插入@TempItems SELECT TOP 100树列表。*

这应该可以在不需要动态SQL(例如EXEC)的情况下工作。注意:WITH之前的语句需要以分号结尾,以便在语法上有效

DECLARE @TempItems TABLE
(
ID int IDENTITY, ForumThreadID int, ForumID int, ParentID int, title NVARCHAR(MAX), title_path NVARCHAR(MAX), 
level_id NVARCHAR(MAX), level_id_path NVARCHAR(MAX), PostBody NVARCHAR(MAX), CreatedBy int, UserName NVARCHAR(50), Created DateTime
);

WITH TreeList (ForumThreadID, ForumID, ParentID, title, title_path, level_id, level_id_path) as 
    ( 
    SELECT p.ForumThreadID,  
    p.ForumID, 
    p.ParentID,  
    p.PostSubject,  
    CONVERT(nvarchar(max), p.ForumThreadID),  
    ROW_NUMBER() OVER(PARTITION BY ParentID ORDER BY p.ForumThreadID),  
    RIGHT('0000' + CAST(ROW_NUMBER() OVER(PARTITION BY ParentID ORDER BY p.ForumThreadID) AS varchar(max)),4)  
    FROM ForumThreads p 
    WHERE (p.ParentID = ' + @ParentID + ') AND (p.Deleted IS NULL) 
    UNION ALL 
    SELECT c.ForumThreadID,  
    c.ForumID,  
    c.ParentID,  
    c.PostSubject,  
    r.title_path + '/' + CAST(c.ForumThreadID AS VARCHAR(MAX)),  
    ROW_NUMBER() OVER(PARTITION BY c.ParentID ORDER BY c.ForumThreadID),  
    CONVERT(varchar(max), r.level_id_path + '.' + RIGHT('0000' + CAST(ROW_NUMBER() OVER(PARTITION BY c.ParentID ORDER BY c.ForumThreadID) AS VARCHAR),4))  
    FROM ForumThreads AS c 
    INNER JOIN treelist AS r 
    ON c.ParentID = r.ForumThreadID 
    WHERE (c.Deleted IS NULL)) 

INSERT INTO @TempItems (ForumThreadID, ForumID, ParentID, title, title_path, level_id, level_id_path, PostBody, CreatedBy, UserName, Created)
    SELECT TOP 100 TreeList.*, d.PostBody, d.CreatedBy, Members.UserName, COALESCE(d.Created,'1-JAN-1900') AS Created 
    FROM TreeList INNER JOIN ForumThreads AS d ON TreeList.ForumThreadID = d.ForumThreadID INNER JOIN 
    Members ON d.CreatedBy = Members.MemberID 
    WHERE (d.Deleted IS NULL) 
    ORDER BY level_id_path;


SELECT * FROM @TempItems

我不知道您使用的是哪个版本,所以您可能需要使用临时表而不是表变量。表变量不能作为insert/exec的目标,但您在哪里见过使用exec@sql的有效语法?请尝试在WITH前面加一个分号。确实,缺少的分号和括号是问题的一部分。感谢您指出这一点。我不知道您使用的是哪个版本,所以您可能需要使用临时表而不是表变量。insert/exec的目标不能是表变量,但您在哪里见过使用exec@sql的有效语法?请尝试在WITH前面加一个分号。确实,缺少分号和括号是问题的一部分。谢谢你指出这一点。谢谢!我从其他地方得到了代码,并根据自己的需要对其进行了修改,但没有完全掌握它的工作原理。现在我更接近了解CTE了。不得不对您建议的代码稍作修改,并将“++@ParentID+”替换为@ParentID。我相信这是我尝试将查询保存到字符串中以供以后执行时留下的痕迹。如果我说使用WITH语句就像创建临时表一样,我是否正确?谢谢!我从其他地方得到了代码,并根据自己的需要对其进行了修改,但没有完全掌握它的工作原理。现在我更接近了解CTE了。不得不对您建议的代码稍作修改,并将“++@ParentID+”替换为@ParentID。我相信这是我尝试将查询保存到字符串中以供以后执行时留下的痕迹。如果我说使用WITH语句就像创建临时表,我是否正确?谢谢。是的,括号缺失,添加括号解决了部分问题。谢谢。是的,括号丢失了,添加括号解决了部分问题。