我有一个存储过程,它像Scott Michell一样对pnd Paging进行排序,就像Sorting Custom Paged Results of一样。
我有两个表:Article
和Category
。我的存储过程适用于Article
表,但我想在Category
表中添加一列到查询中(我意味着内连接)。
实际上我不能像Scott Michell那样做,因为在两个表中都有一些相似的列(当我一直喜欢Scott时,我会得到“Ambiguous Column Error”)。
我没有内连接的存储过程是:
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
go
ALTER PROCEDURE [dbo].[sp_Articles_SelectByCategoryId]
@CategoryId int,
@startRowIndex int = -1,
@maximumRows int = -1,
@sortExpression nvarchar(50),
@recordCount int = NULL OUTPUT
AS
IF (@recordCount IS NOT NULL)
BEGIN
SET @recordCount = (SELECT COUNT(*)
FROM [dbo].[Articles]
WHERE [CategoryId] = @CategoryId)
RETURN
END
IF LEN(@sortExpression) = 0
SET @sortExpression = 'Id'
DECLARE @sql nvarchar(4000)
SET @sql = 'SELECT [Id], [AddedDate], [AddedBy], [CategoryId],
[Title], [Abstract], [Body]
FROM
(SELECT
[Id], [AddedDate], [AddedBy], [CategoryId],
[Title], [Abstract], [Body],
ROW_NUMBER() OVER(ORDER BY ' + @sortExpression + ') as RowNum
FROM [dbo].[Articles]
WHERE CategoryId = ' + CONVERT(nvarchar(10), @CategoryId) + ') as CategoryIdInfo
WHERE ((RowNum between (' + CONVERT(nvarchar(10), @startRowIndex) + ') AND ' + CONVERT(nvarchar(10), @startRowIndex) + ' + ' + CONVERT(nvarchar(10), @maximumRows) + ' - 1)
OR ' + CONVERT(nvarchar(10), @startRowIndex) + ' = -1 OR ' + CONVERT(nvarchar(10), @maximumRows) + ' = -1)'
-- Execute the SQL query
EXEC sp_executesql @sql
我的Category
表是:
CREATE TABLE [dbo].[Category]
(
[Id] [int] IDENTITY(1,1) NOT NULL,
[AddedDate] [datetime] NOT NULL,
[AddedBy] [nvarchar](250) COLLATE Arabic_CI_AS NOT NULL,
[Title] [nvarchar](50) COLLATE Arabic_CI_AS NOT NULL,
[Importance] [int] NOT NULL,
[Description] [nvarchar](300) COLLATE Arabic_CI_AS NULL,
[ImageUrl] [nvarchar](50) COLLATE Arabic_CI_AS NULL,
CONSTRAINT [PK_Category]
PRIMARY KEY CLUSTERED ([Id] ASC)
)
我的Article
表:
CREATE TABLE [dbo].[Articles]
(
[Id] [int] IDENTITY(1,1) NOT NULL,
[AddedDate] [datetime] NOT NULL,
[AddedBy] [nvarchar](250) COLLATE Arabic_CI_AS NOT NULL,
[CategoryId] [int] NOT NULL,
[Title] [nvarchar](255) COLLATE Arabic_CI_AS NOT NULL,
[Abstract] [nvarchar](4000) COLLATE Arabic_CI_AS NULL,
[Body] [nvarchar](max) COLLATE Arabic_CI_AS NOT NULL,
[ReleaseDate] [datetime] NULL,
[ExpireDate] [datetime] NULL,
[Approved] [bit] NOT NULL,
[Listed] [bit] NOT NULL,
[CommentEnabled] [bit] NOT NULL,
[OnlyForMembers] [bit] NOT NULL,
[ViewCount] [int] NOT NULL,
[Votes] [int] NOT NULL,
[TotalRating] [int] NOT NULL,
CONSTRAINT [PK_Articles] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
我不知道如何将“类别”表的“标题”列添加到查询中。
如果我的Category
表没有相似的字段,那么这个查询肯定有效:
DECLARE @sql nvarchar(4000)
SET @sql =
'SELECT
[Id],
[AddedDate],
[AddedBy],
[CategoryId],
[Title],
[Abstract],
[Body],
ArticleTitle
FROM
(SELECT
[Id],
[AddedDate],
[AddedBy],
a.[CategoryId],
[Title],
[Abstract],
[Body],
b.Title as CategoryTitle ,
ROW_NUMBER() OVER(ORDER BY ' + @sortExpression + ') as RowNum
FROM [dbo].[Articles] a INNER JOIN Category b on a.CategoryId = b.Id
WHERE a.CategoryId = ' + CONVERT(nvarchar(10), @CategoryId) + '
) as CategoryIdInfo
如果您想测试,可以下载Attachment(Tables and StoredProcedure) 谢谢
答案 0 :(得分:2)
以下代码在您提供的表上完美运行 - 其中没有数据,但这不应该有所不同,因为我只想证明查询执行,而不是结果。
此代码需要注意的事项:
排序表达式必须包含别名
SET @sortExpression = 'a.Id'
所有重复的列必须是别名
请注意a。[Id],a。[AddedDate],a。[AddedBy],a。[CategoryId],a。[Title],b。[Title]都是别名
列名必须在内部和外部查询之间匹配
您的外部选择中有一个ArticleTitle列名,但内部选择中有一列CategoryTitle。那永远不会奏效。
DECLARE @SortExpression nvarchar(100)
SET @sortExpression = 'a.Id'
DECLARE @sql nvarchar(4000)
SET @sql =
'SELECT
[Id],
[AddedDate],
[AddedBy],
[CategoryId],
[Title],
[Abstract],
[Body],
CategoryTitle
FROM
(SELECT
a.[Id],
a.[AddedDate],
a.[AddedBy],
a.[CategoryId],
a.[Title],
[Abstract],
[Body],
b.Title as CategoryTitle ,
ROW_NUMBER() OVER(ORDER BY ' + @sortExpression + ') as RowNum
FROM [dbo].[Articles] a INNER JOIN Category b on a.CategoryId = b.Id
WHERE a.CategoryId = ' + CONVERT(nvarchar(10), @CategoryId) + '
) as CategoryIdInfo'
-- Execute the SQL query
EXEC sp_executesql @sql
答案 1 :(得分:0)
您是否尝试过类似下面代码的内容?
这使用AS关键字为子查询中的列提供唯一的名称,并使用别名来允许对子查询中的列进行明确的引用。
另请注意, ALL 对含糊不清的列的引用必须是别名,在您的情况下,这包括您正在动态注入的@sortExpression。
ALTER PROCEDURE [dbo].[sp_Articles_SelectByCategoryId]
@CategoryId int,
@startRowIndex int = -1,
@maximumRows int = -1,
@sortExpression nvarchar(50),
@recordCount int = NULL OUTPUT
AS
IF (@recordCount IS NOT NULL)
BEGIN
SET @recordCount = (SELECT COUNT(*) FROM [dbo].[Articles] WHERE [CategoryId] = @CategoryId
)
RETURN
END
IF LEN(@sortExpression) = 0
SET @sortExpression = 'Id'
DECLARE @sql nvarchar(4000)
SET @sql =
'SELECT
[Id],
[AddedDate],
[AddedBy],
[CategoryId],
[Title],
-- CategoryTitle refers to the column name declared by that AS inside the subquery
CategoryTitle
[Abstract],
[Body],
FROM
(SELECT
[Id],
[AddedDate],
[AddedBy],
-- The column aliases a and c allow us to refer to similarly names column unambiguously
a.[CategoryId],
a.[Title],
c.[Title] as CategoryTitle,
[Abstract],
[Body],
--- This now includes an alias on the sortExpression order by
ROW_NUMBER() OVER(ORDER BY a.' + @sortExpression + ') as RowNum
FROM [dbo].[Articles] a
Join [dbo].[Category] c
ON c.CategoryID = a.CategoryID
WHERE c.CategoryId = ' + CONVERT(nvarchar(10), @CategoryId) + '
) as CategoryIdInfo
WHERE
((RowNum between (' + CONVERT(nvarchar(10), @startRowIndex) + ') AND ' + CONVERT(nvarchar(10), @startRowIndex) + ' + ' + CONVERT(nvarchar(10), @maximumRows) + ' - 1)
OR ' + CONVERT(nvarchar(10), @startRowIndex) + ' = -1 OR ' + CONVERT(nvarchar(10), @maximumRows) + ' = -1)'
-- Execute the SQL query
EXEC sp_executesql @sql
这样做是为Article和Category表(分别为a和c)声明了一个别名,允许您明确地引用它们的列。
我没有尝试过使用Row_Number的确切情况,但可以认为没有理由说它不起作用。
然后使用AS关键字应该为您提供一个与外部选择一起使用的唯一名称。