发送 SQL 一个布尔值并将 table 更新为 1 或 -1 以及如何 "update" 初始值的空行
Sending SQL a boolean and update a table as 1 or -1 and how to "update" an empty row for the initial values
我有一个 Songs
table 和一个 likes
列,其中包含用户发送的点赞数。每个用户通过添加到 likes
列的 C# 应用程序发送一个布尔值(1 或 0)。
关于我的程序:
我想知道是否有更高效、更简短的方法来编写函数的第 1 部分?
我必须第一次手动插入“0”而不是 NULL
才能使该功能正常工作。它不起作用,因为 Likes
列的初始值为 NULL
。有没有什么办法可以在第一次有 NULL 的时候影响该行?
对于带有 [Users_Likes_Songs]
table 的函数的第 2 部分,如果用户发送了一个赞 (true = 1) 或删除了它 (false = 0),我想更新).
当用户 'like' 的行完全为空时,我如何第一次更新此 table?
如果你能帮助我,我非常感谢。
程序:
CREATE PROCEDURE Songs_Likes
@User_ID INT,
@SongID INT,
@Song_like BIT
AS
BEGIN
--- part 1 of the function
IF (@Song_like = 1)
BEGIN
UPDATE [Songs]
SET [Likes] = [Likes] + @Song_like
WHERE [Song_ID] = @SongID
END
IF (@Song_like = 0)
BEGIN
UPDATE [Songs]
SET [Likes] = [Likes] - 1
WHERE [Song_ID] = @SongID
END
--- part 2 of the function with the second table
UPDATE [Users_Likes_Songs]
SET [LikeSong] = @Song_like
WHERE ([UserID] = @User_ID) AND ([SongID] = @SongID)
END
您可以在您的程序中尝试这个查询
UPDATE [songs]
SET [likes] = Isnull ([likes], 0) + ( CASE WHEN @Song_like THEN 1 ELSE -1 END)
WHERE [song_id] = @SongID
对于 1) 这更清晰、更短且更有效。
UPDATE [Songs]
SET [Likes] = COALESCE([Likes], 0) + CASE WHEN @Song_like = 1 THEN 1
WHEN @Song_like = 0 THEN -1
ELSE 0 END
WHERE [Song_ID] = @SongID;
对于第二部分,您可以这样做:
IF NOT EXISTS (SELECT 1
FROM [Users_Likes_Songs]
WHERE [UserID] = @User_ID
AND [SongID] = @SongID)
INSERT INTO [Users_Likes_Songs] (User_ID, SongID, [LikeSong])
VALUES (@User_ID, @SongID, @Song_like)
ELSE
UPDATE [Users_Likes_Songs]
SET [LikeSong] = @Song_like WHERE ([UserID] = @User_ID) AND ([SongID] = @SongID)
我认为更好的方法是更改您的设计以计算点赞数,并使用 table 为每个用户存储点赞数。简单来说,类似于:
USE Sandbox;
GO
CREATE SCHEMA music;
GO
CREATE TABLE music.song (SongID int IDENTITY(1,1),
Artist nvarchar(50) NOT NULL,
Title nvarchar(50) NOT NULL,
ReleaseDate date);
CREATE TABLE music.[User] (UserID int IDENTITY(1,1),
[Login] nvarchar(128));
CREATE TABLE music.SongLike (LikeID bigint IDENTITY(1,1),
SongID int,
UserID int,
Liked bit);
CREATE UNIQUE NONCLUSTERED INDEX UserLike ON music.SongLike(SongID, UserID); --Stops multiple likes
GO
--To add a LIKE you can then have a SP like:
CREATE PROC music.AddLike @SongID int, @UserID int, @Liked bit AS
BEGIN
IF EXISTS (SELECT 1 FROM music.SongLike WHERE UserID = @UserID AND SongID = @SongID) BEGIN
UPDATE music.SongLike
SET Liked = @Liked
WHERE UserID = @UserID
AND SongID = @SongID
END ELSE BEGIN
INSERT INTO music.SongLike (SongID,
UserID,
Liked)
VALUES (@SongID, @UserID, @Liked);
END
END
GO
--And, if you want the number of likes:
CREATE VIEW music.SongLikes AS
SELECT S.Artist,
S.Title,
S.ReleaseDate,
COUNT(CASE SL.Liked WHEN 1 THEN 1 END) AS Likes
FROM music.Song S
JOIN music.SongLike SL ON S.SongID = SL.SongID
GROUP BY S.Artist,
S.Title,
S.ReleaseDate;
GO
我有一个 Songs
table 和一个 likes
列,其中包含用户发送的点赞数。每个用户通过添加到 likes
列的 C# 应用程序发送一个布尔值(1 或 0)。
关于我的程序:
我想知道是否有更高效、更简短的方法来编写函数的第 1 部分?
我必须第一次手动插入“0”而不是NULL
才能使该功能正常工作。它不起作用,因为Likes
列的初始值为NULL
。有没有什么办法可以在第一次有 NULL 的时候影响该行?对于带有
[Users_Likes_Songs]
table 的函数的第 2 部分,如果用户发送了一个赞 (true = 1) 或删除了它 (false = 0),我想更新).当用户 'like' 的行完全为空时,我如何第一次更新此 table?
如果你能帮助我,我非常感谢。
程序:
CREATE PROCEDURE Songs_Likes
@User_ID INT,
@SongID INT,
@Song_like BIT
AS
BEGIN
--- part 1 of the function
IF (@Song_like = 1)
BEGIN
UPDATE [Songs]
SET [Likes] = [Likes] + @Song_like
WHERE [Song_ID] = @SongID
END
IF (@Song_like = 0)
BEGIN
UPDATE [Songs]
SET [Likes] = [Likes] - 1
WHERE [Song_ID] = @SongID
END
--- part 2 of the function with the second table
UPDATE [Users_Likes_Songs]
SET [LikeSong] = @Song_like
WHERE ([UserID] = @User_ID) AND ([SongID] = @SongID)
END
您可以在您的程序中尝试这个查询
UPDATE [songs]
SET [likes] = Isnull ([likes], 0) + ( CASE WHEN @Song_like THEN 1 ELSE -1 END)
WHERE [song_id] = @SongID
对于 1) 这更清晰、更短且更有效。
UPDATE [Songs]
SET [Likes] = COALESCE([Likes], 0) + CASE WHEN @Song_like = 1 THEN 1
WHEN @Song_like = 0 THEN -1
ELSE 0 END
WHERE [Song_ID] = @SongID;
对于第二部分,您可以这样做:
IF NOT EXISTS (SELECT 1
FROM [Users_Likes_Songs]
WHERE [UserID] = @User_ID
AND [SongID] = @SongID)
INSERT INTO [Users_Likes_Songs] (User_ID, SongID, [LikeSong])
VALUES (@User_ID, @SongID, @Song_like)
ELSE
UPDATE [Users_Likes_Songs]
SET [LikeSong] = @Song_like WHERE ([UserID] = @User_ID) AND ([SongID] = @SongID)
我认为更好的方法是更改您的设计以计算点赞数,并使用 table 为每个用户存储点赞数。简单来说,类似于:
USE Sandbox;
GO
CREATE SCHEMA music;
GO
CREATE TABLE music.song (SongID int IDENTITY(1,1),
Artist nvarchar(50) NOT NULL,
Title nvarchar(50) NOT NULL,
ReleaseDate date);
CREATE TABLE music.[User] (UserID int IDENTITY(1,1),
[Login] nvarchar(128));
CREATE TABLE music.SongLike (LikeID bigint IDENTITY(1,1),
SongID int,
UserID int,
Liked bit);
CREATE UNIQUE NONCLUSTERED INDEX UserLike ON music.SongLike(SongID, UserID); --Stops multiple likes
GO
--To add a LIKE you can then have a SP like:
CREATE PROC music.AddLike @SongID int, @UserID int, @Liked bit AS
BEGIN
IF EXISTS (SELECT 1 FROM music.SongLike WHERE UserID = @UserID AND SongID = @SongID) BEGIN
UPDATE music.SongLike
SET Liked = @Liked
WHERE UserID = @UserID
AND SongID = @SongID
END ELSE BEGIN
INSERT INTO music.SongLike (SongID,
UserID,
Liked)
VALUES (@SongID, @UserID, @Liked);
END
END
GO
--And, if you want the number of likes:
CREATE VIEW music.SongLikes AS
SELECT S.Artist,
S.Title,
S.ReleaseDate,
COUNT(CASE SL.Liked WHEN 1 THEN 1 END) AS Likes
FROM music.Song S
JOIN music.SongLike SL ON S.SongID = SL.SongID
GROUP BY S.Artist,
S.Title,
S.ReleaseDate;
GO