开发者

Return Data and Update Row without Multiple Lookups?

I have a stored procedure that looks up an article based on the article's title. But I also need to increment a column in the same table that counts the number of times the article is viewed.

Trying to be as efficient as possible, I see two possible ways to approach this:

  1. Perform one SELECT to obtain the PK on the target row. Then use that PK to increment the number of views and, finally, another SELECT using the PK to return the article data.

  2. Perform one SELECT to return the article data to my application, and then use the returned PK to make another round trip to the database to increment the number of views.

I know #1 would be pretty fast, but it's three lookups. And #2 requires two round trips to the database. Is there no way to optimize this task?

EDIT Based on feedback, I came up with the following. Thanks for any comments or constructive criticism.

DECLARE @Slug VARCHAR(250) -- Stored procedure argument

-- declare @UpdatedArticle table variable 
DECLARE @UpdatedArticle TABLE
(
    ArtID INT,
    ArtUserID UNIQUEIDENTIFIER,
    ArtSubcategoryID INT,
    ArtTitle VARCHAR(250),
    ArtHtml VARCHAR(MAX),
    ArtDescription VARCHAR(350),
    ArtKeywords VARCHAR(250),
    ArtLicenseID VARCHAR(10),
    ArtViews BIGINT,
    ArtCreated DATETIME2(7),
    ArtUpdated DATETIME2(7)
);

UPDATE Article
    SET ArtViews = ArtViews + 1
OUTPUT
    INSERTED.ArtID,
    INSERTED.ArtUserID,
    inserted.ArtSubcategoryID,
    INSERTED.ArtTitle,
    INSERTED.ArtHtml,
    INSERTED.ArtDescription,
    INSERTED.ArtKeywords,
    INSERTED.ArtLicenseID,
    INSERTED.ArtViews,
    INSERTED.ArtUpdated,
    INSERTED.ArtCreated
INTO @UpdatedArticle
WHERE ArtSlugHash = CHECKSUM(@Slug) AND ArtSlug = @Slug AND ArtApproved = 1

SELECT a.ArtID, a.ArtUserID, a.ArtTitle, a.ArtHtml, a.ArtDescription, a.ArtKeywords, a.ArtLicenseID,
    l.licTitle, a.ArtViews, a.Ar开发者_如何学CtCreated, a.ArtUpdated, s.SubID, s.SubTitle, c.CatID, c.CatTitle,
    sec.SecID, sec.SecTitle, u.UsrDisplayName AS UserName
    FROM @UpdatedArticle a
    INNER JOIN Subcategory s ON a.ArtSubcategoryID = s.SubID
    INNER JOIN Category c ON s.SubCatID = c.CatID
    INNER JOIN [Section] sec ON c.CatSectionID = sec.SecID
    INNER JOIN [User] u ON a.ArtUserID = u.UsrID
    INNER JOIN License l ON a.ArtLicenseID = l.LicID


Here is a way using the OUTPUT statement (SQL Server 2005 onwards), in a single update statement:

IF OBJECT_ID ('Books', 'U') IS NOT NULL
    DROP TABLE dbo.Books;

CREATE TABLE dbo.Books
(
  BookID int NOT NULL PRIMARY KEY,
  BookTitle nvarchar(50) NOT NULL,
  ModifiedDate datetime NOT NULL,
  NumViews int not null CONSTRAINT DF_Numviews DEFAULT (0)
);

INSERT INTO dbo.Books
  (BookID, BookTitle, ModifiedDate) 
VALUES
  (106, 'abc', GETDATE()),
  (107, 'Great Expectations', GETDATE());


-- declare @UpdateOutput1 table variable 
DECLARE @UpdateOutput1 table
(
  BookID int,
  BookTitle nvarchar(50),
  ModifiedDate datetime,
  NumViews int 
);


-- >>>>  here is the update of Numviews and the Fetch
-- update Numviews in Books table, and retrive the row
UPDATE Books
SET 
  NumViews = NumViews + 1
OUTPUT
    INSERTED.BookID,
    INSERTED.BookTitle,
    INSERTED.ModifiedDate,
    INSERTED.NumViews
  INTO @UpdateOutput1
WHERE BookID = 106

-- view updated row in Books table
SELECT * FROM Books;

-- view output row in @UpdateOutput1 variable
SELECT * FROM @UpdateOutput1;
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜