向SQL发送布尔值并将表更新为1或-1,以及如何“更新”初始值的空行

向SQL发送布尔值并将表更新为1或-1,以及如何“更新”初始值的空行,sql,sql-server,sql-server-2008,if-statement,boolean,Sql,Sql Server,Sql Server 2008,If Statement,Boolean,我有一个带有likes列的Songs表,其中包含发送的likes用户数。每个用户通过一个C应用程序发送一个布尔值1或0,该应用程序将添加到likes列 关于我的程序: CREATE PROCEDURE Songs_Likes @User_ID INT, @SongID INT, @Song_like BIT AS BEGIN --- part 1 of the function IF (@Song_like = 1) BEGIN U

我有一个带有likes列的Songs表,其中包含发送的likes用户数。每个用户通过一个C应用程序发送一个布尔值1或0,该应用程序将添加到likes列

关于我的程序:

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
我想知道是否有更有效、更简短的方法来编写函数的第1部分? 我第一次必须手动插入“0”而不是空值,函数才能工作。它不起作用,因为Likes列的初始值为NULL。当行中有空值时,是否有方法第一次影响该行

对于带有[Users\u Likes\u Songs]表的函数的第2部分,我想更新用户是否发送like true=1或删除它false=0

当用户“like”的值必须为“1”时,当其行完全为空时,我如何第一次更新此表

如果你能帮助我,我非常感谢你

程序如下:

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 

您可以在过程中尝试此查询

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)

对于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)

我认为更好的方法是改变你的设计来计算喜好,并有一个表来存储每个用户的喜好。简单地说,类似于:

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

我认为更好的方法是改变你的设计来计算喜好,并有一个表来存储每个用户的喜好。简单地说,类似于:

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


为什么需要在歌曲表中存储喜欢的数量?您总是可以从Users_Likes_Songs表中计算它。对于您的注释B,为什么不将Likes的默认值设置为0,而不是NULL?然而,理想情况下,我会实际计算喜欢的数字作为计算值。存储在表中很容易以错误的值结束;特别是在比赛条件方面。@HoneyBadger,这是个好主意,但对于演示项目,我必须插入没有实际用户的“假”喜欢。@sup.DR我想说,没有用户,即使是演示,你也不能有喜欢。如果你需要演示,创建假用户,让他们喜欢和不喜欢歌曲。为什么你需要在歌曲表中存储喜欢的数量?您总是可以从Users_Likes_Songs表中计算它。对于您的注释B,为什么不将Likes的默认值设置为0,而不是NULL?然而,理想情况下,我会实际计算喜欢的数字作为计算值。存储在表中很容易以错误的值结束;特别是在比赛条件方面。@HoneyBadger,这是个好主意,但对于演示项目,我必须插入没有实际用户的“假”喜欢。@sup.DR我想说,没有用户,即使是演示,你也不能有喜欢。如果您需要演示,请创建假用户,让他们喜欢或不喜欢歌曲。您的代码中有一个勘误表:ESLE->ELSE。另外,COALESCE比ISNULL更为推荐,因为ANSII标准在您的代码中有一个勘误表:ESLE->ELSE。另外,COALESCE比ISNULL更受推荐,因为ANSII标准更新了我的问题的第二部分,你能看一下吗?我想知道你的我是否正确理解你的答案。谢谢你,只需要用更少的as编辑你的答案-从[Users\u Likes\u Songs]中选择1,其中[UserID]=@User\u ID和[SongID]=@SongID啊,是的。。。有一些令人困惑的地方,还有一个地方不见了。在我的回复中已修复,以供将来参考。谢谢分享!!!我更新了问题的第二部分,你能看一下吗?我想知道你的我是否正确理解你的答案。谢谢你,只需要用更少的as编辑你的答案-从[Users\u Likes\u Songs]中选择1,其中[UserID]=@User\u ID和[SongID]=@SongID啊,是的。。。有一些令人困惑的地方,还有一个地方不见了。在我的回复中已修复,以供将来参考。谢谢分享!!!我会为引用songID的SongsLikes表添加一个约束FK。这只是最基本的。我不会为OP做所有的工作:我会为SongsLikes表添加一个约束FK来引用songID。它需要几个索引和约束,@Sami。这只是最基本的。我没有为OP做所有的工作: