简体   繁体   English

在存储过程中多次使用SQL WITH语句的结果

[英]Using result of a SQL WITH statement more than once in a stored procedure

I have the SQL stored procedure below: 我有下面的SQL存储过程:

ALTER PROCEDURE [dbo].[sp_getpaginatedusersbyglobalfilter] 
    @globalFilter varchar(max)
    , @pageSize int
    , @page int
    , @totalRecords int output
    , @totalFilteredRecords int output
AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

    ;WITH PaginatedUsers AS(
        SELECT     ROW_NUMBER() OVER(ORDER BY u.LastName) ID
                   , u.Username
                   , u.FirstName
                   , u.OtherNames
                   , u.LastName
                   , e.Nombre
                   , r.RoleName
                   , u.PhoneNumber
        FROM       webpages_Users u
        INNER JOIN Establecimiento e
        ON         u.FacilityId = e.IDReporte
        AND        e.EstadoRegistro = 1
        INNER JOIN webpages_UsersInRoles ur
        ON         u.UserId = ur.UserId
        INNER JOIN webpages_Roles r
        ON         ur.RoleId = r.RoleId
        WHERE      u.Username LIKE '%' + @globalFilter + '%'
        OR         u.FirstName LIKE '%' + @globalFilter + '%' 
        OR         u.OtherNames LIKE '%' + @globalFilter + '%'
        OR         u.LastName LIKE '%' + @globalFilter + '%'
        OR         e.Nombre LIKE '%' + @globalFilter + '%'
        OR         r.RoleName LIKE '%' + @globalFilter + '%'
        OR         u.PhoneNumber LIKE '%' + @globalFilter + '%'
    )

    SELECT  pu.ID, pu.Username
            , pu.FirstName
            , pu.OtherNames
            , pu.LastName
            , pu.Nombre AS FacilityName
            , pu.RoleName
            , pu.PhoneNumber
    FROM    PaginatedUsers pu
    WHERE   pu.ID BETWEEN ((@page - 1) * @pageSize + 1)
    AND     @page * @pageSize

    SELECT @totalFilteredRecords = COUNT(pu.ID)
    FROM    PaginatedUsers pu

    SELECT @totalRecords = COUNT(u.UserId)
    FROM   webpages_Users u
END

The problem I have is with the section: 我的问题是与部分:

    SELECT @totalFilteredRecords = COUNT(pu.ID)
    FROM    PaginatedUsers pu

The error I get is "Invalid object name 'PaginatedUsers'". 我得到的错误是“无效的对象名称'PaginatedUsers'”。 As per my research, I cannot use the PaginatedUsers (resulting from the WITH) object more than once in the query. 根据我的研究,我不能在查询中多次使用PaginatedUsers(来自WITH的结果)对象。 Then, How can I do to return the total number of records in the output variable @totalFilteredRecords? 然后,如何返回输出变量@totalFilteredRecords中的记录总数? I've been thinking about inserting the result into a temporal table and then get the count from it as well as the final resultset, but I don't like that idea. 我一直在考虑将结果插入到临时表中,然后从中获取计数以及最终结果集,但是我不喜欢这种想法。 What can I do? 我能做什么?

Thanks. 谢谢。

You can only use the output of a With clause in the same statement as the With clause. 您只能在与With子句相同的语句中使用With子句的输出。 The first Select clause is part of the first SQL Statement that starts with the With clause. 第一个Select子句是第一个以With子句开头的SQL语句的一部分。 By using a second Select, it is in a separate SQL statement. 通过使用第二个Select,它位于单独的SQL语句中。 If you connect the two Selects into a single statement, then it will work. 如果将两个Select连接到单个语句中,则它将起作用。

Your research is correct, you cannot use CTEs more than once. 您的研究是正确的,您不能多次使用CTE。

--EDIT - 编辑

AS OP points out, A SELECT statement that assigns a value to a variable must not be combined with data-retrieval operations. 正如OP指出的那样,不能将为变量分配值的SELECT语句与数据检索操作结合使用。

So I don't have any other suggestions rather than to use a temp table -- here is an untested example: 因此,除了使用临时表之外,我没有其他建议-这是一个未经测试的示例:

SELECT     ROW_NUMBER() OVER(ORDER BY u.LastName) ID
               , u.Username
               , u.FirstName
               , u.OtherNames
               , u.LastName
               , e.Nombre
               , r.RoleName
               , u.PhoneNumber
       INTO #PaginatedUsers
FROM       webpages_Users u
    INNER JOIN Establecimiento e
    ON         u.FacilityId = e.IDReporte
    AND        e.EstadoRegistro = 1
    INNER JOIN webpages_UsersInRoles ur
    ON         u.UserId = ur.UserId
    INNER JOIN webpages_Roles r
    ON         ur.RoleId = r.RoleId
WHERE      u.Username LIKE '%' + @globalFilter + '%'
    OR         u.FirstName LIKE '%' + @globalFilter + '%' 
    OR         u.OtherNames LIKE '%' + @globalFilter + '%'
    OR         u.LastName LIKE '%' + @globalFilter + '%'
    OR         e.Nombre LIKE '%' + @globalFilter + '%'
    OR         r.RoleName LIKE '%' + @globalFilter + '%'
    OR         u.PhoneNumber LIKE '%' + @globalFilter + '%'


SELECT  pu.ID, pu.Username
        , pu.FirstName
        , pu.OtherNames
        , pu.LastName
        , pu.Nombre AS FacilityName
        , pu.RoleName
        , pu.PhoneNumber
FROM    #PaginatedUsers pu
WHERE   pu.ID BETWEEN ((@page - 1) * @pageSize + 1)
AND     @page * @pageSize

SELECT @totalFilteredRecords = COUNT(pu.ID)
FROM    #PaginatedUsers pu

SELECT @totalRecords = COUNT(u.UserId)
FROM   webpages_Users u

DROP TABLE #PaginatedUsers

Here is a good answer I read about CTE vs Temp Tables. 这是我读到的有关CTE与温度表的好答案

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM