【问题标题】:Using result of a SQL WITH statement more than once in a stored procedure在存储过程中多次使用 SQL WITH 语句的结果
【发布时间】:2013-01-21 01:53:15
【问题描述】:

我有下面的 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

我遇到的问题是该部分:

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

我得到的错误是“无效的对象名称'PaginatedUsers'”。根据我的研究,我不能在查询中多次使用 PaginatedUsers(由 WITH 产生)对象。那么,如何返回输出变量@totalFilteredRecords 中的记录总数?我一直在考虑将结果插入到临时表中,然后从中获取计数以及最终结果集,但我不喜欢这个想法。我能做什么?

谢谢。

【问题讨论】:

    标签: sql sql-server-2008 stored-procedures with-statement


    【解决方案1】:

    您只能在与 With 子句相同的语句中使用 With 子句的输出。第一个 Select 子句是第一个以 With 子句开头的 SQL 语句的一部分。通过使用第二个 Select,它位于单独的 SQL 语句中。如果将两个 Select 连接到一个语句中,那么它将起作用。

    【讨论】:

    • 谢谢,查尔斯。可以举个例子吗?
    【解决方案2】:

    您的研究是正确的,您不能多次使用 CTE。

    --编辑

    正如 OP 指出的那样,为变量赋值的 SELECT 语句不得与数据检索操作结合使用。

    所以除了使用临时表之外,我没有任何其他建议——这是一个未经测试的示例:

    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
    

    这是一个很好的 answer 我读过关于 CTE 与临时表的文章。

    【讨论】:

    • 谢谢。斯格德斯。我试过你的建议,但没有奏效。我得到的错误是“为变量赋值的 SELECT 语句不能与数据检索操作结合使用”
    • 我想——我编辑了我的答案以使用临时表。祝你好运!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-02
    • 2022-10-04
    • 2017-04-26
    • 1970-01-01
    • 1970-01-01
    • 2018-12-14
    相关资源
    最近更新 更多